s3-spoolss: fix spoolss GetPrinterData behaviour
[Samba.git] / source3 / rpc_server / srv_spoolss_nt.c
blob262f4a38e2859a5b3163576a39bee84dbd33561e
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"
44 /* macros stolen from s4 spoolss server */
45 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
46 ((info)?ndr_size_##fn(info, level, 0):0)
48 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
49 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
51 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
52 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
54 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
56 #undef DBGC_CLASS
57 #define DBGC_CLASS DBGC_RPC_SRV
59 static Printer_entry *printers_list;
61 typedef struct _counter_printer_0 {
62 struct _counter_printer_0 *next;
63 struct _counter_printer_0 *prev;
65 int snum;
66 uint32_t counter;
67 } counter_printer_0;
69 static counter_printer_0 *counter_list;
71 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
72 static uint32_t smb_connections = 0;
75 /* Map generic permissions to printer object specific permissions */
77 const struct standard_mapping printer_std_mapping = {
78 PRINTER_READ,
79 PRINTER_WRITE,
80 PRINTER_EXECUTE,
81 PRINTER_ALL_ACCESS
84 /* Map generic permissions to print server object specific permissions */
86 const struct standard_mapping printserver_std_mapping = {
87 SERVER_READ,
88 SERVER_WRITE,
89 SERVER_EXECUTE,
90 SERVER_ALL_ACCESS
93 /* API table for Xcv Monitor functions */
95 struct xcv_api_table {
96 const char *name;
97 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
100 static void prune_printername_cache(void);
102 /********************************************************************
103 * Canonicalize servername.
104 ********************************************************************/
106 static const char *canon_servername(const char *servername)
108 const char *pservername = servername;
109 while (*pservername == '\\') {
110 pservername++;
112 return pservername;
115 /* translate between internal status numbers and NT status numbers */
116 static int nt_printj_status(int v)
118 switch (v) {
119 case LPQ_QUEUED:
120 return 0;
121 case LPQ_PAUSED:
122 return JOB_STATUS_PAUSED;
123 case LPQ_SPOOLING:
124 return JOB_STATUS_SPOOLING;
125 case LPQ_PRINTING:
126 return JOB_STATUS_PRINTING;
127 case LPQ_ERROR:
128 return JOB_STATUS_ERROR;
129 case LPQ_DELETING:
130 return JOB_STATUS_DELETING;
131 case LPQ_OFFLINE:
132 return JOB_STATUS_OFFLINE;
133 case LPQ_PAPEROUT:
134 return JOB_STATUS_PAPEROUT;
135 case LPQ_PRINTED:
136 return JOB_STATUS_PRINTED;
137 case LPQ_DELETED:
138 return JOB_STATUS_DELETED;
139 case LPQ_BLOCKED:
140 return JOB_STATUS_BLOCKED_DEVQ;
141 case LPQ_USER_INTERVENTION:
142 return JOB_STATUS_USER_INTERVENTION;
144 return 0;
147 static int nt_printq_status(int v)
149 switch (v) {
150 case LPQ_PAUSED:
151 return PRINTER_STATUS_PAUSED;
152 case LPQ_QUEUED:
153 case LPQ_SPOOLING:
154 case LPQ_PRINTING:
155 return 0;
157 return 0;
160 /***************************************************************************
161 Disconnect from the client
162 ****************************************************************************/
164 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
166 WERROR result;
167 NTSTATUS status;
170 * Tell the specific printing tdb we no longer want messages for this printer
171 * by deregistering our PID.
174 if (!print_notify_deregister_pid(snum))
175 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
177 /* weird if the test succeds !!! */
178 if (smb_connections==0) {
179 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
180 return;
183 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
184 handle,
185 &result);
186 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
187 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
188 win_errstr(result)));
190 /* if it's the last connection, deconnect the IPC$ share */
191 if (smb_connections==1) {
193 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
194 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
196 messaging_deregister(smbd_messaging_context(),
197 MSG_PRINTER_NOTIFY2, NULL);
199 /* Tell the connections db we're no longer interested in
200 * printer notify messages. */
202 serverid_register_msg_flags(
203 messaging_server_id(smbd_messaging_context()),
204 false, FLAG_MSG_PRINT_NOTIFY);
207 smb_connections--;
210 /****************************************************************************
211 Functions to free a printer entry datastruct.
212 ****************************************************************************/
214 static int printer_entry_destructor(Printer_entry *Printer)
216 if (Printer->notify.client_connected == true) {
217 int snum = -1;
219 if ( Printer->printer_type == SPLHND_SERVER) {
220 snum = -1;
221 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
222 } else if (Printer->printer_type == SPLHND_PRINTER) {
223 snum = print_queue_snum(Printer->sharename);
224 if (snum != -1)
225 srv_spoolss_replycloseprinter(snum,
226 &Printer->notify.client_hnd);
230 Printer->notify.flags=0;
231 Printer->notify.options=0;
232 Printer->notify.localmachine[0]='\0';
233 Printer->notify.printerlocal=0;
234 TALLOC_FREE(Printer->notify.option);
235 Printer->notify.client_connected = false;
237 TALLOC_FREE(Printer->devmode);
239 /* Remove from the internal list. */
240 DLIST_REMOVE(printers_list, Printer);
241 return 0;
244 /****************************************************************************
245 find printer index by handle
246 ****************************************************************************/
248 static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
249 struct policy_handle *hnd)
251 Printer_entry *find_printer = NULL;
253 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
254 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
255 return NULL;
258 return find_printer;
261 /****************************************************************************
262 Close printer index by handle.
263 ****************************************************************************/
265 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
267 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
269 if (!Printer) {
270 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
271 OUR_HANDLE(hnd)));
272 return false;
275 close_policy_hnd(p, hnd);
277 return true;
280 /****************************************************************************
281 Delete a printer given a handle.
282 ****************************************************************************/
284 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
286 char *cmd = lp_deleteprinter_cmd();
287 char *command = NULL;
288 int ret;
289 SE_PRIV se_printop = SE_PRINT_OPERATOR;
290 bool is_print_op = false;
292 /* can't fail if we don't try */
294 if ( !*cmd )
295 return WERR_OK;
297 command = talloc_asprintf(ctx,
298 "%s \"%s\"",
299 cmd, sharename);
300 if (!command) {
301 return WERR_NOMEM;
303 if ( token )
304 is_print_op = user_has_privileges( token, &se_printop );
306 DEBUG(10,("Running [%s]\n", command));
308 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
310 if ( is_print_op )
311 become_root();
313 if ( (ret = smbrun(command, NULL)) == 0 ) {
314 /* Tell everyone we updated smb.conf. */
315 message_send_all(smbd_messaging_context(),
316 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
319 if ( is_print_op )
320 unbecome_root();
322 /********** END SePrintOperatorPrivlege BLOCK **********/
324 DEBUGADD(10,("returned [%d]\n", ret));
326 TALLOC_FREE(command);
328 if (ret != 0)
329 return WERR_BADFID; /* What to return here? */
331 /* go ahead and re-read the services immediately */
332 become_root();
333 reload_services(false);
334 unbecome_root();
336 if ( lp_servicenumber( sharename ) >= 0 )
337 return WERR_ACCESS_DENIED;
339 return WERR_OK;
342 /****************************************************************************
343 Delete a printer given a handle.
344 ****************************************************************************/
346 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
348 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
349 WERROR result;
351 if (!Printer) {
352 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
353 OUR_HANDLE(hnd)));
354 return WERR_BADFID;
358 * It turns out that Windows allows delete printer on a handle
359 * opened by an admin user, then used on a pipe handle created
360 * by an anonymous user..... but they're working on security.... riiight !
361 * JRA.
364 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
365 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
366 return WERR_ACCESS_DENIED;
369 /* this does not need a become root since the access check has been
370 done on the handle already */
372 result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
373 Printer->sharename, "");
374 if (!W_ERROR_IS_OK(result)) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376 return WERR_BADFID;
379 result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
380 Printer->sharename );
381 if (!W_ERROR_IS_OK(result)) {
382 return result;
384 prune_printername_cache();
385 return WERR_OK;
388 /****************************************************************************
389 Return the snum of a printer corresponding to an handle.
390 ****************************************************************************/
392 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
393 int *number, struct share_params **params)
395 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
397 if (!Printer) {
398 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
399 OUR_HANDLE(hnd)));
400 return false;
403 switch (Printer->printer_type) {
404 case SPLHND_PRINTER:
405 DEBUG(4,("short name:%s\n", Printer->sharename));
406 *number = print_queue_snum(Printer->sharename);
407 return (*number != -1);
408 case SPLHND_SERVER:
409 return false;
410 default:
411 return false;
415 /****************************************************************************
416 Set printer handle type.
417 Check if it's \\server or \\server\printer
418 ****************************************************************************/
420 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
422 DEBUG(3,("Setting printer type=%s\n", handlename));
424 /* it's a print server */
425 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
426 DEBUGADD(4,("Printer is a print server\n"));
427 Printer->printer_type = SPLHND_SERVER;
429 /* it's a printer (set_printer_hnd_name() will handle port monitors */
430 else {
431 DEBUGADD(4,("Printer is a printer\n"));
432 Printer->printer_type = SPLHND_PRINTER;
435 return true;
438 static void prune_printername_cache_fn(const char *key, const char *value,
439 time_t timeout, void *private_data)
441 gencache_del(key);
444 static void prune_printername_cache(void)
446 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
449 /****************************************************************************
450 Set printer handle name.. Accept names like \\server, \\server\printer,
451 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
452 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
453 XcvDataPort() interface.
454 ****************************************************************************/
456 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
457 struct auth_serversupplied_info *server_info,
458 Printer_entry *Printer,
459 const char *handlename)
461 int snum;
462 int n_services=lp_numservices();
463 char *aprinter;
464 const char *printername;
465 const char *servername = NULL;
466 fstring sname;
467 bool found = false;
468 struct spoolss_PrinterInfo2 *info2 = NULL;
469 WERROR result;
472 * Hopefully nobody names his printers like this. Maybe \ or ,
473 * are illegal in printer names even?
475 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
476 char *cache_key;
477 char *tmp;
479 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
480 (unsigned long)strlen(handlename)));
482 aprinter = CONST_DISCARD(char *, handlename);
483 if ( *handlename == '\\' ) {
484 servername = canon_servername(handlename);
485 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
486 *aprinter = '\0';
487 aprinter++;
489 if (!is_myname_or_ipaddr(servername)) {
490 return false;
493 fstrcpy(Printer->servername, servername);
496 if (Printer->printer_type == SPLHND_SERVER) {
497 return true;
500 if (Printer->printer_type != SPLHND_PRINTER) {
501 return false;
504 DEBUGADD(5, ("searching for [%s]\n", aprinter));
506 /* check for the Port Monitor Interface */
507 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
508 Printer->printer_type = SPLHND_PORTMON_TCP;
509 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
510 found = true;
512 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
513 Printer->printer_type = SPLHND_PORTMON_LOCAL;
514 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
515 found = true;
519 * With hundreds of printers, the "for" loop iterating all
520 * shares can be quite expensive, as it is done on every
521 * OpenPrinter. The loop maps "aprinter" to "sname", the
522 * result of which we cache in gencache.
525 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
526 aprinter);
527 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
529 found = (strcmp(tmp, printer_not_found) != 0);
530 if (!found) {
531 DEBUG(4, ("Printer %s not found\n", aprinter));
532 SAFE_FREE(tmp);
533 return false;
535 fstrcpy(sname, tmp);
536 SAFE_FREE(tmp);
539 /* Search all sharenames first as this is easier than pulling
540 the printer_info_2 off of disk. Don't use find_service() since
541 that calls out to map_username() */
543 /* do another loop to look for printernames */
544 for (snum = 0; !found && snum < n_services; snum++) {
545 const char *printer = lp_const_servicename(snum);
547 /* no point going on if this is not a printer */
548 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
549 continue;
552 /* ignore [printers] share */
553 if (strequal(printer, "printers")) {
554 continue;
557 fstrcpy(sname, printer);
558 if (strequal(aprinter, printer)) {
559 found = true;
560 break;
563 /* no point looking up the printer object if
564 we aren't allowing printername != sharename */
565 if (lp_force_printername(snum)) {
566 continue;
569 result = winreg_get_printer(mem_ctx,
570 server_info,
571 servername,
572 sname,
573 &info2);
574 if ( !W_ERROR_IS_OK(result) ) {
575 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
576 sname, win_errstr(result)));
577 continue;
580 printername = strrchr(info2->printername, '\\');
581 if (printername == NULL) {
582 printername = info2->printername;
583 } else {
584 printername++;
587 if (strequal(printername, aprinter)) {
588 found = true;
589 break;
592 DEBUGADD(10, ("printername: %s\n", printername));
594 TALLOC_FREE(info2);
597 if ( !found ) {
598 if (cache_key != NULL) {
599 gencache_set(cache_key, printer_not_found,
600 time(NULL)+300);
601 TALLOC_FREE(cache_key);
603 DEBUGADD(4,("Printer not found\n"));
604 return false;
607 if (cache_key != NULL) {
608 gencache_set(cache_key, sname, time(NULL)+300);
609 TALLOC_FREE(cache_key);
612 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
614 fstrcpy(Printer->sharename, sname);
616 return true;
619 /****************************************************************************
620 Find first available printer slot. creates a printer handle for you.
621 ****************************************************************************/
623 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
624 const char *name, uint32_t access_granted)
626 Printer_entry *new_printer;
628 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
630 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
631 if (new_printer == NULL) {
632 return false;
634 talloc_set_destructor(new_printer, printer_entry_destructor);
636 if (!create_policy_hnd(p, hnd, new_printer)) {
637 TALLOC_FREE(new_printer);
638 return false;
641 /* Add to the internal list. */
642 DLIST_ADD(printers_list, new_printer);
644 new_printer->notify.option=NULL;
646 if (!set_printer_hnd_printertype(new_printer, name)) {
647 close_printer_handle(p, hnd);
648 return false;
651 if (!set_printer_hnd_name(p->mem_ctx, p->server_info, new_printer, name)) {
652 close_printer_handle(p, hnd);
653 return false;
656 new_printer->access_granted = access_granted;
658 DEBUG(5, ("%d printer handles active\n",
659 (int)num_pipe_handles(p)));
661 return true;
664 /***************************************************************************
665 check to see if the client motify handle is monitoring the notification
666 given by (notify_type, notify_field).
667 **************************************************************************/
669 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
670 uint16_t notify_field)
672 return true;
675 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
676 uint16_t notify_field)
678 struct spoolss_NotifyOption *option = p->notify.option;
679 uint32_t i, j;
682 * Flags should always be zero when the change notify
683 * is registered by the client's spooler. A user Win32 app
684 * might use the flags though instead of the NOTIFY_OPTION_INFO
685 * --jerry
688 if (!option) {
689 return false;
692 if (p->notify.flags)
693 return is_monitoring_event_flags(
694 p->notify.flags, notify_type, notify_field);
696 for (i = 0; i < option->count; i++) {
698 /* Check match for notify_type */
700 if (option->types[i].type != notify_type)
701 continue;
703 /* Check match for field */
705 for (j = 0; j < option->types[i].count; j++) {
706 if (option->types[i].fields[j].field == notify_field) {
707 return true;
712 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
713 p->servername, p->sharename, notify_type, notify_field));
715 return false;
718 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
719 _data->data.integer[0] = _integer; \
720 _data->data.integer[1] = 0;
723 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
724 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
725 if (!_data->data.string.string) {\
726 _data->data.string.size = 0; \
728 _data->data.string.size = strlen_m_term(_p) * 2;
730 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
731 _data->data.devmode.devmode = _devmode;
733 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
734 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
735 if (!_data->data.sd.sd) { \
736 _data->data.sd.sd_size = 0; \
738 _data->data.sd.sd_size = \
739 ndr_size_security_descriptor(_data->data.sd.sd, 0);
741 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
742 struct tm *t,
743 const char **pp,
744 uint32_t *plen)
746 struct spoolss_Time st;
747 uint32_t len = 16;
748 char *p;
750 if (!init_systemtime(&st, t)) {
751 return;
754 p = talloc_array(mem_ctx, char, len);
755 if (!p) {
756 return;
760 * Systemtime must be linearized as a set of UINT16's.
761 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
764 SSVAL(p, 0, st.year);
765 SSVAL(p, 2, st.month);
766 SSVAL(p, 4, st.day_of_week);
767 SSVAL(p, 6, st.day);
768 SSVAL(p, 8, st.hour);
769 SSVAL(p, 10, st.minute);
770 SSVAL(p, 12, st.second);
771 SSVAL(p, 14, st.millisecond);
773 *pp = p;
774 *plen = len;
777 /* Convert a notification message to a struct spoolss_Notify */
779 static void notify_one_value(struct spoolss_notify_msg *msg,
780 struct spoolss_Notify *data,
781 TALLOC_CTX *mem_ctx)
783 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
786 static void notify_string(struct spoolss_notify_msg *msg,
787 struct spoolss_Notify *data,
788 TALLOC_CTX *mem_ctx)
790 /* The length of the message includes the trailing \0 */
792 data->data.string.size = msg->len * 2;
793 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
794 if (!data->data.string.string) {
795 data->data.string.size = 0;
796 return;
800 static void notify_system_time(struct spoolss_notify_msg *msg,
801 struct spoolss_Notify *data,
802 TALLOC_CTX *mem_ctx)
804 data->data.string.string = NULL;
805 data->data.string.size = 0;
807 if (msg->len != sizeof(time_t)) {
808 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
809 msg->len));
810 return;
813 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
814 &data->data.string.string,
815 &data->data.string.size);
818 struct notify2_message_table {
819 const char *name;
820 void (*fn)(struct spoolss_notify_msg *msg,
821 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
824 static struct notify2_message_table printer_notify_table[] = {
825 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
826 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
827 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
828 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
829 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
830 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
831 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
832 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
833 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
834 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
835 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
836 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
837 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
838 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
839 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
840 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
841 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
842 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
843 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
846 static struct notify2_message_table job_notify_table[] = {
847 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
848 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
849 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
850 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
851 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
852 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
853 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
854 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
855 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
856 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
857 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
858 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
859 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
860 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
861 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
862 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
863 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
864 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
865 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
866 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
867 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
868 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
869 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
870 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
874 /***********************************************************************
875 Allocate talloc context for container object
876 **********************************************************************/
878 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
880 if ( !ctr )
881 return;
883 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
885 return;
888 /***********************************************************************
889 release all allocated memory and zero out structure
890 **********************************************************************/
892 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
894 if ( !ctr )
895 return;
897 if ( ctr->ctx )
898 talloc_destroy(ctr->ctx);
900 ZERO_STRUCTP(ctr);
902 return;
905 /***********************************************************************
906 **********************************************************************/
908 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
910 if ( !ctr )
911 return NULL;
913 return ctr->ctx;
916 /***********************************************************************
917 **********************************************************************/
919 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
921 if ( !ctr || !ctr->msg_groups )
922 return NULL;
924 if ( idx >= ctr->num_groups )
925 return NULL;
927 return &ctr->msg_groups[idx];
931 /***********************************************************************
932 How many groups of change messages do we have ?
933 **********************************************************************/
935 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
937 if ( !ctr )
938 return 0;
940 return ctr->num_groups;
943 /***********************************************************************
944 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
945 **********************************************************************/
947 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
949 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
950 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
951 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
952 int i, new_slot;
954 if ( !ctr || !msg )
955 return 0;
957 /* loop over all groups looking for a matching printer name */
959 for ( i=0; i<ctr->num_groups; i++ ) {
960 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
961 break;
964 /* add a new group? */
966 if ( i == ctr->num_groups ) {
967 ctr->num_groups++;
969 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
970 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
971 return 0;
973 ctr->msg_groups = groups;
975 /* clear the new entry and set the printer name */
977 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
978 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
981 /* add the change messages; 'i' is the correct index now regardless */
983 msg_grp = &ctr->msg_groups[i];
985 msg_grp->num_msgs++;
987 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
988 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
989 return 0;
991 msg_grp->msgs = msg_list;
993 new_slot = msg_grp->num_msgs-1;
994 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
996 /* need to allocate own copy of data */
998 if ( msg->len != 0 )
999 msg_grp->msgs[new_slot].notify.data = (char *)
1000 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1002 return ctr->num_groups;
1005 static void construct_info_data(struct spoolss_Notify *info_data,
1006 enum spoolss_NotifyType type,
1007 uint16_t field, int id);
1009 /***********************************************************************
1010 Send a change notication message on all handles which have a call
1011 back registered
1012 **********************************************************************/
1014 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1016 Printer_entry *p;
1017 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1018 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1019 SPOOLSS_NOTIFY_MSG *messages;
1020 int sending_msg_count;
1022 if ( !msg_group ) {
1023 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1024 return;
1027 messages = msg_group->msgs;
1029 if ( !messages ) {
1030 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
1031 return;
1034 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1036 /* loop over all printers */
1038 for (p = printers_list; p; p = p->next) {
1039 struct spoolss_Notify *notifies;
1040 uint32_t count = 0;
1041 uint32_t id;
1042 int i;
1044 /* Is there notification on this handle? */
1046 if ( !p->notify.client_connected )
1047 continue;
1049 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1051 /* For this printer? Print servers always receive
1052 notifications. */
1054 if ( ( p->printer_type == SPLHND_PRINTER ) &&
1055 ( !strequal(msg_group->printername, p->sharename) ) )
1056 continue;
1058 DEBUG(10,("Our printer\n"));
1060 /* allocate the max entries possible */
1062 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1063 if (!notifies) {
1064 return;
1067 /* build the array of change notifications */
1069 sending_msg_count = 0;
1071 for ( i=0; i<msg_group->num_msgs; i++ ) {
1072 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1074 /* Are we monitoring this event? */
1076 if (!is_monitoring_event(p, msg->type, msg->field))
1077 continue;
1079 sending_msg_count++;
1082 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1083 msg->type, msg->field, p->sharename));
1086 * if the is a printer notification handle and not a job notification
1087 * type, then set the id to 0. Other wise just use what was specified
1088 * in the message.
1090 * When registering change notification on a print server handle
1091 * we always need to send back the id (snum) matching the printer
1092 * for which the change took place. For change notify registered
1093 * on a printer handle, this does not matter and the id should be 0.
1095 * --jerry
1098 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1099 id = 0;
1100 else
1101 id = msg->id;
1104 /* Convert unix jobid to smb jobid */
1106 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1107 id = sysjob_to_jobid(msg->id);
1109 if (id == -1) {
1110 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1111 goto done;
1115 construct_info_data( &notifies[count], msg->type, msg->field, id );
1117 switch(msg->type) {
1118 case PRINTER_NOTIFY_TYPE:
1119 if ( printer_notify_table[msg->field].fn )
1120 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1121 break;
1123 case JOB_NOTIFY_TYPE:
1124 if ( job_notify_table[msg->field].fn )
1125 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1126 break;
1128 default:
1129 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1130 goto done;
1133 count++;
1136 if ( sending_msg_count ) {
1137 NTSTATUS status;
1138 WERROR werr;
1139 union spoolss_ReplyPrinterInfo info;
1140 struct spoolss_NotifyInfo info0;
1141 uint32_t reply_result;
1143 info0.version = 0x2;
1144 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1145 info0.count = count;
1146 info0.notifies = notifies;
1148 info.info0 = &info0;
1150 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1151 &p->notify.client_hnd,
1152 p->notify.change, /* color */
1153 p->notify.flags,
1154 &reply_result,
1155 0, /* reply_type, must be 0 */
1156 info,
1157 &werr);
1158 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1159 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1160 notify_cli_pipe->srv_name_slash,
1161 win_errstr(werr)));
1163 switch (reply_result) {
1164 case 0:
1165 break;
1166 case PRINTER_NOTIFY_INFO_DISCARDED:
1167 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1168 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1169 break;
1170 default:
1171 break;
1176 done:
1177 DEBUG(8,("send_notify2_changes: Exit...\n"));
1178 return;
1181 /***********************************************************************
1182 **********************************************************************/
1184 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1187 uint32_t tv_sec, tv_usec;
1188 size_t offset = 0;
1190 /* Unpack message */
1192 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1193 msg->printer);
1195 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1196 &tv_sec, &tv_usec,
1197 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1199 if (msg->len == 0)
1200 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1201 &msg->notify.value[0], &msg->notify.value[1]);
1202 else
1203 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1204 &msg->len, &msg->notify.data);
1206 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1207 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1209 tv->tv_sec = tv_sec;
1210 tv->tv_usec = tv_usec;
1212 if (msg->len == 0)
1213 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1214 msg->notify.value[1]));
1215 else
1216 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1218 return true;
1221 /********************************************************************
1222 Receive a notify2 message list
1223 ********************************************************************/
1225 static void receive_notify2_message_list(struct messaging_context *msg,
1226 void *private_data,
1227 uint32_t msg_type,
1228 struct server_id server_id,
1229 DATA_BLOB *data)
1231 size_t msg_count, i;
1232 char *buf = (char *)data->data;
1233 char *msg_ptr;
1234 size_t msg_len;
1235 SPOOLSS_NOTIFY_MSG notify;
1236 SPOOLSS_NOTIFY_MSG_CTR messages;
1237 int num_groups;
1239 if (data->length < 4) {
1240 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1241 return;
1244 msg_count = IVAL(buf, 0);
1245 msg_ptr = buf + 4;
1247 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1249 if (msg_count == 0) {
1250 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1251 return;
1254 /* initialize the container */
1256 ZERO_STRUCT( messages );
1257 notify_msg_ctr_init( &messages );
1260 * build message groups for each printer identified
1261 * in a change_notify msg. Remember that a PCN message
1262 * includes the handle returned for the srv_spoolss_replyopenprinter()
1263 * call. Therefore messages are grouped according to printer handle.
1266 for ( i=0; i<msg_count; i++ ) {
1267 struct timeval msg_tv;
1269 if (msg_ptr + 4 - buf > data->length) {
1270 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1271 return;
1274 msg_len = IVAL(msg_ptr,0);
1275 msg_ptr += 4;
1277 if (msg_ptr + msg_len - buf > data->length) {
1278 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1279 return;
1282 /* unpack messages */
1284 ZERO_STRUCT( notify );
1285 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1286 msg_ptr += msg_len;
1288 /* add to correct list in container */
1290 notify_msg_ctr_addmsg( &messages, &notify );
1292 /* free memory that might have been allocated by notify2_unpack_msg() */
1294 if ( notify.len != 0 )
1295 SAFE_FREE( notify.notify.data );
1298 /* process each group of messages */
1300 num_groups = notify_msg_ctr_numgroups( &messages );
1301 for ( i=0; i<num_groups; i++ )
1302 send_notify2_changes( &messages, i );
1305 /* cleanup */
1307 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1308 (uint32_t)msg_count ));
1310 notify_msg_ctr_destroy( &messages );
1312 return;
1315 /********************************************************************
1316 Send a message to ourself about new driver being installed
1317 so we can upgrade the information for each printer bound to this
1318 driver
1319 ********************************************************************/
1321 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1323 int len = strlen(drivername);
1325 if (!len)
1326 return false;
1328 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1329 drivername));
1331 messaging_send_buf(smbd_messaging_context(),
1332 messaging_server_id(smbd_messaging_context()),
1333 MSG_PRINTER_DRVUPGRADE,
1334 (uint8_t *)drivername, len+1);
1336 return true;
1339 /**********************************************************************
1340 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1341 over all printers, upgrading ones as necessary
1342 **********************************************************************/
1344 void do_drv_upgrade_printer(struct messaging_context *msg,
1345 void *private_data,
1346 uint32_t msg_type,
1347 struct server_id server_id,
1348 DATA_BLOB *data)
1350 TALLOC_CTX *tmp_ctx;
1351 struct auth_serversupplied_info *server_info = NULL;
1352 struct spoolss_PrinterInfo2 *pinfo2;
1353 NTSTATUS status;
1354 WERROR result;
1355 const char *drivername;
1356 int snum;
1357 int n_services = lp_numservices();
1358 size_t len;
1360 tmp_ctx = talloc_new(NULL);
1361 if (!tmp_ctx) return;
1363 status = make_server_info_system(tmp_ctx, &server_info);
1364 if (!NT_STATUS_IS_OK(status)) {
1365 DEBUG(0, ("do_drv_upgrade_printer: "
1366 "Could not create system server_info\n"));
1367 goto done;
1370 len = MIN(data->length,sizeof(drivername)-1);
1371 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1372 if (!drivername) {
1373 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1374 goto done;
1377 DEBUG(10, ("do_drv_upgrade_printer: "
1378 "Got message for new driver [%s]\n", drivername));
1380 /* Iterate the printer list */
1382 for (snum = 0; snum < n_services; snum++) {
1383 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1384 continue;
1387 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1388 lp_const_servicename(snum),
1389 &pinfo2);
1391 if (!W_ERROR_IS_OK(result)) {
1392 continue;
1395 if (!pinfo2->drivername) {
1396 continue;
1399 if (strcmp(drivername, pinfo2->drivername) != 0) {
1400 continue;
1403 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1405 /* all we care about currently is the change_id */
1406 result = winreg_printer_update_changeid(tmp_ctx,
1407 server_info,
1408 pinfo2->printername);
1410 if (!W_ERROR_IS_OK(result)) {
1411 DEBUG(3, ("do_drv_upgrade_printer: "
1412 "Failed to update changeid [%s]\n",
1413 win_errstr(result)));
1417 /* all done */
1418 done:
1419 talloc_free(tmp_ctx);
1422 /********************************************************************
1423 Update the cache for all printq's with a registered client
1424 connection
1425 ********************************************************************/
1427 void update_monitored_printq_cache( void )
1429 Printer_entry *printer = printers_list;
1430 int snum;
1432 /* loop through all printers and update the cache where
1433 client_connected == true */
1434 while ( printer )
1436 if ( (printer->printer_type == SPLHND_PRINTER)
1437 && printer->notify.client_connected )
1439 snum = print_queue_snum(printer->sharename);
1440 print_queue_status( snum, NULL, NULL );
1443 printer = printer->next;
1446 return;
1449 /****************************************************************
1450 _spoolss_OpenPrinter
1451 ****************************************************************/
1453 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1454 struct spoolss_OpenPrinter *r)
1456 struct spoolss_OpenPrinterEx e;
1457 WERROR werr;
1459 ZERO_STRUCT(e.in.userlevel);
1461 e.in.printername = r->in.printername;
1462 e.in.datatype = r->in.datatype;
1463 e.in.devmode_ctr = r->in.devmode_ctr;
1464 e.in.access_mask = r->in.access_mask;
1465 e.in.level = 0;
1467 e.out.handle = r->out.handle;
1469 werr = _spoolss_OpenPrinterEx(p, &e);
1471 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1472 /* OpenPrinterEx returns this for a bad
1473 * printer name. We must return WERR_INVALID_PRINTER_NAME
1474 * instead.
1476 werr = WERR_INVALID_PRINTER_NAME;
1479 return werr;
1482 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1483 struct spoolss_DeviceMode *orig,
1484 struct spoolss_DeviceMode **dest)
1486 struct spoolss_DeviceMode *dm;
1488 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1489 if (!dm) {
1490 return WERR_NOMEM;
1493 /* copy all values, then duplicate strings and structs */
1494 *dm = *orig;
1496 dm->devicename = talloc_strdup(dm, orig->devicename);
1497 if (!dm->devicename) {
1498 return WERR_NOMEM;
1500 dm->formname = talloc_strdup(dm, orig->formname);
1501 if (!dm->formname) {
1502 return WERR_NOMEM;
1504 if (orig->driverextra_data.data) {
1505 dm->driverextra_data.data =
1506 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1507 orig->driverextra_data.length);
1508 if (!dm->driverextra_data.data) {
1509 return WERR_NOMEM;
1513 *dest = dm;
1514 return WERR_OK;
1517 /****************************************************************
1518 _spoolss_OpenPrinterEx
1519 ****************************************************************/
1521 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1522 struct spoolss_OpenPrinterEx *r)
1524 int snum;
1525 Printer_entry *Printer=NULL;
1527 if (!r->in.printername) {
1528 return WERR_INVALID_PARAM;
1531 /* some sanity check because you can open a printer or a print server */
1532 /* aka: \\server\printer or \\server */
1534 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1536 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1537 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1538 "for printer %s\n", r->in.printername));
1539 ZERO_STRUCTP(r->out.handle);
1540 return WERR_INVALID_PARAM;
1543 Printer = find_printer_index_by_hnd(p, r->out.handle);
1544 if ( !Printer ) {
1545 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1546 "handle we created for printer %s\n", r->in.printername));
1547 close_printer_handle(p, r->out.handle);
1548 ZERO_STRUCTP(r->out.handle);
1549 return WERR_INVALID_PARAM;
1553 * First case: the user is opening the print server:
1555 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1556 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1558 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1559 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1560 * or if the user is listed in the smb.conf printer admin parameter.
1562 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1563 * client view printer folder, but does not show the MSAPW.
1565 * Note: this test needs code to check access rights here too. Jeremy
1566 * could you look at this?
1568 * Second case: the user is opening a printer:
1569 * NT doesn't let us connect to a printer if the connecting user
1570 * doesn't have print permission.
1572 * Third case: user is opening a Port Monitor
1573 * access checks same as opening a handle to the print server.
1576 switch (Printer->printer_type )
1578 case SPLHND_SERVER:
1579 case SPLHND_PORTMON_TCP:
1580 case SPLHND_PORTMON_LOCAL:
1581 /* Printserver handles use global struct... */
1583 snum = -1;
1585 /* Map standard access rights to object specific access rights */
1587 se_map_standard(&r->in.access_mask,
1588 &printserver_std_mapping);
1590 /* Deny any object specific bits that don't apply to print
1591 servers (i.e printer and job specific bits) */
1593 r->in.access_mask &= SEC_MASK_SPECIFIC;
1595 if (r->in.access_mask &
1596 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1597 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1598 close_printer_handle(p, r->out.handle);
1599 ZERO_STRUCTP(r->out.handle);
1600 return WERR_ACCESS_DENIED;
1603 /* Allow admin access */
1605 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1607 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1609 if (!lp_ms_add_printer_wizard()) {
1610 close_printer_handle(p, r->out.handle);
1611 ZERO_STRUCTP(r->out.handle);
1612 return WERR_ACCESS_DENIED;
1615 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1616 and not a printer admin, then fail */
1618 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1619 !user_has_privileges(p->server_info->ptok,
1620 &se_printop ) &&
1621 !token_contains_name_in_list(
1622 uidtoname(p->server_info->utok.uid),
1623 p->server_info->info3->base.domain.string,
1624 NULL,
1625 p->server_info->ptok,
1626 lp_printer_admin(snum))) {
1627 close_printer_handle(p, r->out.handle);
1628 ZERO_STRUCTP(r->out.handle);
1629 return WERR_ACCESS_DENIED;
1632 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1634 else
1636 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1639 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1640 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1642 /* We fall through to return WERR_OK */
1643 break;
1645 case SPLHND_PRINTER:
1646 /* NT doesn't let us connect to a printer if the connecting user
1647 doesn't have print permission. */
1649 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1650 close_printer_handle(p, r->out.handle);
1651 ZERO_STRUCTP(r->out.handle);
1652 return WERR_BADFID;
1655 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1656 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1659 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1661 /* map an empty access mask to the minimum access mask */
1662 if (r->in.access_mask == 0x0)
1663 r->in.access_mask = PRINTER_ACCESS_USE;
1666 * If we are not serving the printer driver for this printer,
1667 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1668 * will keep NT clients happy --jerry
1671 if (lp_use_client_driver(snum)
1672 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1674 r->in.access_mask = PRINTER_ACCESS_USE;
1677 /* check smb.conf parameters and the the sec_desc */
1679 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1680 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1681 ZERO_STRUCTP(r->out.handle);
1682 return WERR_ACCESS_DENIED;
1685 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1686 p->server_info->ptok, snum) ||
1687 !print_access_check(p->server_info, snum,
1688 r->in.access_mask)) {
1689 DEBUG(3, ("access DENIED for printer open\n"));
1690 close_printer_handle(p, r->out.handle);
1691 ZERO_STRUCTP(r->out.handle);
1692 return WERR_ACCESS_DENIED;
1695 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1696 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1697 close_printer_handle(p, r->out.handle);
1698 ZERO_STRUCTP(r->out.handle);
1699 return WERR_ACCESS_DENIED;
1702 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1703 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1704 else
1705 r->in.access_mask = PRINTER_ACCESS_USE;
1707 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1708 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1710 winreg_create_printer(p->mem_ctx,
1711 p->server_info,
1712 Printer->servername,
1713 lp_const_servicename(snum));
1715 break;
1717 default:
1718 /* sanity check to prevent programmer error */
1719 ZERO_STRUCTP(r->out.handle);
1720 return WERR_BADFID;
1723 Printer->access_granted = r->in.access_mask;
1726 * If the client sent a devmode in the OpenPrinter() call, then
1727 * save it here in case we get a job submission on this handle
1730 if ((Printer->printer_type != SPLHND_SERVER) &&
1731 r->in.devmode_ctr.devmode) {
1732 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1733 &Printer->devmode);
1736 #if 0 /* JERRY -- I'm doubtful this is really effective */
1737 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1738 optimization in Windows 2000 clients --jerry */
1740 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1741 && (RA_WIN2K == get_remote_arch()) )
1743 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1744 sys_usleep( 500000 );
1746 #endif
1748 return WERR_OK;
1751 /****************************************************************
1752 _spoolss_ClosePrinter
1753 ****************************************************************/
1755 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1756 struct spoolss_ClosePrinter *r)
1758 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1760 if (Printer && Printer->document_started) {
1761 struct spoolss_EndDocPrinter e;
1763 e.in.handle = r->in.handle;
1765 _spoolss_EndDocPrinter(p, &e);
1768 if (!close_printer_handle(p, r->in.handle))
1769 return WERR_BADFID;
1771 /* clear the returned printer handle. Observed behavior
1772 from Win2k server. Don't think this really matters.
1773 Previous code just copied the value of the closed
1774 handle. --jerry */
1776 ZERO_STRUCTP(r->out.handle);
1778 return WERR_OK;
1781 /****************************************************************
1782 _spoolss_DeletePrinter
1783 ****************************************************************/
1785 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1786 struct spoolss_DeletePrinter *r)
1788 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1789 WERROR result;
1790 int snum;
1792 if (Printer && Printer->document_started) {
1793 struct spoolss_EndDocPrinter e;
1795 e.in.handle = r->in.handle;
1797 _spoolss_EndDocPrinter(p, &e);
1800 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1801 winreg_delete_printer_key(p->mem_ctx,
1802 p->server_info,
1803 lp_const_servicename(snum),
1804 "");
1807 result = delete_printer_handle(p, r->in.handle);
1809 return result;
1812 /*******************************************************************
1813 * static function to lookup the version id corresponding to an
1814 * long architecture string
1815 ******************************************************************/
1817 static const struct print_architecture_table_node archi_table[]= {
1819 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1820 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1821 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1822 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1823 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1824 {"Windows IA64", SPL_ARCH_IA64, 3 },
1825 {"Windows x64", SPL_ARCH_X64, 3 },
1826 {NULL, "", -1 }
1829 static int get_version_id(const char *arch)
1831 int i;
1833 for (i=0; archi_table[i].long_archi != NULL; i++)
1835 if (strcmp(arch, archi_table[i].long_archi) == 0)
1836 return (archi_table[i].version);
1839 return -1;
1842 /****************************************************************
1843 _spoolss_DeletePrinterDriver
1844 ****************************************************************/
1846 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
1847 struct spoolss_DeletePrinterDriver *r)
1850 struct spoolss_DriverInfo8 *info = NULL;
1851 struct spoolss_DriverInfo8 *info_win2k = NULL;
1852 int version;
1853 WERROR status;
1854 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1856 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1857 and not a printer admin, then fail */
1859 if ( (p->server_info->utok.uid != sec_initial_uid())
1860 && !user_has_privileges(p->server_info->ptok, &se_printop )
1861 && !token_contains_name_in_list(
1862 uidtoname(p->server_info->utok.uid),
1863 p->server_info->info3->base.domain.string,
1864 NULL,
1865 p->server_info->ptok,
1866 lp_printer_admin(-1)) )
1868 return WERR_ACCESS_DENIED;
1871 /* check that we have a valid driver name first */
1873 if ((version = get_version_id(r->in.architecture)) == -1)
1874 return WERR_INVALID_ENVIRONMENT;
1876 status = winreg_get_driver(p->mem_ctx, p->server_info,
1877 r->in.architecture, r->in.driver,
1878 version, &info);
1879 if (!W_ERROR_IS_OK(status)) {
1880 /* try for Win2k driver if "Windows NT x86" */
1882 if ( version == 2 ) {
1883 version = 3;
1885 status = winreg_get_driver(p->mem_ctx, p->server_info,
1886 r->in.architecture,
1887 r->in.driver,
1888 version, &info);
1889 if (!W_ERROR_IS_OK(status)) {
1890 status = WERR_UNKNOWN_PRINTER_DRIVER;
1891 goto done;
1894 /* otherwise it was a failure */
1895 else {
1896 status = WERR_UNKNOWN_PRINTER_DRIVER;
1897 goto done;
1902 if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
1903 status = WERR_PRINTER_DRIVER_IN_USE;
1904 goto done;
1907 if (version == 2) {
1908 status = winreg_get_driver(p->mem_ctx, p->server_info,
1909 r->in.architecture,
1910 r->in.driver, 3, &info_win2k);
1911 if (W_ERROR_IS_OK(status)) {
1912 /* if we get to here, we now have 2 driver info structures to remove */
1913 /* remove the Win2k driver first*/
1915 status = winreg_del_driver(p->mem_ctx,
1916 p->server_info,
1917 info_win2k, 3);
1918 talloc_free(info_win2k);
1920 /* this should not have failed---if it did, report to client */
1921 if (!W_ERROR_IS_OK(status)) {
1922 goto done;
1927 status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
1929 done:
1930 talloc_free(info);
1932 return status;
1935 /****************************************************************
1936 _spoolss_DeletePrinterDriverEx
1937 ****************************************************************/
1939 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
1940 struct spoolss_DeletePrinterDriverEx *r)
1942 struct spoolss_DriverInfo8 *info = NULL;
1943 struct spoolss_DriverInfo8 *info_win2k = NULL;
1944 int version;
1945 bool delete_files;
1946 WERROR status;
1947 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1949 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1950 and not a printer admin, then fail */
1952 if ( (p->server_info->utok.uid != sec_initial_uid())
1953 && !user_has_privileges(p->server_info->ptok, &se_printop )
1954 && !token_contains_name_in_list(
1955 uidtoname(p->server_info->utok.uid),
1956 p->server_info->info3->base.domain.string,
1957 NULL,
1958 p->server_info->ptok, lp_printer_admin(-1)) )
1960 return WERR_ACCESS_DENIED;
1963 /* check that we have a valid driver name first */
1964 if ((version = get_version_id(r->in.architecture)) == -1) {
1965 /* this is what NT returns */
1966 return WERR_INVALID_ENVIRONMENT;
1969 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1970 version = r->in.version;
1972 status = winreg_get_driver(p->mem_ctx, p->server_info,
1973 r->in.architecture, r->in.driver,
1974 version, &info);
1975 if (!W_ERROR_IS_OK(status)) {
1976 status = WERR_UNKNOWN_PRINTER_DRIVER;
1979 * if the client asked for a specific version,
1980 * or this is something other than Windows NT x86,
1981 * then we've failed
1984 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1985 goto done;
1987 /* try for Win2k driver if "Windows NT x86" */
1989 version = 3;
1990 status = winreg_get_driver(info, p->server_info,
1991 r->in.architecture,
1992 r->in.driver,
1993 version, &info);
1994 if (!W_ERROR_IS_OK(status)) {
1995 status = WERR_UNKNOWN_PRINTER_DRIVER;
1996 goto done;
2000 if (printer_driver_in_use(info, p->server_info, info)) {
2001 status = WERR_PRINTER_DRIVER_IN_USE;
2002 goto done;
2006 * we have a couple of cases to consider.
2007 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2008 * then the delete should fail if **any** files overlap with
2009 * other drivers
2010 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2011 * non-overlapping files
2012 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2013 * is set, the do not delete any files
2014 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2017 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2019 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2021 if (delete_files &&
2022 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2023 printer_driver_files_in_use(info, p->server_info, info)) {
2024 /* no idea of the correct error here */
2025 status = WERR_ACCESS_DENIED;
2026 goto done;
2030 /* also check for W32X86/3 if necessary; maybe we already have? */
2032 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2033 status = winreg_get_driver(info, p->server_info,
2034 r->in.architecture,
2035 r->in.driver, 3, &info_win2k);
2036 if (W_ERROR_IS_OK(status)) {
2038 if (delete_files &&
2039 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2040 printer_driver_files_in_use(info, p->server_info,
2041 info_win2k)) {
2042 /* no idea of the correct error here */
2043 talloc_free(info_win2k);
2044 status = WERR_ACCESS_DENIED;
2045 goto done;
2048 /* if we get to here, we now have 2 driver info structures to remove */
2049 /* remove the Win2k driver first*/
2051 status = winreg_del_driver(info, p->server_info,
2052 info_win2k, 3);
2054 /* this should not have failed---if it did, report to client */
2056 if (!W_ERROR_IS_OK(status)) {
2057 goto done;
2061 * now delete any associated files if delete_files is
2062 * true. Even if this part failes, we return succes
2063 * because the driver doesn not exist any more
2065 if (delete_files) {
2066 delete_driver_files(p->server_info,
2067 info_win2k);
2072 status = winreg_del_driver(info, p->server_info, info, version);
2073 if (!W_ERROR_IS_OK(status)) {
2074 goto done;
2078 * now delete any associated files if delete_files is
2079 * true. Even if this part failes, we return succes
2080 * because the driver doesn not exist any more
2082 if (delete_files) {
2083 delete_driver_files(p->server_info, info);
2086 done:
2087 talloc_free(info);
2088 return status;
2092 /********************************************************************
2093 GetPrinterData on a printer server Handle.
2094 ********************************************************************/
2096 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2097 const char *value,
2098 enum winreg_Type *type,
2099 union spoolss_PrinterData *data)
2101 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2103 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2104 *type = REG_DWORD;
2105 data->value = 0x00;
2106 return WERR_OK;
2109 if (!StrCaseCmp(value, "BeepEnabled")) {
2110 *type = REG_DWORD;
2111 data->value = 0x00;
2112 return WERR_OK;
2115 if (!StrCaseCmp(value, "EventLog")) {
2116 *type = REG_DWORD;
2117 /* formally was 0x1b */
2118 data->value = 0x00;
2119 return WERR_OK;
2122 if (!StrCaseCmp(value, "NetPopup")) {
2123 *type = REG_DWORD;
2124 data->value = 0x00;
2125 return WERR_OK;
2128 if (!StrCaseCmp(value, "MajorVersion")) {
2129 *type = REG_DWORD;
2131 /* Windows NT 4.0 seems to not allow uploading of drivers
2132 to a server that reports 0x3 as the MajorVersion.
2133 need to investigate more how Win2k gets around this .
2134 -- jerry */
2136 if (RA_WINNT == get_remote_arch()) {
2137 data->value = 0x02;
2138 } else {
2139 data->value = 0x03;
2142 return WERR_OK;
2145 if (!StrCaseCmp(value, "MinorVersion")) {
2146 *type = REG_DWORD;
2147 data->value = 0x00;
2148 return WERR_OK;
2151 /* REG_BINARY
2152 * uint32_t size = 0x114
2153 * uint32_t major = 5
2154 * uint32_t minor = [0|1]
2155 * uint32_t build = [2195|2600]
2156 * extra unicode string = e.g. "Service Pack 3"
2158 if (!StrCaseCmp(value, "OSVersion")) {
2159 DATA_BLOB blob;
2160 enum ndr_err_code ndr_err;
2161 struct spoolss_OSVersion os;
2163 os.major = 5; /* Windows 2000 == 5.0 */
2164 os.minor = 0;
2165 os.build = 2195; /* build */
2166 os.extra_string = ""; /* leave extra string empty */
2168 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2169 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2170 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2171 return WERR_GENERAL_FAILURE;
2174 *type = REG_BINARY;
2175 data->binary = blob;
2177 return WERR_OK;
2181 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2182 *type = REG_SZ;
2184 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2185 W_ERROR_HAVE_NO_MEMORY(data->string);
2187 return WERR_OK;
2190 if (!StrCaseCmp(value, "Architecture")) {
2191 *type = REG_SZ;
2192 data->string = talloc_strdup(mem_ctx,
2193 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2194 W_ERROR_HAVE_NO_MEMORY(data->string);
2196 return WERR_OK;
2199 if (!StrCaseCmp(value, "DsPresent")) {
2200 *type = REG_DWORD;
2202 /* only show the publish check box if we are a
2203 member of a AD domain */
2205 if (lp_security() == SEC_ADS) {
2206 data->value = 0x01;
2207 } else {
2208 data->value = 0x00;
2210 return WERR_OK;
2213 if (!StrCaseCmp(value, "DNSMachineName")) {
2214 const char *hostname = get_mydnsfullname();
2216 if (!hostname) {
2217 return WERR_BADFILE;
2220 *type = REG_SZ;
2221 data->string = talloc_strdup(mem_ctx, hostname);
2222 W_ERROR_HAVE_NO_MEMORY(data->string);
2224 return WERR_OK;
2227 *type = REG_NONE;
2229 return WERR_INVALID_PARAM;
2232 /****************************************************************
2233 _spoolss_GetPrinterData
2234 ****************************************************************/
2236 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2237 struct spoolss_GetPrinterData *r)
2239 struct spoolss_GetPrinterDataEx r2;
2241 r2.in.handle = r->in.handle;
2242 r2.in.key_name = "PrinterDriverData";
2243 r2.in.value_name = r->in.value_name;
2244 r2.in.offered = r->in.offered;
2245 r2.out.type = r->out.type;
2246 r2.out.data = r->out.data;
2247 r2.out.needed = r->out.needed;
2249 return _spoolss_GetPrinterDataEx(p, &r2);
2252 /*********************************************************
2253 Connect to the client machine.
2254 **********************************************************/
2256 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2257 struct sockaddr_storage *client_ss, const char *remote_machine)
2259 NTSTATUS ret;
2260 struct cli_state *the_cli;
2261 struct sockaddr_storage rm_addr;
2262 char addr[INET6_ADDRSTRLEN];
2264 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2265 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2266 remote_machine));
2267 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2268 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2269 return false;
2271 print_sockaddr(addr, sizeof(addr), &rm_addr);
2272 } else {
2273 rm_addr = *client_ss;
2274 print_sockaddr(addr, sizeof(addr), &rm_addr);
2275 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2276 addr));
2279 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2280 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2281 addr));
2282 return false;
2285 /* setup the connection */
2286 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2287 &rm_addr, 0, "IPC$", "IPC",
2288 "", /* username */
2289 "", /* domain */
2290 "", /* password */
2291 0, lp_client_signing(), NULL );
2293 if ( !NT_STATUS_IS_OK( ret ) ) {
2294 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2295 remote_machine ));
2296 return false;
2299 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2300 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2301 cli_shutdown(the_cli);
2302 return false;
2306 * Ok - we have an anonymous connection to the IPC$ share.
2307 * Now start the NT Domain stuff :-).
2310 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2311 if (!NT_STATUS_IS_OK(ret)) {
2312 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2313 remote_machine, nt_errstr(ret)));
2314 cli_shutdown(the_cli);
2315 return false;
2318 return true;
2321 /***************************************************************************
2322 Connect to the client.
2323 ****************************************************************************/
2325 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2326 uint32_t localprinter, uint32_t type,
2327 struct policy_handle *handle,
2328 struct sockaddr_storage *client_ss)
2330 WERROR result;
2331 NTSTATUS status;
2334 * If it's the first connection, contact the client
2335 * and connect to the IPC$ share anonymously
2337 if (smb_connections==0) {
2338 fstring unix_printer;
2340 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2342 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2343 return false;
2345 messaging_register(smbd_messaging_context(), NULL,
2346 MSG_PRINTER_NOTIFY2,
2347 receive_notify2_message_list);
2348 /* Tell the connections db we're now interested in printer
2349 * notify messages. */
2350 serverid_register_msg_flags(
2351 messaging_server_id(smbd_messaging_context()),
2352 true, FLAG_MSG_PRINT_NOTIFY);
2356 * Tell the specific printing tdb we want messages for this printer
2357 * by registering our PID.
2360 if (!print_notify_register_pid(snum))
2361 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2363 smb_connections++;
2365 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2366 printer,
2367 localprinter,
2368 type,
2370 NULL,
2371 handle,
2372 &result);
2373 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2374 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2375 win_errstr(result)));
2377 return (W_ERROR_IS_OK(result));
2380 /****************************************************************
2381 ****************************************************************/
2383 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2384 const struct spoolss_NotifyOption *r)
2386 struct spoolss_NotifyOption *option;
2387 uint32_t i,k;
2389 if (!r) {
2390 return NULL;
2393 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2394 if (!option) {
2395 return NULL;
2398 *option = *r;
2400 if (!option->count) {
2401 return option;
2404 option->types = talloc_zero_array(option,
2405 struct spoolss_NotifyOptionType, option->count);
2406 if (!option->types) {
2407 talloc_free(option);
2408 return NULL;
2411 for (i=0; i < option->count; i++) {
2412 option->types[i] = r->types[i];
2414 if (option->types[i].count) {
2415 option->types[i].fields = talloc_zero_array(option,
2416 union spoolss_Field, option->types[i].count);
2417 if (!option->types[i].fields) {
2418 talloc_free(option);
2419 return NULL;
2421 for (k=0; k<option->types[i].count; k++) {
2422 option->types[i].fields[k] =
2423 r->types[i].fields[k];
2428 return option;
2431 /****************************************************************
2432 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2434 * before replying OK: status=0 a rpc call is made to the workstation
2435 * asking ReplyOpenPrinter
2437 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2438 * called from api_spoolss_rffpcnex
2439 ****************************************************************/
2441 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2442 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2444 int snum = -1;
2445 struct spoolss_NotifyOption *option = r->in.notify_options;
2446 struct sockaddr_storage client_ss;
2448 /* store the notify value in the printer struct */
2450 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2452 if (!Printer) {
2453 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2454 "Invalid handle (%s:%u:%u).\n",
2455 OUR_HANDLE(r->in.handle)));
2456 return WERR_BADFID;
2459 Printer->notify.flags = r->in.flags;
2460 Printer->notify.options = r->in.options;
2461 Printer->notify.printerlocal = r->in.printer_local;
2463 TALLOC_FREE(Printer->notify.option);
2464 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2466 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2468 /* Connect to the client machine and send a ReplyOpenPrinter */
2470 if ( Printer->printer_type == SPLHND_SERVER)
2471 snum = -1;
2472 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2473 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2474 return WERR_BADFID;
2476 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2477 "client_address is %s\n", p->client_address));
2479 if (!interpret_string_addr(&client_ss, p->client_address,
2480 AI_NUMERICHOST)) {
2481 return WERR_SERVER_UNAVAILABLE;
2484 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2485 Printer->notify.printerlocal, 1,
2486 &Printer->notify.client_hnd, &client_ss))
2487 return WERR_SERVER_UNAVAILABLE;
2489 Printer->notify.client_connected = true;
2491 return WERR_OK;
2494 /*******************************************************************
2495 * fill a notify_info_data with the servername
2496 ********************************************************************/
2498 static void spoolss_notify_server_name(int snum,
2499 struct spoolss_Notify *data,
2500 print_queue_struct *queue,
2501 struct spoolss_PrinterInfo2 *pinfo2,
2502 TALLOC_CTX *mem_ctx)
2504 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2507 /*******************************************************************
2508 * fill a notify_info_data with the printername (not including the servername).
2509 ********************************************************************/
2511 static void spoolss_notify_printer_name(int snum,
2512 struct spoolss_Notify *data,
2513 print_queue_struct *queue,
2514 struct spoolss_PrinterInfo2 *pinfo2,
2515 TALLOC_CTX *mem_ctx)
2517 /* the notify name should not contain the \\server\ part */
2518 const char *p = strrchr(pinfo2->printername, '\\');
2520 if (!p) {
2521 p = pinfo2->printername;
2522 } else {
2523 p++;
2526 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2529 /*******************************************************************
2530 * fill a notify_info_data with the servicename
2531 ********************************************************************/
2533 static void spoolss_notify_share_name(int snum,
2534 struct spoolss_Notify *data,
2535 print_queue_struct *queue,
2536 struct spoolss_PrinterInfo2 *pinfo2,
2537 TALLOC_CTX *mem_ctx)
2539 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2542 /*******************************************************************
2543 * fill a notify_info_data with the port name
2544 ********************************************************************/
2546 static void spoolss_notify_port_name(int snum,
2547 struct spoolss_Notify *data,
2548 print_queue_struct *queue,
2549 struct spoolss_PrinterInfo2 *pinfo2,
2550 TALLOC_CTX *mem_ctx)
2552 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2555 /*******************************************************************
2556 * fill a notify_info_data with the printername
2557 * but it doesn't exist, have to see what to do
2558 ********************************************************************/
2560 static void spoolss_notify_driver_name(int snum,
2561 struct spoolss_Notify *data,
2562 print_queue_struct *queue,
2563 struct spoolss_PrinterInfo2 *pinfo2,
2564 TALLOC_CTX *mem_ctx)
2566 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2569 /*******************************************************************
2570 * fill a notify_info_data with the comment
2571 ********************************************************************/
2573 static void spoolss_notify_comment(int snum,
2574 struct spoolss_Notify *data,
2575 print_queue_struct *queue,
2576 struct spoolss_PrinterInfo2 *pinfo2,
2577 TALLOC_CTX *mem_ctx)
2579 const char *p;
2581 if (*pinfo2->comment == '\0') {
2582 p = lp_comment(snum);
2583 } else {
2584 p = pinfo2->comment;
2587 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2590 /*******************************************************************
2591 * fill a notify_info_data with the comment
2592 * location = "Room 1, floor 2, building 3"
2593 ********************************************************************/
2595 static void spoolss_notify_location(int snum,
2596 struct spoolss_Notify *data,
2597 print_queue_struct *queue,
2598 struct spoolss_PrinterInfo2 *pinfo2,
2599 TALLOC_CTX *mem_ctx)
2601 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2604 /*******************************************************************
2605 * fill a notify_info_data with the device mode
2606 * jfm:xxxx don't to it for know but that's a real problem !!!
2607 ********************************************************************/
2609 static void spoolss_notify_devmode(int snum,
2610 struct spoolss_Notify *data,
2611 print_queue_struct *queue,
2612 struct spoolss_PrinterInfo2 *pinfo2,
2613 TALLOC_CTX *mem_ctx)
2615 /* for a dummy implementation we have to zero the fields */
2616 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2619 /*******************************************************************
2620 * fill a notify_info_data with the separator file name
2621 ********************************************************************/
2623 static void spoolss_notify_sepfile(int snum,
2624 struct spoolss_Notify *data,
2625 print_queue_struct *queue,
2626 struct spoolss_PrinterInfo2 *pinfo2,
2627 TALLOC_CTX *mem_ctx)
2629 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2632 /*******************************************************************
2633 * fill a notify_info_data with the print processor
2634 * jfm:xxxx return always winprint to indicate we don't do anything to it
2635 ********************************************************************/
2637 static void spoolss_notify_print_processor(int snum,
2638 struct spoolss_Notify *data,
2639 print_queue_struct *queue,
2640 struct spoolss_PrinterInfo2 *pinfo2,
2641 TALLOC_CTX *mem_ctx)
2643 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2646 /*******************************************************************
2647 * fill a notify_info_data with the print processor options
2648 * jfm:xxxx send an empty string
2649 ********************************************************************/
2651 static void spoolss_notify_parameters(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, pinfo2->parameters);
2660 /*******************************************************************
2661 * fill a notify_info_data with the data type
2662 * jfm:xxxx always send RAW as data type
2663 ********************************************************************/
2665 static void spoolss_notify_datatype(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->datatype);
2674 /*******************************************************************
2675 * fill a notify_info_data with the security descriptor
2676 * jfm:xxxx send an null pointer to say no security desc
2677 * have to implement security before !
2678 ********************************************************************/
2680 static void spoolss_notify_security_desc(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_SECDESC(data, pinfo2->secdesc);
2689 /*******************************************************************
2690 * fill a notify_info_data with the attributes
2691 * jfm:xxxx a samba printer is always shared
2692 ********************************************************************/
2694 static void spoolss_notify_attributes(int snum,
2695 struct spoolss_Notify *data,
2696 print_queue_struct *queue,
2697 struct spoolss_PrinterInfo2 *pinfo2,
2698 TALLOC_CTX *mem_ctx)
2700 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2703 /*******************************************************************
2704 * fill a notify_info_data with the priority
2705 ********************************************************************/
2707 static void spoolss_notify_priority(int snum,
2708 struct spoolss_Notify *data,
2709 print_queue_struct *queue,
2710 struct spoolss_PrinterInfo2 *pinfo2,
2711 TALLOC_CTX *mem_ctx)
2713 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2716 /*******************************************************************
2717 * fill a notify_info_data with the default priority
2718 ********************************************************************/
2720 static void spoolss_notify_default_priority(int snum,
2721 struct spoolss_Notify *data,
2722 print_queue_struct *queue,
2723 struct spoolss_PrinterInfo2 *pinfo2,
2724 TALLOC_CTX *mem_ctx)
2726 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2729 /*******************************************************************
2730 * fill a notify_info_data with the start time
2731 ********************************************************************/
2733 static void spoolss_notify_start_time(int snum,
2734 struct spoolss_Notify *data,
2735 print_queue_struct *queue,
2736 struct spoolss_PrinterInfo2 *pinfo2,
2737 TALLOC_CTX *mem_ctx)
2739 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2742 /*******************************************************************
2743 * fill a notify_info_data with the until time
2744 ********************************************************************/
2746 static void spoolss_notify_until_time(int snum,
2747 struct spoolss_Notify *data,
2748 print_queue_struct *queue,
2749 struct spoolss_PrinterInfo2 *pinfo2,
2750 TALLOC_CTX *mem_ctx)
2752 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2755 /*******************************************************************
2756 * fill a notify_info_data with the status
2757 ********************************************************************/
2759 static void spoolss_notify_status(int snum,
2760 struct spoolss_Notify *data,
2761 print_queue_struct *queue,
2762 struct spoolss_PrinterInfo2 *pinfo2,
2763 TALLOC_CTX *mem_ctx)
2765 print_status_struct status;
2767 print_queue_length(snum, &status);
2768 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2771 /*******************************************************************
2772 * fill a notify_info_data with the number of jobs queued
2773 ********************************************************************/
2775 static void spoolss_notify_cjobs(int snum,
2776 struct spoolss_Notify *data,
2777 print_queue_struct *queue,
2778 struct spoolss_PrinterInfo2 *pinfo2,
2779 TALLOC_CTX *mem_ctx)
2781 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2784 /*******************************************************************
2785 * fill a notify_info_data with the average ppm
2786 ********************************************************************/
2788 static void spoolss_notify_average_ppm(int snum,
2789 struct spoolss_Notify *data,
2790 print_queue_struct *queue,
2791 struct spoolss_PrinterInfo2 *pinfo2,
2792 TALLOC_CTX *mem_ctx)
2794 /* always respond 8 pages per minutes */
2795 /* a little hard ! */
2796 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2799 /*******************************************************************
2800 * fill a notify_info_data with username
2801 ********************************************************************/
2803 static void spoolss_notify_username(int snum,
2804 struct spoolss_Notify *data,
2805 print_queue_struct *queue,
2806 struct spoolss_PrinterInfo2 *pinfo2,
2807 TALLOC_CTX *mem_ctx)
2809 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2812 /*******************************************************************
2813 * fill a notify_info_data with job status
2814 ********************************************************************/
2816 static void spoolss_notify_job_status(int snum,
2817 struct spoolss_Notify *data,
2818 print_queue_struct *queue,
2819 struct spoolss_PrinterInfo2 *pinfo2,
2820 TALLOC_CTX *mem_ctx)
2822 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2825 /*******************************************************************
2826 * fill a notify_info_data with job name
2827 ********************************************************************/
2829 static void spoolss_notify_job_name(int snum,
2830 struct spoolss_Notify *data,
2831 print_queue_struct *queue,
2832 struct spoolss_PrinterInfo2 *pinfo2,
2833 TALLOC_CTX *mem_ctx)
2835 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2838 /*******************************************************************
2839 * fill a notify_info_data with job status
2840 ********************************************************************/
2842 static void spoolss_notify_job_status_string(int snum,
2843 struct spoolss_Notify *data,
2844 print_queue_struct *queue,
2845 struct spoolss_PrinterInfo2 *pinfo2,
2846 TALLOC_CTX *mem_ctx)
2849 * Now we're returning job status codes we just return a "" here. JRA.
2852 const char *p = "";
2854 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2855 p = "unknown";
2857 switch (queue->status) {
2858 case LPQ_QUEUED:
2859 p = "Queued";
2860 break;
2861 case LPQ_PAUSED:
2862 p = ""; /* NT provides the paused string */
2863 break;
2864 case LPQ_SPOOLING:
2865 p = "Spooling";
2866 break;
2867 case LPQ_PRINTING:
2868 p = "Printing";
2869 break;
2871 #endif /* NO LONGER NEEDED. */
2873 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2876 /*******************************************************************
2877 * fill a notify_info_data with job time
2878 ********************************************************************/
2880 static void spoolss_notify_job_time(int snum,
2881 struct spoolss_Notify *data,
2882 print_queue_struct *queue,
2883 struct spoolss_PrinterInfo2 *pinfo2,
2884 TALLOC_CTX *mem_ctx)
2886 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2889 /*******************************************************************
2890 * fill a notify_info_data with job size
2891 ********************************************************************/
2893 static void spoolss_notify_job_size(int snum,
2894 struct spoolss_Notify *data,
2895 print_queue_struct *queue,
2896 struct spoolss_PrinterInfo2 *pinfo2,
2897 TALLOC_CTX *mem_ctx)
2899 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2902 /*******************************************************************
2903 * fill a notify_info_data with page info
2904 ********************************************************************/
2905 static void spoolss_notify_total_pages(int snum,
2906 struct spoolss_Notify *data,
2907 print_queue_struct *queue,
2908 struct spoolss_PrinterInfo2 *pinfo2,
2909 TALLOC_CTX *mem_ctx)
2911 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2914 /*******************************************************************
2915 * fill a notify_info_data with pages printed info.
2916 ********************************************************************/
2917 static void spoolss_notify_pages_printed(int snum,
2918 struct spoolss_Notify *data,
2919 print_queue_struct *queue,
2920 struct spoolss_PrinterInfo2 *pinfo2,
2921 TALLOC_CTX *mem_ctx)
2923 /* Add code when back-end tracks this */
2924 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2927 /*******************************************************************
2928 Fill a notify_info_data with job position.
2929 ********************************************************************/
2931 static void spoolss_notify_job_position(int snum,
2932 struct spoolss_Notify *data,
2933 print_queue_struct *queue,
2934 struct spoolss_PrinterInfo2 *pinfo2,
2935 TALLOC_CTX *mem_ctx)
2937 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2940 /*******************************************************************
2941 Fill a notify_info_data with submitted time.
2942 ********************************************************************/
2944 static void spoolss_notify_submitted_time(int snum,
2945 struct spoolss_Notify *data,
2946 print_queue_struct *queue,
2947 struct spoolss_PrinterInfo2 *pinfo2,
2948 TALLOC_CTX *mem_ctx)
2950 data->data.string.string = NULL;
2951 data->data.string.size = 0;
2953 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2954 &data->data.string.string,
2955 &data->data.string.size);
2959 struct s_notify_info_data_table
2961 enum spoolss_NotifyType type;
2962 uint16_t field;
2963 const char *name;
2964 enum spoolss_NotifyTable variable_type;
2965 void (*fn) (int snum, struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx);
2971 /* A table describing the various print notification constants and
2972 whether the notification data is a pointer to a variable sized
2973 buffer, a one value uint32_t or a two value uint32_t. */
2975 static const struct s_notify_info_data_table notify_info_data_table[] =
2977 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2978 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2979 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2980 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2981 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2982 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2983 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2984 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2985 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2986 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2987 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2988 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3003 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3004 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3005 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3006 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3007 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3008 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3009 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3010 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3011 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3012 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3013 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3014 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3015 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3016 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3017 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3018 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3019 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3020 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3021 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3022 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3023 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3024 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3025 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3028 /*******************************************************************
3029 Return the variable_type of info_data structure.
3030 ********************************************************************/
3032 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3033 uint16_t field)
3035 int i=0;
3037 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3038 if ( (notify_info_data_table[i].type == type) &&
3039 (notify_info_data_table[i].field == field) ) {
3040 return notify_info_data_table[i].variable_type;
3044 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3046 return 0;
3049 /****************************************************************************
3050 ****************************************************************************/
3052 static bool search_notify(enum spoolss_NotifyType type,
3053 uint16_t field,
3054 int *value)
3056 int i;
3058 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3059 if (notify_info_data_table[i].type == type &&
3060 notify_info_data_table[i].field == field &&
3061 notify_info_data_table[i].fn != NULL) {
3062 *value = i;
3063 return true;
3067 return false;
3070 /****************************************************************************
3071 ****************************************************************************/
3073 static void construct_info_data(struct spoolss_Notify *info_data,
3074 enum spoolss_NotifyType type,
3075 uint16_t field, int id)
3077 info_data->type = type;
3078 info_data->field.field = field;
3079 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3080 info_data->job_id = id;
3083 /*******************************************************************
3085 * fill a notify_info struct with info asked
3087 ********************************************************************/
3089 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3090 struct spoolss_NotifyInfo *info,
3091 struct spoolss_PrinterInfo2 *pinfo2,
3092 int snum,
3093 const struct spoolss_NotifyOptionType *option_type,
3094 uint32_t id,
3095 TALLOC_CTX *mem_ctx)
3097 int field_num,j;
3098 enum spoolss_NotifyType type;
3099 uint16_t field;
3101 struct spoolss_Notify *current_data;
3102 print_queue_struct *queue=NULL;
3104 type = option_type->type;
3106 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3107 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3108 option_type->count, lp_servicename(snum)));
3110 for(field_num=0; field_num < option_type->count; field_num++) {
3111 field = option_type->fields[field_num].field;
3113 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3115 if (!search_notify(type, field, &j) )
3116 continue;
3118 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3119 struct spoolss_Notify,
3120 info->count + 1);
3121 if (info->notifies == NULL) {
3122 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3123 return false;
3126 current_data = &info->notifies[info->count];
3128 construct_info_data(current_data, type, field, id);
3130 DEBUG(10, ("construct_notify_printer_info: "
3131 "calling [%s] snum=%d printername=[%s])\n",
3132 notify_info_data_table[j].name, snum,
3133 pinfo2->printername));
3135 notify_info_data_table[j].fn(snum, current_data, queue,
3136 pinfo2, mem_ctx);
3138 info->count++;
3141 return true;
3144 /*******************************************************************
3146 * fill a notify_info struct with info asked
3148 ********************************************************************/
3150 static bool construct_notify_jobs_info(print_queue_struct *queue,
3151 struct spoolss_NotifyInfo *info,
3152 struct spoolss_PrinterInfo2 *pinfo2,
3153 int snum,
3154 const struct spoolss_NotifyOptionType *option_type,
3155 uint32_t id,
3156 TALLOC_CTX *mem_ctx)
3158 int field_num,j;
3159 enum spoolss_NotifyType type;
3160 uint16_t field;
3161 struct spoolss_Notify *current_data;
3163 DEBUG(4,("construct_notify_jobs_info\n"));
3165 type = option_type->type;
3167 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3168 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3169 option_type->count));
3171 for(field_num=0; field_num<option_type->count; field_num++) {
3172 field = option_type->fields[field_num].field;
3174 if (!search_notify(type, field, &j) )
3175 continue;
3177 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3178 struct spoolss_Notify,
3179 info->count + 1);
3180 if (info->notifies == NULL) {
3181 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3182 return false;
3185 current_data=&(info->notifies[info->count]);
3187 construct_info_data(current_data, type, field, id);
3188 notify_info_data_table[j].fn(snum, current_data, queue,
3189 pinfo2, mem_ctx);
3190 info->count++;
3193 return true;
3197 * JFM: The enumeration is not that simple, it's even non obvious.
3199 * let's take an example: I want to monitor the PRINTER SERVER for
3200 * the printer's name and the number of jobs currently queued.
3201 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3202 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3204 * I have 3 printers on the back of my server.
3206 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3207 * structures.
3208 * Number Data Id
3209 * 1 printer 1 name 1
3210 * 2 printer 1 cjob 1
3211 * 3 printer 2 name 2
3212 * 4 printer 2 cjob 2
3213 * 5 printer 3 name 3
3214 * 6 printer 3 name 3
3216 * that's the print server case, the printer case is even worse.
3219 /*******************************************************************
3221 * enumerate all printers on the printserver
3222 * fill a notify_info struct with info asked
3224 ********************************************************************/
3226 static WERROR printserver_notify_info(struct pipes_struct *p,
3227 struct policy_handle *hnd,
3228 struct spoolss_NotifyInfo *info,
3229 TALLOC_CTX *mem_ctx)
3231 int snum;
3232 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3233 int n_services=lp_numservices();
3234 int i;
3235 struct spoolss_NotifyOption *option;
3236 struct spoolss_NotifyOptionType option_type;
3237 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3238 WERROR result;
3240 DEBUG(4,("printserver_notify_info\n"));
3242 if (!Printer)
3243 return WERR_BADFID;
3245 option = Printer->notify.option;
3247 info->version = 2;
3248 info->notifies = NULL;
3249 info->count = 0;
3251 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3252 sending a ffpcn() request first */
3254 if ( !option )
3255 return WERR_BADFID;
3257 for (i=0; i<option->count; i++) {
3258 option_type = option->types[i];
3260 if (option_type.type != PRINTER_NOTIFY_TYPE)
3261 continue;
3263 for (snum = 0; snum < n_services; snum++) {
3264 if (!lp_browseable(snum) ||
3265 !lp_snum_ok(snum) ||
3266 !lp_print_ok(snum)) {
3267 continue; /* skip */
3270 /* Maybe we should use the SYSTEM server_info here... */
3271 result = winreg_get_printer(mem_ctx, p->server_info,
3272 Printer->servername,
3273 lp_servicename(snum),
3274 &pinfo2);
3275 if (!W_ERROR_IS_OK(result)) {
3276 DEBUG(4, ("printserver_notify_info: "
3277 "Failed to get printer [%s]\n",
3278 lp_servicename(snum)));
3279 continue;
3283 construct_notify_printer_info(Printer, info,
3284 pinfo2, snum,
3285 &option_type, snum,
3286 mem_ctx);
3288 TALLOC_FREE(pinfo2);
3292 #if 0
3294 * Debugging information, don't delete.
3297 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3298 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3299 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3301 for (i=0; i<info->count; i++) {
3302 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3303 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3304 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3306 #endif
3308 return WERR_OK;
3311 /*******************************************************************
3313 * fill a notify_info struct with info asked
3315 ********************************************************************/
3317 static WERROR printer_notify_info(struct pipes_struct *p,
3318 struct policy_handle *hnd,
3319 struct spoolss_NotifyInfo *info,
3320 TALLOC_CTX *mem_ctx)
3322 int snum;
3323 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3324 int i;
3325 uint32_t id;
3326 struct spoolss_NotifyOption *option;
3327 struct spoolss_NotifyOptionType option_type;
3328 int count,j;
3329 print_queue_struct *queue=NULL;
3330 print_status_struct status;
3331 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3332 WERROR result;
3334 DEBUG(4,("printer_notify_info\n"));
3336 if (!Printer)
3337 return WERR_BADFID;
3339 option = Printer->notify.option;
3340 id = 0x0;
3342 info->version = 2;
3343 info->notifies = NULL;
3344 info->count = 0;
3346 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3347 sending a ffpcn() request first */
3349 if ( !option )
3350 return WERR_BADFID;
3352 get_printer_snum(p, hnd, &snum, NULL);
3354 /* Maybe we should use the SYSTEM server_info here... */
3355 result = winreg_get_printer(mem_ctx, p->server_info,
3356 Printer->servername,
3357 lp_servicename(snum), &pinfo2);
3358 if (!W_ERROR_IS_OK(result)) {
3359 return WERR_BADFID;
3362 for (i=0; i<option->count; i++) {
3363 option_type = option->types[i];
3365 switch (option_type.type) {
3366 case PRINTER_NOTIFY_TYPE:
3367 if (construct_notify_printer_info(Printer, info,
3368 pinfo2, snum,
3369 &option_type, id,
3370 mem_ctx)) {
3371 id--;
3373 break;
3375 case JOB_NOTIFY_TYPE:
3377 count = print_queue_status(snum, &queue, &status);
3379 for (j=0; j<count; j++) {
3380 construct_notify_jobs_info(&queue[j], info,
3381 pinfo2, snum,
3382 &option_type,
3383 queue[j].job,
3384 mem_ctx);
3387 SAFE_FREE(queue);
3388 break;
3393 * Debugging information, don't delete.
3396 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3397 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3398 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3400 for (i=0; i<info->count; i++) {
3401 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3402 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3403 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3407 talloc_free(pinfo2);
3408 return WERR_OK;
3411 /****************************************************************
3412 _spoolss_RouterRefreshPrinterChangeNotify
3413 ****************************************************************/
3415 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3416 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3418 struct spoolss_NotifyInfo *info;
3420 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3421 WERROR result = WERR_BADFID;
3423 /* we always have a spoolss_NotifyInfo struct */
3424 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3425 if (!info) {
3426 result = WERR_NOMEM;
3427 goto done;
3430 *r->out.info = info;
3432 if (!Printer) {
3433 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3434 "Invalid handle (%s:%u:%u).\n",
3435 OUR_HANDLE(r->in.handle)));
3436 goto done;
3439 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3442 * We are now using the change value, and
3443 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3444 * I don't have a global notification system, I'm sending back all the
3445 * informations even when _NOTHING_ has changed.
3448 /* We need to keep track of the change value to send back in
3449 RRPCN replies otherwise our updates are ignored. */
3451 Printer->notify.fnpcn = true;
3453 if (Printer->notify.client_connected) {
3454 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3455 "Saving change value in request [%x]\n",
3456 r->in.change_low));
3457 Printer->notify.change = r->in.change_low;
3460 /* just ignore the spoolss_NotifyOption */
3462 switch (Printer->printer_type) {
3463 case SPLHND_SERVER:
3464 result = printserver_notify_info(p, r->in.handle,
3465 info, p->mem_ctx);
3466 break;
3468 case SPLHND_PRINTER:
3469 result = printer_notify_info(p, r->in.handle,
3470 info, p->mem_ctx);
3471 break;
3474 Printer->notify.fnpcn = false;
3476 done:
3477 return result;
3480 /********************************************************************
3481 * construct_printer_info_0
3482 * fill a printer_info_0 struct
3483 ********************************************************************/
3485 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3486 struct auth_serversupplied_info *server_info,
3487 struct spoolss_PrinterInfo2 *info2,
3488 struct spoolss_PrinterInfo0 *r,
3489 int snum)
3491 int count;
3492 counter_printer_0 *session_counter;
3493 struct timeval setuptime;
3494 print_status_struct status;
3496 r->printername = talloc_strdup(mem_ctx, info2->printername);
3497 W_ERROR_HAVE_NO_MEMORY(r->printername);
3499 r->servername = talloc_strdup(mem_ctx, info2->servername);
3500 W_ERROR_HAVE_NO_MEMORY(r->servername);
3502 count = print_queue_length(snum, &status);
3504 /* check if we already have a counter for this printer */
3505 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3506 if (session_counter->snum == snum)
3507 break;
3510 /* it's the first time, add it to the list */
3511 if (session_counter == NULL) {
3512 session_counter = SMB_MALLOC_P(counter_printer_0);
3513 W_ERROR_HAVE_NO_MEMORY(session_counter);
3514 ZERO_STRUCTP(session_counter);
3515 session_counter->snum = snum;
3516 session_counter->counter = 0;
3517 DLIST_ADD(counter_list, session_counter);
3520 /* increment it */
3521 session_counter->counter++;
3523 r->cjobs = count;
3524 r->total_jobs = 0;
3525 r->total_bytes = 0;
3527 get_startup_time(&setuptime);
3528 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3530 /* JFM:
3531 * the global_counter should be stored in a TDB as it's common to all the clients
3532 * and should be zeroed on samba startup
3534 r->global_counter = session_counter->counter;
3535 r->total_pages = 0;
3536 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3537 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3538 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3539 r->free_build = SPOOLSS_RELEASE_BUILD;
3540 r->spooling = 0;
3541 r->max_spooling = 0;
3542 r->session_counter = session_counter->counter;
3543 r->num_error_out_of_paper = 0x0;
3544 r->num_error_not_ready = 0x0; /* number of print failure */
3545 r->job_error = 0x0;
3546 r->number_of_processors = 0x1;
3547 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3548 r->high_part_total_bytes = 0x0;
3549 winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3550 r->last_error = WERR_OK;
3551 r->status = nt_printq_status(status.status);
3552 r->enumerate_network_printers = 0x0;
3553 r->c_setprinter = 0x0;
3554 r->processor_architecture = 0x0;
3555 r->processor_level = 0x6; /* 6 ???*/
3556 r->ref_ic = 0;
3557 r->reserved2 = 0;
3558 r->reserved3 = 0;
3560 return WERR_OK;
3564 /********************************************************************
3565 * construct_printer_info1
3566 * fill a spoolss_PrinterInfo1 struct
3567 ********************************************************************/
3569 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3570 const struct spoolss_PrinterInfo2 *info2,
3571 uint32_t flags,
3572 struct spoolss_PrinterInfo1 *r,
3573 int snum)
3575 r->flags = flags;
3577 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3578 info2->printername,
3579 info2->drivername,
3580 info2->location);
3581 W_ERROR_HAVE_NO_MEMORY(r->description);
3583 if (info2->comment == NULL || info2->comment[0] == '\0') {
3584 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3585 } else {
3586 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3588 W_ERROR_HAVE_NO_MEMORY(r->comment);
3590 r->name = talloc_strdup(mem_ctx, info2->printername);
3591 W_ERROR_HAVE_NO_MEMORY(r->name);
3593 return WERR_OK;
3596 /********************************************************************
3597 * construct_printer_info2
3598 * fill a spoolss_PrinterInfo2 struct
3599 ********************************************************************/
3601 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3602 const struct spoolss_PrinterInfo2 *info2,
3603 struct spoolss_PrinterInfo2 *r,
3604 int snum)
3606 int count;
3607 print_status_struct status;
3609 count = print_queue_length(snum, &status);
3611 r->servername = talloc_strdup(mem_ctx, info2->servername);
3612 W_ERROR_HAVE_NO_MEMORY(r->servername);
3613 r->printername = talloc_strdup(mem_ctx, info2->printername);
3614 W_ERROR_HAVE_NO_MEMORY(r->printername);
3615 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3616 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3617 r->portname = talloc_strdup(mem_ctx, info2->portname);
3618 W_ERROR_HAVE_NO_MEMORY(r->portname);
3619 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3620 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3622 if (info2->comment[0] == '\0') {
3623 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3624 } else {
3625 r->comment = talloc_strdup(mem_ctx, info2->comment);
3627 W_ERROR_HAVE_NO_MEMORY(r->comment);
3629 r->location = talloc_strdup(mem_ctx, info2->location);
3630 W_ERROR_HAVE_NO_MEMORY(r->location);
3631 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3632 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3633 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3634 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3635 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3636 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3637 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3638 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3640 r->attributes = info2->attributes;
3642 r->priority = info2->priority;
3643 r->defaultpriority = info2->defaultpriority;
3644 r->starttime = info2->starttime;
3645 r->untiltime = info2->untiltime;
3646 r->status = nt_printq_status(status.status);
3647 r->cjobs = count;
3648 r->averageppm = info2->averageppm;
3650 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3651 if (!r->devmode) {
3652 DEBUG(8,("Returning NULL Devicemode!\n"));
3655 r->secdesc = NULL;
3657 if (info2->secdesc != NULL) {
3658 /* don't use talloc_steal() here unless you do a deep steal of all
3659 the SEC_DESC members */
3661 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3664 return WERR_OK;
3667 /********************************************************************
3668 * construct_printer_info3
3669 * fill a spoolss_PrinterInfo3 struct
3670 ********************************************************************/
3672 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3673 const struct spoolss_PrinterInfo2 *info2,
3674 struct spoolss_PrinterInfo3 *r,
3675 int snum)
3677 /* These are the components of the SD we are returning. */
3679 if (info2->secdesc != NULL) {
3680 /* don't use talloc_steal() here unless you do a deep steal of all
3681 the SEC_DESC members */
3683 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3684 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3687 return WERR_OK;
3690 /********************************************************************
3691 * construct_printer_info4
3692 * fill a spoolss_PrinterInfo4 struct
3693 ********************************************************************/
3695 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3696 const struct spoolss_PrinterInfo2 *info2,
3697 struct spoolss_PrinterInfo4 *r,
3698 int snum)
3700 r->printername = talloc_strdup(mem_ctx, info2->printername);
3701 W_ERROR_HAVE_NO_MEMORY(r->printername);
3702 r->servername = talloc_strdup(mem_ctx, info2->servername);
3703 W_ERROR_HAVE_NO_MEMORY(r->servername);
3705 r->attributes = info2->attributes;
3707 return WERR_OK;
3710 /********************************************************************
3711 * construct_printer_info5
3712 * fill a spoolss_PrinterInfo5 struct
3713 ********************************************************************/
3715 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3716 const struct spoolss_PrinterInfo2 *info2,
3717 struct spoolss_PrinterInfo5 *r,
3718 int snum)
3720 r->printername = talloc_strdup(mem_ctx, info2->printername);
3721 W_ERROR_HAVE_NO_MEMORY(r->printername);
3722 r->portname = talloc_strdup(mem_ctx, info2->portname);
3723 W_ERROR_HAVE_NO_MEMORY(r->portname);
3725 r->attributes = info2->attributes;
3727 /* these two are not used by NT+ according to MSDN */
3728 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3729 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3731 return WERR_OK;
3734 /********************************************************************
3735 * construct_printer_info_6
3736 * fill a spoolss_PrinterInfo6 struct
3737 ********************************************************************/
3739 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3740 const struct spoolss_PrinterInfo2 *info2,
3741 struct spoolss_PrinterInfo6 *r,
3742 int snum)
3744 int count;
3745 print_status_struct status;
3747 count = print_queue_length(snum, &status);
3749 r->status = nt_printq_status(status.status);
3751 return WERR_OK;
3754 /********************************************************************
3755 * construct_printer_info7
3756 * fill a spoolss_PrinterInfo7 struct
3757 ********************************************************************/
3759 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3760 Printer_entry *print_hnd,
3761 struct spoolss_PrinterInfo7 *r,
3762 int snum)
3764 struct auth_serversupplied_info *server_info;
3765 struct GUID guid;
3766 NTSTATUS status;
3768 status = make_server_info_system(mem_ctx, &server_info);
3769 if (!NT_STATUS_IS_OK(status)) {
3770 DEBUG(0, ("construct_printer_info7: "
3771 "Could not create system server_info\n"));
3772 return WERR_NOMEM;
3775 if (is_printer_published(mem_ctx, server_info, print_hnd->servername,
3776 lp_servicename(snum), &guid, NULL)) {
3777 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3778 r->action = DSPRINT_PUBLISH;
3779 } else {
3780 r->guid = talloc_strdup(mem_ctx, "");
3781 r->action = DSPRINT_UNPUBLISH;
3783 W_ERROR_HAVE_NO_MEMORY(r->guid);
3785 TALLOC_FREE(server_info);
3786 return WERR_OK;
3789 /********************************************************************
3790 * construct_printer_info8
3791 * fill a spoolss_PrinterInfo8 struct
3792 ********************************************************************/
3794 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3795 const struct spoolss_PrinterInfo2 *info2,
3796 struct spoolss_DeviceModeInfo *r,
3797 int snum)
3799 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3800 if (!r->devmode) {
3801 DEBUG(8,("Returning NULL Devicemode!\n"));
3804 return WERR_OK;
3808 /********************************************************************
3809 ********************************************************************/
3811 static bool snum_is_shared_printer(int snum)
3813 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3816 /********************************************************************
3817 Spoolss_enumprinters.
3818 ********************************************************************/
3820 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3821 struct auth_serversupplied_info *server_info,
3822 uint32_t level,
3823 uint32_t flags,
3824 union spoolss_PrinterInfo **info_p,
3825 uint32_t *count_p)
3827 int snum;
3828 int n_services = lp_numservices();
3829 union spoolss_PrinterInfo *info = NULL;
3830 uint32_t count = 0;
3831 WERROR result = WERR_OK;
3833 *count_p = 0;
3834 *info_p = NULL;
3836 for (snum = 0; snum < n_services; snum++) {
3838 const char *printer;
3839 struct spoolss_PrinterInfo2 *info2;
3841 if (!snum_is_shared_printer(snum)) {
3842 continue;
3845 printer = lp_const_servicename(snum);
3847 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3848 printer, snum));
3850 result = winreg_create_printer(mem_ctx,
3851 server_info,
3852 NULL,
3853 printer);
3854 if (!W_ERROR_IS_OK(result)) {
3855 goto out;
3858 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3859 union spoolss_PrinterInfo,
3860 count + 1);
3861 if (!info) {
3862 result = WERR_NOMEM;
3863 goto out;
3866 result = winreg_get_printer(mem_ctx, server_info,
3867 NULL, printer, &info2);
3868 if (!W_ERROR_IS_OK(result)) {
3869 goto out;
3872 switch (level) {
3873 case 0:
3874 result = construct_printer_info0(info, server_info, info2,
3875 &info[count].info0, snum);
3876 break;
3877 case 1:
3878 result = construct_printer_info1(info, info2, flags,
3879 &info[count].info1, snum);
3880 break;
3881 case 2:
3882 result = construct_printer_info2(info, info2,
3883 &info[count].info2, snum);
3884 break;
3885 case 4:
3886 result = construct_printer_info4(info, info2,
3887 &info[count].info4, snum);
3888 break;
3889 case 5:
3890 result = construct_printer_info5(info, info2,
3891 &info[count].info5, snum);
3892 break;
3894 default:
3895 result = WERR_UNKNOWN_LEVEL;
3896 goto out;
3899 if (!W_ERROR_IS_OK(result)) {
3900 goto out;
3903 count++;
3906 *count_p = count;
3907 *info_p = info;
3909 out:
3910 if (!W_ERROR_IS_OK(result)) {
3911 TALLOC_FREE(info);
3912 return result;
3915 *info_p = info;
3917 return WERR_OK;
3920 /********************************************************************
3921 * handle enumeration of printers at level 0
3922 ********************************************************************/
3924 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3925 struct auth_serversupplied_info *server_info,
3926 uint32_t flags,
3927 const char *servername,
3928 union spoolss_PrinterInfo **info,
3929 uint32_t *count)
3931 DEBUG(4,("enum_all_printers_info_0\n"));
3933 return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3937 /********************************************************************
3938 ********************************************************************/
3940 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3941 struct auth_serversupplied_info *server_info,
3942 uint32_t flags,
3943 union spoolss_PrinterInfo **info,
3944 uint32_t *count)
3946 DEBUG(4,("enum_all_printers_info_1\n"));
3948 return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3951 /********************************************************************
3952 enum_all_printers_info_1_local.
3953 *********************************************************************/
3955 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3956 struct auth_serversupplied_info *server_info,
3957 union spoolss_PrinterInfo **info,
3958 uint32_t *count)
3960 DEBUG(4,("enum_all_printers_info_1_local\n"));
3962 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3965 /********************************************************************
3966 enum_all_printers_info_1_name.
3967 *********************************************************************/
3969 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3970 struct auth_serversupplied_info *server_info,
3971 const char *name,
3972 union spoolss_PrinterInfo **info,
3973 uint32_t *count)
3975 const char *s = name;
3977 DEBUG(4,("enum_all_printers_info_1_name\n"));
3979 if ((name[0] == '\\') && (name[1] == '\\')) {
3980 s = name + 2;
3983 if (!is_myname_or_ipaddr(s)) {
3984 return WERR_INVALID_NAME;
3987 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3990 /********************************************************************
3991 enum_all_printers_info_1_network.
3992 *********************************************************************/
3994 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3995 struct auth_serversupplied_info *server_info,
3996 const char *name,
3997 union spoolss_PrinterInfo **info,
3998 uint32_t *count)
4000 const char *s = name;
4002 DEBUG(4,("enum_all_printers_info_1_network\n"));
4004 /* If we respond to a enum_printers level 1 on our name with flags
4005 set to PRINTER_ENUM_REMOTE with a list of printers then these
4006 printers incorrectly appear in the APW browse list.
4007 Specifically the printers for the server appear at the workgroup
4008 level where all the other servers in the domain are
4009 listed. Windows responds to this call with a
4010 WERR_CAN_NOT_COMPLETE so we should do the same. */
4012 if (name[0] == '\\' && name[1] == '\\') {
4013 s = name + 2;
4016 if (is_myname_or_ipaddr(s)) {
4017 return WERR_CAN_NOT_COMPLETE;
4020 return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
4023 /********************************************************************
4024 * api_spoolss_enumprinters
4026 * called from api_spoolss_enumprinters (see this to understand)
4027 ********************************************************************/
4029 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4030 struct auth_serversupplied_info *server_info,
4031 union spoolss_PrinterInfo **info,
4032 uint32_t *count)
4034 DEBUG(4,("enum_all_printers_info_2\n"));
4036 return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
4039 /********************************************************************
4040 * handle enumeration of printers at level 1
4041 ********************************************************************/
4043 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4044 struct auth_serversupplied_info *server_info,
4045 uint32_t flags,
4046 const char *name,
4047 union spoolss_PrinterInfo **info,
4048 uint32_t *count)
4050 /* Not all the flags are equals */
4052 if (flags & PRINTER_ENUM_LOCAL) {
4053 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
4056 if (flags & PRINTER_ENUM_NAME) {
4057 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
4060 if (flags & PRINTER_ENUM_NETWORK) {
4061 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
4064 return WERR_OK; /* NT4sp5 does that */
4067 /********************************************************************
4068 * handle enumeration of printers at level 2
4069 ********************************************************************/
4071 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4072 struct auth_serversupplied_info *server_info,
4073 uint32_t flags,
4074 const char *servername,
4075 union spoolss_PrinterInfo **info,
4076 uint32_t *count)
4078 if (flags & PRINTER_ENUM_LOCAL) {
4079 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4082 if (flags & PRINTER_ENUM_NAME) {
4083 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4084 return WERR_INVALID_NAME;
4087 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
4090 if (flags & PRINTER_ENUM_REMOTE) {
4091 return WERR_UNKNOWN_LEVEL;
4094 return WERR_OK;
4097 /********************************************************************
4098 * handle enumeration of printers at level 4
4099 ********************************************************************/
4101 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4102 struct auth_serversupplied_info *server_info,
4103 uint32_t flags,
4104 const char *servername,
4105 union spoolss_PrinterInfo **info,
4106 uint32_t *count)
4108 DEBUG(4,("enum_all_printers_info_4\n"));
4110 return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4114 /********************************************************************
4115 * handle enumeration of printers at level 5
4116 ********************************************************************/
4118 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4119 struct auth_serversupplied_info *server_info,
4120 uint32_t flags,
4121 const char *servername,
4122 union spoolss_PrinterInfo **info,
4123 uint32_t *count)
4125 DEBUG(4,("enum_all_printers_info_5\n"));
4127 return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4130 /****************************************************************
4131 _spoolss_EnumPrinters
4132 ****************************************************************/
4134 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4135 struct spoolss_EnumPrinters *r)
4137 const char *name = NULL;
4138 WERROR result;
4140 /* that's an [in out] buffer */
4142 if (!r->in.buffer && (r->in.offered != 0)) {
4143 return WERR_INVALID_PARAM;
4146 DEBUG(4,("_spoolss_EnumPrinters\n"));
4148 *r->out.needed = 0;
4149 *r->out.count = 0;
4150 *r->out.info = NULL;
4153 * Level 1:
4154 * flags==PRINTER_ENUM_NAME
4155 * if name=="" then enumerates all printers
4156 * if name!="" then enumerate the printer
4157 * flags==PRINTER_ENUM_REMOTE
4158 * name is NULL, enumerate printers
4159 * Level 2: name!="" enumerates printers, name can't be NULL
4160 * Level 3: doesn't exist
4161 * Level 4: does a local registry lookup
4162 * Level 5: same as Level 2
4165 if (r->in.server) {
4166 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4167 W_ERROR_HAVE_NO_MEMORY(name);
4170 switch (r->in.level) {
4171 case 0:
4172 result = enumprinters_level0(p->mem_ctx, p->server_info,
4173 r->in.flags, name,
4174 r->out.info, r->out.count);
4175 break;
4176 case 1:
4177 result = enumprinters_level1(p->mem_ctx, p->server_info,
4178 r->in.flags, name,
4179 r->out.info, r->out.count);
4180 break;
4181 case 2:
4182 result = enumprinters_level2(p->mem_ctx, p->server_info,
4183 r->in.flags, name,
4184 r->out.info, r->out.count);
4185 break;
4186 case 4:
4187 result = enumprinters_level4(p->mem_ctx, p->server_info,
4188 r->in.flags, name,
4189 r->out.info, r->out.count);
4190 break;
4191 case 5:
4192 result = enumprinters_level5(p->mem_ctx, p->server_info,
4193 r->in.flags, name,
4194 r->out.info, r->out.count);
4195 break;
4196 default:
4197 return WERR_UNKNOWN_LEVEL;
4200 if (!W_ERROR_IS_OK(result)) {
4201 return result;
4204 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4205 spoolss_EnumPrinters,
4206 *r->out.info, r->in.level,
4207 *r->out.count);
4208 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4209 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4211 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4214 /****************************************************************
4215 _spoolss_GetPrinter
4216 ****************************************************************/
4218 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4219 struct spoolss_GetPrinter *r)
4221 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4222 struct spoolss_PrinterInfo2 *info2 = NULL;
4223 WERROR result = WERR_OK;
4224 const char *servername = NULL;
4225 int snum;
4227 /* that's an [in out] buffer */
4229 if (!r->in.buffer && (r->in.offered != 0)) {
4230 return WERR_INVALID_PARAM;
4233 *r->out.needed = 0;
4235 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4236 return WERR_BADFID;
4239 if (Printer != NULL || Printer->servername != NULL) {
4240 servername = Printer->servername;
4243 result = winreg_get_printer(p->mem_ctx,
4244 p->server_info,
4245 servername,
4246 lp_const_servicename(snum),
4247 &info2);
4248 if (!W_ERROR_IS_OK(result)) {
4249 goto out;
4252 switch (r->in.level) {
4253 case 0:
4254 result = construct_printer_info0(p->mem_ctx, p->server_info,
4255 info2,
4256 &r->out.info->info0, snum);
4257 break;
4258 case 1:
4259 result = construct_printer_info1(p->mem_ctx, info2,
4260 PRINTER_ENUM_ICON8,
4261 &r->out.info->info1, snum);
4262 break;
4263 case 2:
4264 result = construct_printer_info2(p->mem_ctx, info2,
4265 &r->out.info->info2, snum);
4266 break;
4267 case 3:
4268 result = construct_printer_info3(p->mem_ctx, info2,
4269 &r->out.info->info3, snum);
4270 break;
4271 case 4:
4272 result = construct_printer_info4(p->mem_ctx, info2,
4273 &r->out.info->info4, snum);
4274 break;
4275 case 5:
4276 result = construct_printer_info5(p->mem_ctx, info2,
4277 &r->out.info->info5, snum);
4278 break;
4279 case 6:
4280 result = construct_printer_info6(p->mem_ctx, info2,
4281 &r->out.info->info6, snum);
4282 break;
4283 case 7:
4284 result = construct_printer_info7(p->mem_ctx, Printer,
4285 &r->out.info->info7, snum);
4286 break;
4287 case 8:
4288 result = construct_printer_info8(p->mem_ctx, info2,
4289 &r->out.info->info8, snum);
4290 break;
4291 default:
4292 result = WERR_UNKNOWN_LEVEL;
4293 break;
4296 out:
4297 if (!W_ERROR_IS_OK(result)) {
4298 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4299 r->in.level, win_errstr(result)));
4300 TALLOC_FREE(r->out.info);
4301 return result;
4304 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4305 r->out.info, r->in.level);
4306 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4308 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4311 /********************************************************************
4312 ********************************************************************/
4314 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4315 do { \
4316 if (in && strlen(in)) { \
4317 out = talloc_strdup(mem_ctx, in); \
4318 } else { \
4319 out = talloc_strdup(mem_ctx, ""); \
4321 W_ERROR_HAVE_NO_MEMORY(out); \
4322 } while (0);
4324 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4325 do { \
4326 if (in && strlen(in)) { \
4327 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4328 } else { \
4329 out = talloc_strdup(mem_ctx, ""); \
4331 W_ERROR_HAVE_NO_MEMORY(out); \
4332 } while (0);
4334 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4335 const char **string_array,
4336 const char ***presult,
4337 const char *cservername,
4338 const char *arch,
4339 int version)
4341 int i, num_strings = 0;
4342 const char **array = NULL;
4344 if (string_array == NULL) {
4345 return WERR_INVALID_PARAMETER;;
4348 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4349 const char *str = NULL;
4351 if (cservername == NULL || arch == NULL) {
4352 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4353 } else {
4354 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4357 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4358 TALLOC_FREE(array);
4359 return WERR_NOMEM;
4363 if (i > 0) {
4364 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4365 &array, &num_strings);
4368 if (presult) {
4369 *presult = array;
4372 return WERR_OK;
4375 /********************************************************************
4376 * fill a spoolss_DriverInfo1 struct
4377 ********************************************************************/
4379 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4380 struct spoolss_DriverInfo1 *r,
4381 const struct spoolss_DriverInfo8 *driver,
4382 const char *servername)
4384 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4385 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4387 return WERR_OK;
4390 /********************************************************************
4391 * fill a spoolss_DriverInfo2 struct
4392 ********************************************************************/
4394 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4395 struct spoolss_DriverInfo2 *r,
4396 const struct spoolss_DriverInfo8 *driver,
4397 const char *servername)
4400 const char *cservername = canon_servername(servername);
4402 r->version = driver->version;
4404 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4405 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4406 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4407 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4409 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4410 driver->architecture,
4411 driver->version,
4412 driver->driver_path,
4413 r->driver_path);
4415 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4416 driver->architecture,
4417 driver->version,
4418 driver->data_file,
4419 r->data_file);
4421 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4422 driver->architecture,
4423 driver->version,
4424 driver->config_file,
4425 r->config_file);
4427 return WERR_OK;
4430 /********************************************************************
4431 * fill a spoolss_DriverInfo3 struct
4432 ********************************************************************/
4434 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4435 struct spoolss_DriverInfo3 *r,
4436 const struct spoolss_DriverInfo8 *driver,
4437 const char *servername)
4439 const char *cservername = canon_servername(servername);
4441 r->version = driver->version;
4443 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4444 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4445 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4446 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4448 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4449 driver->architecture,
4450 driver->version,
4451 driver->driver_path,
4452 r->driver_path);
4454 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4455 driver->architecture,
4456 driver->version,
4457 driver->data_file,
4458 r->data_file);
4460 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4461 driver->architecture,
4462 driver->version,
4463 driver->config_file,
4464 r->config_file);
4466 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4467 driver->architecture,
4468 driver->version,
4469 driver->help_file,
4470 r->help_file);
4472 FILL_DRIVER_STRING(mem_ctx,
4473 driver->monitor_name,
4474 r->monitor_name);
4476 FILL_DRIVER_STRING(mem_ctx,
4477 driver->default_datatype,
4478 r->default_datatype);
4480 return string_array_from_driver_info(mem_ctx,
4481 driver->dependent_files,
4482 &r->dependent_files,
4483 cservername,
4484 driver->architecture,
4485 driver->version);
4488 /********************************************************************
4489 * fill a spoolss_DriverInfo4 struct
4490 ********************************************************************/
4492 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4493 struct spoolss_DriverInfo4 *r,
4494 const struct spoolss_DriverInfo8 *driver,
4495 const char *servername)
4497 const char *cservername = canon_servername(servername);
4498 WERROR result;
4500 r->version = driver->version;
4502 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4503 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4504 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4505 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4507 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4508 driver->architecture,
4509 driver->version,
4510 driver->driver_path,
4511 r->driver_path);
4513 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4514 driver->architecture,
4515 driver->version,
4516 driver->data_file,
4517 r->data_file);
4519 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4520 driver->architecture,
4521 driver->version,
4522 driver->config_file,
4523 r->config_file);
4525 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4526 driver->architecture,
4527 driver->version,
4528 driver->help_file,
4529 r->help_file);
4531 result = string_array_from_driver_info(mem_ctx,
4532 driver->dependent_files,
4533 &r->dependent_files,
4534 cservername,
4535 driver->architecture,
4536 driver->version);
4537 if (!W_ERROR_IS_OK(result)) {
4538 return result;
4541 FILL_DRIVER_STRING(mem_ctx,
4542 driver->monitor_name,
4543 r->monitor_name);
4545 FILL_DRIVER_STRING(mem_ctx,
4546 driver->default_datatype,
4547 r->default_datatype);
4550 result = string_array_from_driver_info(mem_ctx,
4551 driver->previous_names,
4552 &r->previous_names,
4553 NULL, NULL, 0);
4555 return result;
4558 /********************************************************************
4559 * fill a spoolss_DriverInfo5 struct
4560 ********************************************************************/
4562 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4563 struct spoolss_DriverInfo5 *r,
4564 const struct spoolss_DriverInfo8 *driver,
4565 const char *servername)
4567 const char *cservername = canon_servername(servername);
4569 r->version = driver->version;
4571 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4572 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4573 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4574 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4576 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4577 driver->architecture,
4578 driver->version,
4579 driver->driver_path,
4580 r->driver_path);
4582 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4583 driver->architecture,
4584 driver->version,
4585 driver->data_file,
4586 r->data_file);
4588 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4589 driver->architecture,
4590 driver->version,
4591 driver->config_file,
4592 r->config_file);
4594 r->driver_attributes = 0;
4595 r->config_version = 0;
4596 r->driver_version = 0;
4598 return WERR_OK;
4600 /********************************************************************
4601 * fill a spoolss_DriverInfo6 struct
4602 ********************************************************************/
4604 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4605 struct spoolss_DriverInfo6 *r,
4606 const struct spoolss_DriverInfo8 *driver,
4607 const char *servername)
4609 const char *cservername = canon_servername(servername);
4610 WERROR result;
4612 r->version = driver->version;
4614 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4615 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4616 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4617 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4619 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4620 driver->architecture,
4621 driver->version,
4622 driver->driver_path,
4623 r->driver_path);
4625 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4626 driver->architecture,
4627 driver->version,
4628 driver->data_file,
4629 r->data_file);
4631 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4632 driver->architecture,
4633 driver->version,
4634 driver->config_file,
4635 r->config_file);
4637 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4638 driver->architecture,
4639 driver->version,
4640 driver->help_file,
4641 r->help_file);
4643 FILL_DRIVER_STRING(mem_ctx,
4644 driver->monitor_name,
4645 r->monitor_name);
4647 FILL_DRIVER_STRING(mem_ctx,
4648 driver->default_datatype,
4649 r->default_datatype);
4651 result = string_array_from_driver_info(mem_ctx,
4652 driver->dependent_files,
4653 &r->dependent_files,
4654 cservername,
4655 driver->architecture,
4656 driver->version);
4657 if (!W_ERROR_IS_OK(result)) {
4658 return result;
4661 result = string_array_from_driver_info(mem_ctx,
4662 driver->previous_names,
4663 &r->previous_names,
4664 NULL, NULL, 0);
4665 if (!W_ERROR_IS_OK(result)) {
4666 return result;
4669 r->driver_date = driver->driver_date;
4670 r->driver_version = driver->driver_version;
4672 FILL_DRIVER_STRING(mem_ctx,
4673 driver->manufacturer_name,
4674 r->manufacturer_name);
4675 FILL_DRIVER_STRING(mem_ctx,
4676 driver->manufacturer_url,
4677 r->manufacturer_url);
4678 FILL_DRIVER_STRING(mem_ctx,
4679 driver->hardware_id,
4680 r->hardware_id);
4681 FILL_DRIVER_STRING(mem_ctx,
4682 driver->provider,
4683 r->provider);
4685 return WERR_OK;
4688 /********************************************************************
4689 * fill a spoolss_DriverInfo8 struct
4690 ********************************************************************/
4692 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4693 struct spoolss_DriverInfo8 *r,
4694 const struct spoolss_DriverInfo8 *driver,
4695 const char *servername)
4697 const char *cservername = canon_servername(servername);
4698 WERROR result;
4700 r->version = driver->version;
4702 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4703 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4704 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4705 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4707 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4708 driver->architecture,
4709 driver->version,
4710 driver->driver_path,
4711 r->driver_path);
4713 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4714 driver->architecture,
4715 driver->version,
4716 driver->data_file,
4717 r->data_file);
4719 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4720 driver->architecture,
4721 driver->version,
4722 driver->config_file,
4723 r->config_file);
4725 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4726 driver->architecture,
4727 driver->version,
4728 driver->help_file,
4729 r->help_file);
4731 FILL_DRIVER_STRING(mem_ctx,
4732 driver->monitor_name,
4733 r->monitor_name);
4735 FILL_DRIVER_STRING(mem_ctx,
4736 driver->default_datatype,
4737 r->default_datatype);
4739 result = string_array_from_driver_info(mem_ctx,
4740 driver->dependent_files,
4741 &r->dependent_files,
4742 cservername,
4743 driver->architecture,
4744 driver->version);
4745 if (!W_ERROR_IS_OK(result)) {
4746 return result;
4749 result = string_array_from_driver_info(mem_ctx,
4750 driver->previous_names,
4751 &r->previous_names,
4752 NULL, NULL, 0);
4753 if (!W_ERROR_IS_OK(result)) {
4754 return result;
4757 r->driver_date = driver->driver_date;
4758 r->driver_version = driver->driver_version;
4760 FILL_DRIVER_STRING(mem_ctx,
4761 driver->manufacturer_name,
4762 r->manufacturer_name);
4763 FILL_DRIVER_STRING(mem_ctx,
4764 driver->manufacturer_url,
4765 r->manufacturer_url);
4766 FILL_DRIVER_STRING(mem_ctx,
4767 driver->hardware_id,
4768 r->hardware_id);
4769 FILL_DRIVER_STRING(mem_ctx,
4770 driver->provider,
4771 r->provider);
4773 FILL_DRIVER_STRING(mem_ctx,
4774 driver->print_processor,
4775 r->print_processor);
4776 FILL_DRIVER_STRING(mem_ctx,
4777 driver->vendor_setup,
4778 r->vendor_setup);
4780 result = string_array_from_driver_info(mem_ctx,
4781 driver->color_profiles,
4782 &r->color_profiles,
4783 NULL, NULL, 0);
4784 if (!W_ERROR_IS_OK(result)) {
4785 return result;
4788 FILL_DRIVER_STRING(mem_ctx,
4789 driver->inf_path,
4790 r->inf_path);
4792 r->printer_driver_attributes = driver->printer_driver_attributes;
4794 result = string_array_from_driver_info(mem_ctx,
4795 driver->core_driver_dependencies,
4796 &r->core_driver_dependencies,
4797 NULL, NULL, 0);
4798 if (!W_ERROR_IS_OK(result)) {
4799 return result;
4802 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4803 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4805 return WERR_OK;
4808 #if 0 /* disabled until marshalling issues are resolved - gd */
4809 /********************************************************************
4810 ********************************************************************/
4812 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4813 struct spoolss_DriverFileInfo *r,
4814 const char *cservername,
4815 const char *file_name,
4816 enum spoolss_DriverFileType file_type,
4817 uint32_t file_version)
4819 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4820 cservername, file_name);
4821 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4822 r->file_type = file_type;
4823 r->file_version = file_version;
4825 return WERR_OK;
4828 /********************************************************************
4829 ********************************************************************/
4831 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4832 const struct spoolss_DriverInfo8 *driver,
4833 const char *cservername,
4834 struct spoolss_DriverFileInfo **info_p,
4835 uint32_t *count_p)
4837 struct spoolss_DriverFileInfo *info = NULL;
4838 uint32_t count = 0;
4839 WERROR result;
4840 uint32_t i;
4842 *info_p = NULL;
4843 *count_p = 0;
4845 if (strlen(driver->driver_path)) {
4846 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4847 struct spoolss_DriverFileInfo,
4848 count + 1);
4849 W_ERROR_HAVE_NO_MEMORY(info);
4850 result = fill_spoolss_DriverFileInfo(info,
4851 &info[count],
4852 cservername,
4853 driver->driver_path,
4854 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4856 W_ERROR_NOT_OK_RETURN(result);
4857 count++;
4860 if (strlen(driver->config_file)) {
4861 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4862 struct spoolss_DriverFileInfo,
4863 count + 1);
4864 W_ERROR_HAVE_NO_MEMORY(info);
4865 result = fill_spoolss_DriverFileInfo(info,
4866 &info[count],
4867 cservername,
4868 driver->config_file,
4869 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4871 W_ERROR_NOT_OK_RETURN(result);
4872 count++;
4875 if (strlen(driver->data_file)) {
4876 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4877 struct spoolss_DriverFileInfo,
4878 count + 1);
4879 W_ERROR_HAVE_NO_MEMORY(info);
4880 result = fill_spoolss_DriverFileInfo(info,
4881 &info[count],
4882 cservername,
4883 driver->data_file,
4884 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4886 W_ERROR_NOT_OK_RETURN(result);
4887 count++;
4890 if (strlen(driver->help_file)) {
4891 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4892 struct spoolss_DriverFileInfo,
4893 count + 1);
4894 W_ERROR_HAVE_NO_MEMORY(info);
4895 result = fill_spoolss_DriverFileInfo(info,
4896 &info[count],
4897 cservername,
4898 driver->help_file,
4899 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4901 W_ERROR_NOT_OK_RETURN(result);
4902 count++;
4905 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4906 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4907 struct spoolss_DriverFileInfo,
4908 count + 1);
4909 W_ERROR_HAVE_NO_MEMORY(info);
4910 result = fill_spoolss_DriverFileInfo(info,
4911 &info[count],
4912 cservername,
4913 driver->dependent_files[i],
4914 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4916 W_ERROR_NOT_OK_RETURN(result);
4917 count++;
4920 *info_p = info;
4921 *count_p = count;
4923 return WERR_OK;
4926 /********************************************************************
4927 * fill a spoolss_DriverInfo101 struct
4928 ********************************************************************/
4930 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4931 struct spoolss_DriverInfo101 *r,
4932 const struct spoolss_DriverInfo8 *driver,
4933 const char *servername)
4935 const char *cservername = canon_servername(servername);
4936 WERROR result;
4938 r->version = driver->version;
4940 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4941 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4942 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4943 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4945 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4946 cservername,
4947 &r->file_info,
4948 &r->file_count);
4949 if (!W_ERROR_IS_OK(result)) {
4950 return result;
4953 FILL_DRIVER_STRING(mem_ctx,
4954 driver->monitor_name,
4955 r->monitor_name);
4957 FILL_DRIVER_STRING(mem_ctx,
4958 driver->default_datatype,
4959 r->default_datatype);
4961 result = string_array_from_driver_info(mem_ctx,
4962 driver->previous_names,
4963 &r->previous_names,
4964 NULL, NULL, 0);
4965 if (!W_ERROR_IS_OK(result)) {
4966 return result;
4969 r->driver_date = driver->driver_date;
4970 r->driver_version = driver->driver_version;
4972 FILL_DRIVER_STRING(mem_ctx,
4973 driver->manufacturer_name,
4974 r->manufacturer_name);
4975 FILL_DRIVER_STRING(mem_ctx,
4976 driver->manufacturer_url,
4977 r->manufacturer_url);
4978 FILL_DRIVER_STRING(mem_ctx,
4979 driver->hardware_id,
4980 r->hardware_id);
4981 FILL_DRIVER_STRING(mem_ctx,
4982 driver->provider,
4983 r->provider);
4985 return WERR_OK;
4987 #endif
4988 /********************************************************************
4989 ********************************************************************/
4991 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4992 struct auth_serversupplied_info *server_info,
4993 uint32_t level,
4994 union spoolss_DriverInfo *r,
4995 int snum,
4996 const char *servername,
4997 const char *architecture,
4998 uint32_t version)
5000 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5001 struct spoolss_DriverInfo8 *driver;
5002 WERROR result;
5004 if (level == 101) {
5005 return WERR_UNKNOWN_LEVEL;
5008 result = winreg_get_printer(mem_ctx,
5009 server_info,
5010 servername,
5011 lp_const_servicename(snum),
5012 &pinfo2);
5014 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5015 win_errstr(result)));
5017 if (!W_ERROR_IS_OK(result)) {
5018 return WERR_INVALID_PRINTER_NAME;
5021 result = winreg_get_driver(mem_ctx, server_info, architecture,
5022 pinfo2->drivername, version, &driver);
5024 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5025 win_errstr(result)));
5027 if (!W_ERROR_IS_OK(result)) {
5029 * Is this a W2k client ?
5032 if (version < 3) {
5033 talloc_free(pinfo2);
5034 return WERR_UNKNOWN_PRINTER_DRIVER;
5037 /* Yes - try again with a WinNT driver. */
5038 version = 2;
5039 result = winreg_get_driver(mem_ctx, server_info, architecture,
5040 pinfo2->drivername,
5041 version, &driver);
5042 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5043 win_errstr(result)));
5044 if (!W_ERROR_IS_OK(result)) {
5045 talloc_free(pinfo2);
5046 return WERR_UNKNOWN_PRINTER_DRIVER;
5050 switch (level) {
5051 case 1:
5052 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5053 break;
5054 case 2:
5055 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5056 break;
5057 case 3:
5058 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5059 break;
5060 case 4:
5061 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5062 break;
5063 case 5:
5064 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5065 break;
5066 case 6:
5067 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5068 break;
5069 case 8:
5070 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5071 break;
5072 #if 0 /* disabled until marshalling issues are resolved - gd */
5073 case 101:
5074 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5075 break;
5076 #endif
5077 default:
5078 result = WERR_UNKNOWN_LEVEL;
5079 break;
5082 talloc_free(pinfo2);
5083 talloc_free(driver);
5085 return result;
5088 /****************************************************************
5089 _spoolss_GetPrinterDriver2
5090 ****************************************************************/
5092 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5093 struct spoolss_GetPrinterDriver2 *r)
5095 Printer_entry *printer;
5096 WERROR result;
5098 int snum;
5100 /* that's an [in out] buffer */
5102 if (!r->in.buffer && (r->in.offered != 0)) {
5103 return WERR_INVALID_PARAM;
5106 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5108 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5109 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5110 return WERR_INVALID_PRINTER_NAME;
5113 *r->out.needed = 0;
5114 *r->out.server_major_version = 0;
5115 *r->out.server_minor_version = 0;
5117 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5118 return WERR_BADFID;
5121 result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
5122 r->in.level, r->out.info,
5123 snum, printer->servername,
5124 r->in.architecture,
5125 r->in.client_major_version);
5126 if (!W_ERROR_IS_OK(result)) {
5127 TALLOC_FREE(r->out.info);
5128 return result;
5131 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5132 r->out.info, r->in.level);
5133 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5135 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5139 /****************************************************************
5140 _spoolss_StartPagePrinter
5141 ****************************************************************/
5143 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5144 struct spoolss_StartPagePrinter *r)
5146 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5148 if (!Printer) {
5149 DEBUG(3,("_spoolss_StartPagePrinter: "
5150 "Error in startpageprinter printer handle\n"));
5151 return WERR_BADFID;
5154 Printer->page_started = true;
5155 return WERR_OK;
5158 /****************************************************************
5159 _spoolss_EndPagePrinter
5160 ****************************************************************/
5162 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5163 struct spoolss_EndPagePrinter *r)
5165 int snum;
5167 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5169 if (!Printer) {
5170 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5171 OUR_HANDLE(r->in.handle)));
5172 return WERR_BADFID;
5175 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5176 return WERR_BADFID;
5178 Printer->page_started = false;
5179 print_job_endpage(snum, Printer->jobid);
5181 return WERR_OK;
5184 /****************************************************************
5185 _spoolss_StartDocPrinter
5186 ****************************************************************/
5188 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5189 struct spoolss_StartDocPrinter *r)
5191 struct spoolss_DocumentInfo1 *info_1;
5192 int snum;
5193 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5194 WERROR werr;
5196 if (!Printer) {
5197 DEBUG(2,("_spoolss_StartDocPrinter: "
5198 "Invalid handle (%s:%u:%u)\n",
5199 OUR_HANDLE(r->in.handle)));
5200 return WERR_BADFID;
5203 if (Printer->jobid) {
5204 DEBUG(2, ("_spoolss_StartDocPrinter: "
5205 "StartDocPrinter called twice! "
5206 "(existing jobid = %d)\n", Printer->jobid));
5207 return WERR_INVALID_HANDLE;
5210 if (r->in.level != 1) {
5211 return WERR_UNKNOWN_LEVEL;
5214 info_1 = r->in.info.info1;
5217 * a nice thing with NT is it doesn't listen to what you tell it.
5218 * when asked to send _only_ RAW datas, it tries to send datas
5219 * in EMF format.
5221 * So I add checks like in NT Server ...
5224 if (info_1->datatype) {
5225 if (strcmp(info_1->datatype, "RAW") != 0) {
5226 *r->out.job_id = 0;
5227 return WERR_INVALID_DATATYPE;
5231 /* get the share number of the printer */
5232 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5233 return WERR_BADFID;
5236 werr = print_job_start(p->server_info, snum,
5237 info_1->document_name, info_1->output_file,
5238 Printer->devmode, &Printer->jobid);
5240 /* An error occured in print_job_start() so return an appropriate
5241 NT error code. */
5243 if (!W_ERROR_IS_OK(werr)) {
5244 return werr;
5247 Printer->document_started = true;
5248 *r->out.job_id = Printer->jobid;
5250 return WERR_OK;
5253 /****************************************************************
5254 _spoolss_EndDocPrinter
5255 ****************************************************************/
5257 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5258 struct spoolss_EndDocPrinter *r)
5260 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5261 NTSTATUS status;
5262 int snum;
5264 if (!Printer) {
5265 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5266 OUR_HANDLE(r->in.handle)));
5267 return WERR_BADFID;
5270 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5271 return WERR_BADFID;
5274 Printer->document_started = false;
5275 status = print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5276 if (!NT_STATUS_IS_OK(status)) {
5277 DEBUG(2, ("_spoolss_EndDocPrinter: "
5278 "print_job_end failed [%s]\n",
5279 nt_errstr(status)));
5282 Printer->jobid = 0;
5283 return ntstatus_to_werror(status);
5286 /****************************************************************
5287 _spoolss_WritePrinter
5288 ****************************************************************/
5290 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5291 struct spoolss_WritePrinter *r)
5293 ssize_t buffer_written;
5294 int snum;
5295 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5297 if (!Printer) {
5298 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5299 OUR_HANDLE(r->in.handle)));
5300 *r->out.num_written = r->in._data_size;
5301 return WERR_BADFID;
5304 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5305 return WERR_BADFID;
5307 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5308 buffer_written = print_job_write(snum, Printer->jobid,
5309 (const char *)r->in.data.data,
5310 (SMB_OFF_T)-1,
5311 (size_t)r->in._data_size);
5312 if (buffer_written == (ssize_t)-1) {
5313 *r->out.num_written = 0;
5314 if (errno == ENOSPC)
5315 return WERR_NO_SPOOL_SPACE;
5316 else
5317 return WERR_ACCESS_DENIED;
5320 *r->out.num_written = r->in._data_size;
5322 return WERR_OK;
5325 /********************************************************************
5326 * api_spoolss_getprinter
5327 * called from the spoolss dispatcher
5329 ********************************************************************/
5331 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5332 struct pipes_struct *p)
5334 int snum;
5335 WERROR errcode = WERR_BADFUNC;
5336 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5338 if (!Printer) {
5339 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5340 OUR_HANDLE(handle)));
5341 return WERR_BADFID;
5344 if (!get_printer_snum(p, handle, &snum, NULL))
5345 return WERR_BADFID;
5347 switch (command) {
5348 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5349 errcode = print_queue_pause(p->server_info, snum);
5350 break;
5351 case SPOOLSS_PRINTER_CONTROL_RESUME:
5352 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5353 errcode = print_queue_resume(p->server_info, snum);
5354 break;
5355 case SPOOLSS_PRINTER_CONTROL_PURGE:
5356 errcode = print_queue_purge(p->server_info, snum);
5357 break;
5358 default:
5359 return WERR_UNKNOWN_LEVEL;
5362 return errcode;
5366 /****************************************************************
5367 _spoolss_AbortPrinter
5368 * From MSDN: "Deletes printer's spool file if printer is configured
5369 * for spooling"
5370 ****************************************************************/
5372 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5373 struct spoolss_AbortPrinter *r)
5375 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5376 int snum;
5377 WERROR errcode = WERR_OK;
5379 if (!Printer) {
5380 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5381 OUR_HANDLE(r->in.handle)));
5382 return WERR_BADFID;
5385 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5386 return WERR_BADFID;
5388 if (!Printer->document_started) {
5389 return WERR_SPL_NO_STARTDOC;
5392 errcode = print_job_delete(p->server_info, snum, Printer->jobid);
5394 return errcode;
5397 /********************************************************************
5398 * called by spoolss_api_setprinter
5399 * when updating a printer description
5400 ********************************************************************/
5402 static WERROR update_printer_sec(struct policy_handle *handle,
5403 struct pipes_struct *p,
5404 struct sec_desc_buf *secdesc_ctr)
5406 struct spoolss_security_descriptor *new_secdesc = NULL;
5407 struct spoolss_security_descriptor *old_secdesc = NULL;
5408 const char *printer;
5409 WERROR result;
5410 int snum;
5412 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5414 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5415 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5416 OUR_HANDLE(handle)));
5418 result = WERR_BADFID;
5419 goto done;
5422 if (secdesc_ctr == NULL) {
5423 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5424 result = WERR_INVALID_PARAM;
5425 goto done;
5427 printer = lp_const_servicename(snum);
5429 /* Check the user has permissions to change the security
5430 descriptor. By experimentation with two NT machines, the user
5431 requires Full Access to the printer to change security
5432 information. */
5434 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5435 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5436 result = WERR_ACCESS_DENIED;
5437 goto done;
5440 /* NT seems to like setting the security descriptor even though
5441 nothing may have actually changed. */
5442 result = winreg_get_printer_secdesc(p->mem_ctx,
5443 p->server_info,
5444 printer,
5445 &old_secdesc);
5446 if (!W_ERROR_IS_OK(result)) {
5447 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5448 result = WERR_BADFID;
5449 goto done;
5452 if (DEBUGLEVEL >= 10) {
5453 struct security_acl *the_acl;
5454 int i;
5456 the_acl = old_secdesc->dacl;
5457 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5458 printer, the_acl->num_aces));
5460 for (i = 0; i < the_acl->num_aces; i++) {
5461 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5462 &the_acl->aces[i].trustee),
5463 the_acl->aces[i].access_mask));
5466 the_acl = secdesc_ctr->sd->dacl;
5468 if (the_acl) {
5469 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5470 printer, the_acl->num_aces));
5472 for (i = 0; i < the_acl->num_aces; i++) {
5473 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5474 &the_acl->aces[i].trustee),
5475 the_acl->aces[i].access_mask));
5477 } else {
5478 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5482 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5483 if (new_secdesc == NULL) {
5484 result = WERR_NOMEM;
5485 goto done;
5488 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5489 result = WERR_OK;
5490 goto done;
5493 result = winreg_set_printer_secdesc(p->mem_ctx,
5494 p->server_info,
5495 printer,
5496 new_secdesc);
5498 done:
5499 return result;
5502 /********************************************************************
5503 Canonicalize printer info from a client
5504 ********************************************************************/
5506 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5507 struct spoolss_SetPrinterInfo2 *info2,
5508 int snum)
5510 fstring printername;
5511 const char *p;
5513 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5514 "portname=%s drivername=%s comment=%s location=%s\n",
5515 info2->servername, info2->printername, info2->sharename,
5516 info2->portname, info2->drivername, info2->comment,
5517 info2->location));
5519 /* we force some elements to "correct" values */
5520 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5521 if (info2->servername == NULL) {
5522 return false;
5524 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5525 if (info2->sharename == NULL) {
5526 return false;
5529 /* check to see if we allow printername != sharename */
5530 if (lp_force_printername(snum)) {
5531 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5532 global_myname(), info2->sharename);
5533 } else {
5534 /* make sure printername is in \\server\printername format */
5535 fstrcpy(printername, info2->printername);
5536 p = printername;
5537 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5538 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5539 p++;
5542 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5543 global_myname(), p);
5545 if (info2->printername == NULL) {
5546 return false;
5549 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5550 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5552 return true;
5555 /****************************************************************************
5556 ****************************************************************************/
5558 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5560 char *cmd = lp_addport_cmd();
5561 char *command = NULL;
5562 int ret;
5563 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5564 bool is_print_op = false;
5566 if ( !*cmd ) {
5567 return WERR_ACCESS_DENIED;
5570 command = talloc_asprintf(ctx,
5571 "%s \"%s\" \"%s\"", cmd, portname, uri );
5572 if (!command) {
5573 return WERR_NOMEM;
5576 if ( token )
5577 is_print_op = user_has_privileges( token, &se_printop );
5579 DEBUG(10,("Running [%s]\n", command));
5581 /********* BEGIN SePrintOperatorPrivilege **********/
5583 if ( is_print_op )
5584 become_root();
5586 ret = smbrun(command, NULL);
5588 if ( is_print_op )
5589 unbecome_root();
5591 /********* END SePrintOperatorPrivilege **********/
5593 DEBUGADD(10,("returned [%d]\n", ret));
5595 TALLOC_FREE(command);
5597 if ( ret != 0 ) {
5598 return WERR_ACCESS_DENIED;
5601 return WERR_OK;
5604 /****************************************************************************
5605 ****************************************************************************/
5607 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5608 struct spoolss_SetPrinterInfo2 *info2,
5609 const char *remote_machine)
5611 char *cmd = lp_addprinter_cmd();
5612 char **qlines;
5613 char *command = NULL;
5614 int numlines;
5615 int ret;
5616 int fd;
5617 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5618 bool is_print_op = false;
5620 if (!remote_machine) {
5621 return false;
5624 command = talloc_asprintf(ctx,
5625 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5626 cmd, info2->printername, info2->sharename,
5627 info2->portname, info2->drivername,
5628 info2->location, info2->comment, remote_machine);
5629 if (!command) {
5630 return false;
5633 if ( token )
5634 is_print_op = user_has_privileges( token, &se_printop );
5636 DEBUG(10,("Running [%s]\n", command));
5638 /********* BEGIN SePrintOperatorPrivilege **********/
5640 if ( is_print_op )
5641 become_root();
5643 if ( (ret = smbrun(command, &fd)) == 0 ) {
5644 /* Tell everyone we updated smb.conf. */
5645 message_send_all(smbd_messaging_context(),
5646 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5649 if ( is_print_op )
5650 unbecome_root();
5652 /********* END SePrintOperatorPrivilege **********/
5654 DEBUGADD(10,("returned [%d]\n", ret));
5656 TALLOC_FREE(command);
5658 if ( ret != 0 ) {
5659 if (fd != -1)
5660 close(fd);
5661 return false;
5664 /* reload our services immediately */
5665 become_root();
5666 reload_services(false);
5667 unbecome_root();
5669 numlines = 0;
5670 /* Get lines and convert them back to dos-codepage */
5671 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5672 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5673 close(fd);
5675 /* Set the portname to what the script says the portname should be. */
5676 /* but don't require anything to be return from the script exit a good error code */
5678 if (numlines) {
5679 /* Set the portname to what the script says the portname should be. */
5680 info2->portname = talloc_strdup(ctx, qlines[0]);
5681 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5684 TALLOC_FREE(qlines);
5685 return true;
5688 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5689 struct auth_serversupplied_info *server_info,
5690 int snum,
5691 struct spoolss_SetPrinterInfo2 *printer,
5692 struct spoolss_PrinterInfo2 *old_printer)
5694 bool force_update = (old_printer == NULL);
5695 const char *dnsdomname;
5696 const char *longname;
5697 const char *uncname;
5698 const char *spooling;
5699 DATA_BLOB buffer;
5700 WERROR result = WERR_OK;
5702 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5703 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5704 winreg_set_printer_dataex(mem_ctx,
5705 server_info,
5706 printer->sharename,
5707 SPOOL_DSSPOOLER_KEY,
5708 SPOOL_REG_DRIVERNAME,
5709 REG_SZ,
5710 buffer.data,
5711 buffer.length);
5713 if (!force_update) {
5714 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5715 printer->drivername));
5717 notify_printer_driver(snum, printer->drivername);
5721 if (force_update || !strequal(printer->comment, old_printer->comment)) {
5722 push_reg_sz(mem_ctx, &buffer, printer->comment);
5723 winreg_set_printer_dataex(mem_ctx,
5724 server_info,
5725 printer->sharename,
5726 SPOOL_DSSPOOLER_KEY,
5727 SPOOL_REG_DESCRIPTION,
5728 REG_SZ,
5729 buffer.data,
5730 buffer.length);
5732 if (!force_update) {
5733 notify_printer_comment(snum, printer->comment);
5737 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5738 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5739 winreg_set_printer_dataex(mem_ctx,
5740 server_info,
5741 printer->sharename,
5742 SPOOL_DSSPOOLER_KEY,
5743 SPOOL_REG_PRINTSHARENAME,
5744 REG_SZ,
5745 buffer.data,
5746 buffer.length);
5748 if (!force_update) {
5749 notify_printer_sharename(snum, printer->sharename);
5753 if (force_update || !strequal(printer->printername, old_printer->printername)) {
5754 const char *p;
5756 p = strrchr(printer->printername, '\\' );
5757 if (p != NULL) {
5758 p++;
5759 } else {
5760 p = printer->printername;
5763 push_reg_sz(mem_ctx, &buffer, p);
5764 winreg_set_printer_dataex(mem_ctx,
5765 server_info,
5766 printer->sharename,
5767 SPOOL_DSSPOOLER_KEY,
5768 SPOOL_REG_PRINTERNAME,
5769 REG_SZ,
5770 buffer.data,
5771 buffer.length);
5773 if (!force_update) {
5774 notify_printer_printername(snum, p);
5778 if (force_update || !strequal(printer->portname, old_printer->portname)) {
5779 push_reg_sz(mem_ctx, &buffer, printer->portname);
5780 winreg_set_printer_dataex(mem_ctx,
5781 server_info,
5782 printer->sharename,
5783 SPOOL_DSSPOOLER_KEY,
5784 SPOOL_REG_PORTNAME,
5785 REG_SZ,
5786 buffer.data,
5787 buffer.length);
5789 if (!force_update) {
5790 notify_printer_port(snum, printer->portname);
5794 if (force_update || !strequal(printer->location, old_printer->location)) {
5795 push_reg_sz(mem_ctx, &buffer, printer->location);
5796 winreg_set_printer_dataex(mem_ctx,
5797 server_info,
5798 printer->sharename,
5799 SPOOL_DSSPOOLER_KEY,
5800 SPOOL_REG_LOCATION,
5801 REG_SZ,
5802 buffer.data,
5803 buffer.length);
5805 if (!force_update) {
5806 notify_printer_location(snum, printer->location);
5810 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
5811 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
5812 winreg_set_printer_dataex(mem_ctx,
5813 server_info,
5814 printer->sharename,
5815 SPOOL_DSSPOOLER_KEY,
5816 SPOOL_REG_PRINTSEPARATORFILE,
5817 REG_SZ,
5818 buffer.data,
5819 buffer.length);
5821 if (!force_update) {
5822 notify_printer_location(snum, printer->location);
5826 if (force_update || printer->starttime != old_printer->starttime) {
5827 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5828 SIVAL(buffer.data, 0, printer->starttime);
5829 winreg_set_printer_dataex(mem_ctx,
5830 server_info,
5831 printer->sharename,
5832 SPOOL_DSSPOOLER_KEY,
5833 SPOOL_REG_PRINTSTARTTIME,
5834 REG_DWORD,
5835 buffer.data,
5836 buffer.length);
5839 if (force_update || printer->untiltime != old_printer->untiltime) {
5840 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5841 SIVAL(buffer.data, 0, printer->untiltime);
5842 winreg_set_printer_dataex(mem_ctx,
5843 server_info,
5844 printer->sharename,
5845 SPOOL_DSSPOOLER_KEY,
5846 SPOOL_REG_PRINTENDTIME,
5847 REG_DWORD,
5848 buffer.data,
5849 buffer.length);
5852 if (force_update || printer->priority != old_printer->priority) {
5853 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5854 SIVAL(buffer.data, 0, printer->priority);
5855 winreg_set_printer_dataex(mem_ctx,
5856 server_info,
5857 printer->sharename,
5858 SPOOL_DSSPOOLER_KEY,
5859 SPOOL_REG_PRIORITY,
5860 REG_DWORD,
5861 buffer.data,
5862 buffer.length);
5865 if (force_update || printer->attributes != old_printer->attributes) {
5866 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5867 SIVAL(buffer.data, 0, (printer->attributes &
5868 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
5869 winreg_set_printer_dataex(mem_ctx,
5870 server_info,
5871 printer->sharename,
5872 SPOOL_DSSPOOLER_KEY,
5873 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
5874 REG_DWORD,
5875 buffer.data,
5876 buffer.length);
5878 switch (printer->attributes & 0x3) {
5879 case 0:
5880 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
5881 break;
5882 case 1:
5883 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
5884 break;
5885 case 2:
5886 spooling = SPOOL_REGVAL_PRINTDIRECT;
5887 break;
5888 default:
5889 spooling = "unknown";
5891 push_reg_sz(mem_ctx, &buffer, spooling);
5892 winreg_set_printer_dataex(mem_ctx,
5893 server_info,
5894 printer->sharename,
5895 SPOOL_DSSPOOLER_KEY,
5896 SPOOL_REG_PRINTSPOOLING,
5897 REG_SZ,
5898 buffer.data,
5899 buffer.length);
5902 push_reg_sz(mem_ctx, &buffer, global_myname());
5903 winreg_set_printer_dataex(mem_ctx,
5904 server_info,
5905 printer->sharename,
5906 SPOOL_DSSPOOLER_KEY,
5907 SPOOL_REG_SHORTSERVERNAME,
5908 REG_SZ,
5909 buffer.data,
5910 buffer.length);
5912 dnsdomname = get_mydnsfullname();
5913 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
5914 longname = talloc_strdup(mem_ctx, dnsdomname);
5915 } else {
5916 longname = talloc_strdup(mem_ctx, global_myname());
5918 if (longname == NULL) {
5919 result = WERR_NOMEM;
5920 goto done;
5923 push_reg_sz(mem_ctx, &buffer, longname);
5924 winreg_set_printer_dataex(mem_ctx,
5925 server_info,
5926 printer->sharename,
5927 SPOOL_DSSPOOLER_KEY,
5928 SPOOL_REG_SERVERNAME,
5929 REG_SZ,
5930 buffer.data,
5931 buffer.length);
5933 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5934 global_myname(), printer->sharename);
5935 push_reg_sz(mem_ctx, &buffer, uncname);
5936 winreg_set_printer_dataex(mem_ctx,
5937 server_info,
5938 printer->sharename,
5939 SPOOL_DSSPOOLER_KEY,
5940 SPOOL_REG_UNCNAME,
5941 REG_SZ,
5942 buffer.data,
5943 buffer.length);
5945 done:
5946 return result;
5949 /********************************************************************
5950 * Called by spoolss_api_setprinter
5951 * when updating a printer description.
5952 ********************************************************************/
5954 static WERROR update_printer(struct pipes_struct *p,
5955 struct policy_handle *handle,
5956 struct spoolss_SetPrinterInfoCtr *info_ctr,
5957 struct spoolss_DeviceMode *devmode)
5959 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5960 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5961 struct spoolss_PrinterInfo2 *old_printer;
5962 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5963 const char *servername = NULL;
5964 int snum;
5965 WERROR result = WERR_OK;
5966 TALLOC_CTX *tmp_ctx;
5968 DEBUG(8,("update_printer\n"));
5970 tmp_ctx = talloc_new(p->mem_ctx);
5971 if (tmp_ctx == NULL) {
5972 return WERR_NOMEM;
5975 if (!Printer) {
5976 result = WERR_BADFID;
5977 goto done;
5980 if (!get_printer_snum(p, handle, &snum, NULL)) {
5981 result = WERR_BADFID;
5982 goto done;
5985 if (Printer != NULL || Printer->servername != NULL) {
5986 servername = Printer->servername;
5989 result = winreg_get_printer(tmp_ctx,
5990 p->server_info,
5991 servername,
5992 lp_const_servicename(snum),
5993 &old_printer);
5994 if (!W_ERROR_IS_OK(result)) {
5995 result = WERR_BADFID;
5996 goto done;
5999 /* Do sanity check on the requested changes for Samba */
6000 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6001 result = WERR_INVALID_PARAM;
6002 goto done;
6005 /* FIXME!!! If the driver has changed we really should verify that
6006 it is installed before doing much else --jerry */
6008 /* Check calling user has permission to update printer description */
6009 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6010 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6011 result = WERR_ACCESS_DENIED;
6012 goto done;
6015 /* Call addprinter hook */
6016 /* Check changes to see if this is really needed */
6018 if (*lp_addprinter_cmd() &&
6019 (!strequal(printer->drivername, old_printer->drivername) ||
6020 !strequal(printer->comment, old_printer->comment) ||
6021 !strequal(printer->portname, old_printer->portname) ||
6022 !strequal(printer->location, old_printer->location)) )
6024 /* add_printer_hook() will call reload_services() */
6025 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6026 printer, p->client_address) ) {
6027 result = WERR_ACCESS_DENIED;
6028 goto done;
6032 update_dsspooler(tmp_ctx,
6033 p->server_info,
6034 snum,
6035 printer,
6036 old_printer);
6038 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6040 if (devmode == NULL) {
6041 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6043 result = winreg_update_printer(tmp_ctx,
6044 p->server_info,
6045 printer->sharename,
6046 printer_mask,
6047 printer,
6048 devmode,
6049 NULL);
6051 done:
6052 talloc_free(tmp_ctx);
6054 return result;
6057 /****************************************************************************
6058 ****************************************************************************/
6059 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6060 struct policy_handle *handle,
6061 struct spoolss_SetPrinterInfo7 *info7)
6063 #ifdef HAVE_ADS
6064 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6065 WERROR result;
6066 int snum;
6067 Printer_entry *Printer;
6069 if ( lp_security() != SEC_ADS ) {
6070 return WERR_UNKNOWN_LEVEL;
6073 Printer = find_printer_index_by_hnd(p, handle);
6075 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6077 if (!Printer)
6078 return WERR_BADFID;
6080 if (!get_printer_snum(p, handle, &snum, NULL))
6081 return WERR_BADFID;
6083 result = winreg_get_printer(p->mem_ctx, p->server_info,
6084 Printer->servername,
6085 lp_servicename(snum), &pinfo2);
6086 if (!W_ERROR_IS_OK(result)) {
6087 return WERR_BADFID;
6090 nt_printer_publish(pinfo2, p->server_info, pinfo2, info7->action);
6092 TALLOC_FREE(pinfo2);
6093 return WERR_OK;
6094 #else
6095 return WERR_UNKNOWN_LEVEL;
6096 #endif
6099 /********************************************************************
6100 ********************************************************************/
6102 static WERROR update_printer_devmode(struct pipes_struct *p,
6103 struct policy_handle *handle,
6104 struct spoolss_DeviceMode *devmode)
6106 int snum;
6107 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6108 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6110 DEBUG(8,("update_printer_devmode\n"));
6112 if (!Printer) {
6113 return WERR_BADFID;
6116 if (!get_printer_snum(p, handle, &snum, NULL)) {
6117 return WERR_BADFID;
6120 /* Check calling user has permission to update printer description */
6121 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6122 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6123 return WERR_ACCESS_DENIED;
6126 return winreg_update_printer(p->mem_ctx,
6127 p->server_info,
6128 lp_const_servicename(snum),
6129 info2_mask,
6130 NULL,
6131 devmode,
6132 NULL);
6136 /****************************************************************
6137 _spoolss_SetPrinter
6138 ****************************************************************/
6140 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6141 struct spoolss_SetPrinter *r)
6143 WERROR result;
6145 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6147 if (!Printer) {
6148 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6149 OUR_HANDLE(r->in.handle)));
6150 return WERR_BADFID;
6153 /* check the level */
6154 switch (r->in.info_ctr->level) {
6155 case 0:
6156 return control_printer(r->in.handle, r->in.command, p);
6157 case 2:
6158 result = update_printer(p, r->in.handle,
6159 r->in.info_ctr,
6160 r->in.devmode_ctr->devmode);
6161 if (!W_ERROR_IS_OK(result))
6162 return result;
6163 if (r->in.secdesc_ctr->sd)
6164 result = update_printer_sec(r->in.handle, p,
6165 r->in.secdesc_ctr);
6166 return result;
6167 case 3:
6168 return update_printer_sec(r->in.handle, p,
6169 r->in.secdesc_ctr);
6170 case 7:
6171 return publish_or_unpublish_printer(p, r->in.handle,
6172 r->in.info_ctr->info.info7);
6173 case 8:
6174 return update_printer_devmode(p, r->in.handle,
6175 r->in.devmode_ctr->devmode);
6176 default:
6177 return WERR_UNKNOWN_LEVEL;
6181 /****************************************************************
6182 _spoolss_FindClosePrinterNotify
6183 ****************************************************************/
6185 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6186 struct spoolss_FindClosePrinterNotify *r)
6188 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6190 if (!Printer) {
6191 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6192 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6193 return WERR_BADFID;
6196 if (Printer->notify.client_connected == true) {
6197 int snum = -1;
6199 if ( Printer->printer_type == SPLHND_SERVER)
6200 snum = -1;
6201 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6202 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6203 return WERR_BADFID;
6205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6208 Printer->notify.flags=0;
6209 Printer->notify.options=0;
6210 Printer->notify.localmachine[0]='\0';
6211 Printer->notify.printerlocal=0;
6212 TALLOC_FREE(Printer->notify.option);
6213 Printer->notify.client_connected = false;
6215 return WERR_OK;
6218 /****************************************************************
6219 _spoolss_AddJob
6220 ****************************************************************/
6222 WERROR _spoolss_AddJob(struct pipes_struct *p,
6223 struct spoolss_AddJob *r)
6225 if (!r->in.buffer && (r->in.offered != 0)) {
6226 return WERR_INVALID_PARAM;
6229 /* this is what a NT server returns for AddJob. AddJob must fail on
6230 * non-local printers */
6232 if (r->in.level != 1) {
6233 return WERR_UNKNOWN_LEVEL;
6236 return WERR_INVALID_PARAM;
6239 /****************************************************************************
6240 fill_job_info1
6241 ****************************************************************************/
6243 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6244 struct spoolss_JobInfo1 *r,
6245 const print_queue_struct *queue,
6246 int position, int snum,
6247 struct spoolss_PrinterInfo2 *pinfo2)
6249 struct tm *t;
6251 t = gmtime(&queue->time);
6253 r->job_id = queue->job;
6255 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6256 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6257 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6258 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6259 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6260 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6261 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6262 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6263 r->data_type = talloc_strdup(mem_ctx, "RAW");
6264 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6265 r->text_status = talloc_strdup(mem_ctx, "");
6266 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6268 r->status = nt_printj_status(queue->status);
6269 r->priority = queue->priority;
6270 r->position = position;
6271 r->total_pages = queue->page_count;
6272 r->pages_printed = 0; /* ??? */
6274 init_systemtime(&r->submitted, t);
6276 return WERR_OK;
6279 /****************************************************************************
6280 fill_job_info2
6281 ****************************************************************************/
6283 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6284 struct spoolss_JobInfo2 *r,
6285 const print_queue_struct *queue,
6286 int position, int snum,
6287 struct spoolss_PrinterInfo2 *pinfo2,
6288 struct spoolss_DeviceMode *devmode)
6290 struct tm *t;
6292 t = gmtime(&queue->time);
6294 r->job_id = queue->job;
6296 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6297 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6298 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6299 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6300 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6301 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6302 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6303 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6304 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6305 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6306 r->data_type = talloc_strdup(mem_ctx, "RAW");
6307 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6308 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6309 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6310 r->parameters = talloc_strdup(mem_ctx, "");
6311 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6312 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6313 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6315 r->devmode = devmode;
6317 r->text_status = talloc_strdup(mem_ctx, "");
6318 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6320 r->secdesc = NULL;
6322 r->status = nt_printj_status(queue->status);
6323 r->priority = queue->priority;
6324 r->position = position;
6325 r->start_time = 0;
6326 r->until_time = 0;
6327 r->total_pages = queue->page_count;
6328 r->size = queue->size;
6329 init_systemtime(&r->submitted, t);
6330 r->time = 0;
6331 r->pages_printed = 0; /* ??? */
6333 return WERR_OK;
6336 /****************************************************************************
6337 fill_job_info3
6338 ****************************************************************************/
6340 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6341 struct spoolss_JobInfo3 *r,
6342 const print_queue_struct *queue,
6343 const print_queue_struct *next_queue,
6344 int position, int snum,
6345 struct spoolss_PrinterInfo2 *pinfo2)
6347 r->job_id = queue->job;
6348 r->next_job_id = 0;
6349 if (next_queue) {
6350 r->next_job_id = next_queue->job;
6352 r->reserved = 0;
6354 return WERR_OK;
6357 /****************************************************************************
6358 Enumjobs at level 1.
6359 ****************************************************************************/
6361 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6362 const print_queue_struct *queue,
6363 uint32_t num_queues, int snum,
6364 struct spoolss_PrinterInfo2 *pinfo2,
6365 union spoolss_JobInfo **info_p,
6366 uint32_t *count)
6368 union spoolss_JobInfo *info;
6369 int i;
6370 WERROR result = WERR_OK;
6372 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6373 W_ERROR_HAVE_NO_MEMORY(info);
6375 *count = num_queues;
6377 for (i=0; i<*count; i++) {
6378 result = fill_job_info1(info,
6379 &info[i].info1,
6380 &queue[i],
6382 snum,
6383 pinfo2);
6384 if (!W_ERROR_IS_OK(result)) {
6385 goto out;
6389 out:
6390 if (!W_ERROR_IS_OK(result)) {
6391 TALLOC_FREE(info);
6392 *count = 0;
6393 return result;
6396 *info_p = info;
6398 return WERR_OK;
6401 /****************************************************************************
6402 Enumjobs at level 2.
6403 ****************************************************************************/
6405 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6406 const print_queue_struct *queue,
6407 uint32_t num_queues, int snum,
6408 struct spoolss_PrinterInfo2 *pinfo2,
6409 union spoolss_JobInfo **info_p,
6410 uint32_t *count)
6412 union spoolss_JobInfo *info;
6413 int i;
6414 WERROR result = WERR_OK;
6416 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6417 W_ERROR_HAVE_NO_MEMORY(info);
6419 *count = num_queues;
6421 for (i=0; i<*count; i++) {
6422 struct spoolss_DeviceMode *devmode;
6424 result = spoolss_create_default_devmode(info,
6425 pinfo2->printername,
6426 &devmode);
6427 if (!W_ERROR_IS_OK(result)) {
6428 DEBUG(3, ("Can't proceed w/o a devmode!"));
6429 goto out;
6432 result = fill_job_info2(info,
6433 &info[i].info2,
6434 &queue[i],
6436 snum,
6437 pinfo2,
6438 devmode);
6439 if (!W_ERROR_IS_OK(result)) {
6440 goto out;
6444 out:
6445 if (!W_ERROR_IS_OK(result)) {
6446 TALLOC_FREE(info);
6447 *count = 0;
6448 return result;
6451 *info_p = info;
6453 return WERR_OK;
6456 /****************************************************************************
6457 Enumjobs at level 3.
6458 ****************************************************************************/
6460 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6461 const print_queue_struct *queue,
6462 uint32_t num_queues, int snum,
6463 struct spoolss_PrinterInfo2 *pinfo2,
6464 union spoolss_JobInfo **info_p,
6465 uint32_t *count)
6467 union spoolss_JobInfo *info;
6468 int i;
6469 WERROR result = WERR_OK;
6471 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6472 W_ERROR_HAVE_NO_MEMORY(info);
6474 *count = num_queues;
6476 for (i=0; i<*count; i++) {
6477 const print_queue_struct *next_queue = NULL;
6479 if (i+1 < *count) {
6480 next_queue = &queue[i+1];
6483 result = fill_job_info3(info,
6484 &info[i].info3,
6485 &queue[i],
6486 next_queue,
6488 snum,
6489 pinfo2);
6490 if (!W_ERROR_IS_OK(result)) {
6491 goto out;
6495 out:
6496 if (!W_ERROR_IS_OK(result)) {
6497 TALLOC_FREE(info);
6498 *count = 0;
6499 return result;
6502 *info_p = info;
6504 return WERR_OK;
6507 /****************************************************************
6508 _spoolss_EnumJobs
6509 ****************************************************************/
6511 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6512 struct spoolss_EnumJobs *r)
6514 WERROR result;
6515 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6516 int snum;
6517 print_status_struct prt_status;
6518 print_queue_struct *queue = NULL;
6519 uint32_t count;
6521 /* that's an [in out] buffer */
6523 if (!r->in.buffer && (r->in.offered != 0)) {
6524 return WERR_INVALID_PARAM;
6527 DEBUG(4,("_spoolss_EnumJobs\n"));
6529 *r->out.needed = 0;
6530 *r->out.count = 0;
6531 *r->out.info = NULL;
6533 /* lookup the printer snum and tdb entry */
6535 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6536 return WERR_BADFID;
6539 result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
6540 lp_servicename(snum), &pinfo2);
6541 if (!W_ERROR_IS_OK(result)) {
6542 return result;
6545 count = print_queue_status(snum, &queue, &prt_status);
6546 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6547 count, prt_status.status, prt_status.message));
6549 if (count == 0) {
6550 SAFE_FREE(queue);
6551 TALLOC_FREE(pinfo2);
6552 return WERR_OK;
6555 switch (r->in.level) {
6556 case 1:
6557 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6558 pinfo2, r->out.info, r->out.count);
6559 break;
6560 case 2:
6561 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6562 pinfo2, r->out.info, r->out.count);
6563 break;
6564 case 3:
6565 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6566 pinfo2, r->out.info, r->out.count);
6567 break;
6568 default:
6569 result = WERR_UNKNOWN_LEVEL;
6570 break;
6573 SAFE_FREE(queue);
6574 TALLOC_FREE(pinfo2);
6576 if (!W_ERROR_IS_OK(result)) {
6577 return result;
6580 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6581 spoolss_EnumJobs,
6582 *r->out.info, r->in.level,
6583 *r->out.count);
6584 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6585 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6587 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6590 /****************************************************************
6591 _spoolss_ScheduleJob
6592 ****************************************************************/
6594 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
6595 struct spoolss_ScheduleJob *r)
6597 return WERR_OK;
6600 /****************************************************************
6601 ****************************************************************/
6603 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6604 const char *printer_name,
6605 uint32_t job_id,
6606 struct spoolss_SetJobInfo1 *r)
6608 char *old_doc_name;
6610 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6611 return WERR_BADFID;
6614 if (strequal(old_doc_name, r->document_name)) {
6615 return WERR_OK;
6618 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6619 return WERR_BADFID;
6622 return WERR_OK;
6625 /****************************************************************
6626 _spoolss_SetJob
6627 ****************************************************************/
6629 WERROR _spoolss_SetJob(struct pipes_struct *p,
6630 struct spoolss_SetJob *r)
6632 int snum;
6633 WERROR errcode = WERR_BADFUNC;
6635 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6636 return WERR_BADFID;
6639 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6640 return WERR_INVALID_PRINTER_NAME;
6643 switch (r->in.command) {
6644 case SPOOLSS_JOB_CONTROL_CANCEL:
6645 case SPOOLSS_JOB_CONTROL_DELETE:
6646 errcode = print_job_delete(p->server_info,
6647 snum, r->in.job_id);
6648 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6649 errcode = WERR_OK;
6651 break;
6652 case SPOOLSS_JOB_CONTROL_PAUSE:
6653 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6654 errcode = WERR_OK;
6656 break;
6657 case SPOOLSS_JOB_CONTROL_RESTART:
6658 case SPOOLSS_JOB_CONTROL_RESUME:
6659 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6660 errcode = WERR_OK;
6662 break;
6663 case 0:
6664 errcode = WERR_OK;
6665 break;
6666 default:
6667 return WERR_UNKNOWN_LEVEL;
6670 if (!W_ERROR_IS_OK(errcode)) {
6671 return errcode;
6674 if (r->in.ctr == NULL) {
6675 return errcode;
6678 switch (r->in.ctr->level) {
6679 case 1:
6680 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6681 r->in.job_id,
6682 r->in.ctr->info.info1);
6683 break;
6684 case 2:
6685 case 3:
6686 case 4:
6687 default:
6688 return WERR_UNKNOWN_LEVEL;
6691 return errcode;
6694 /****************************************************************************
6695 Enumerates all printer drivers by level and architecture.
6696 ****************************************************************************/
6698 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6699 struct auth_serversupplied_info *server_info,
6700 const char *servername,
6701 const char *architecture,
6702 uint32_t level,
6703 union spoolss_DriverInfo **info_p,
6704 uint32_t *count_p)
6706 int i;
6707 uint32_t version;
6708 struct spoolss_DriverInfo8 *driver;
6709 union spoolss_DriverInfo *info = NULL;
6710 uint32_t count = 0;
6711 WERROR result = WERR_OK;
6712 uint32_t num_drivers;
6713 const char **drivers;
6715 *count_p = 0;
6716 *info_p = NULL;
6718 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6719 result = winreg_get_driver_list(mem_ctx, server_info,
6720 architecture, version,
6721 &num_drivers, &drivers);
6722 if (!W_ERROR_IS_OK(result)) {
6723 goto out;
6725 DEBUG(4, ("we have:[%d] drivers in environment"
6726 " [%s] and version [%d]\n",
6727 num_drivers, architecture, version));
6729 if (num_drivers != 0) {
6730 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6731 union spoolss_DriverInfo,
6732 count + num_drivers);
6733 if (!info) {
6734 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6735 "failed to enlarge driver info buffer!\n"));
6736 result = WERR_NOMEM;
6737 goto out;
6741 for (i = 0; i < num_drivers; i++) {
6742 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6744 result = winreg_get_driver(mem_ctx, server_info,
6745 architecture, drivers[i],
6746 version, &driver);
6747 if (!W_ERROR_IS_OK(result)) {
6748 goto out;
6751 switch (level) {
6752 case 1:
6753 result = fill_printer_driver_info1(info, &info[count+i].info1,
6754 driver, servername);
6755 break;
6756 case 2:
6757 result = fill_printer_driver_info2(info, &info[count+i].info2,
6758 driver, servername);
6759 break;
6760 case 3:
6761 result = fill_printer_driver_info3(info, &info[count+i].info3,
6762 driver, servername);
6763 break;
6764 case 4:
6765 result = fill_printer_driver_info4(info, &info[count+i].info4,
6766 driver, servername);
6767 break;
6768 case 5:
6769 result = fill_printer_driver_info5(info, &info[count+i].info5,
6770 driver, servername);
6771 break;
6772 case 6:
6773 result = fill_printer_driver_info6(info, &info[count+i].info6,
6774 driver, servername);
6775 break;
6776 case 8:
6777 result = fill_printer_driver_info8(info, &info[count+i].info8,
6778 driver, servername);
6779 break;
6780 default:
6781 result = WERR_UNKNOWN_LEVEL;
6782 break;
6785 TALLOC_FREE(driver);
6787 if (!W_ERROR_IS_OK(result)) {
6788 goto out;
6792 count += num_drivers;
6793 TALLOC_FREE(drivers);
6796 out:
6797 TALLOC_FREE(drivers);
6799 if (!W_ERROR_IS_OK(result)) {
6800 TALLOC_FREE(info);
6801 return result;
6804 *info_p = info;
6805 *count_p = count;
6807 return WERR_OK;
6810 /****************************************************************************
6811 Enumerates all printer drivers by level.
6812 ****************************************************************************/
6814 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6815 struct auth_serversupplied_info *server_info,
6816 const char *servername,
6817 const char *architecture,
6818 uint32_t level,
6819 union spoolss_DriverInfo **info_p,
6820 uint32_t *count_p)
6822 uint32_t a,i;
6823 WERROR result = WERR_OK;
6825 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6827 for (a=0; archi_table[a].long_archi != NULL; a++) {
6829 union spoolss_DriverInfo *info = NULL;
6830 uint32_t count = 0;
6832 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6833 server_info,
6834 servername,
6835 archi_table[a].long_archi,
6836 level,
6837 &info,
6838 &count);
6839 if (!W_ERROR_IS_OK(result)) {
6840 continue;
6843 for (i=0; i < count; i++) {
6844 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6845 info[i], info_p, count_p);
6849 return result;
6852 return enumprinterdrivers_level_by_architecture(mem_ctx,
6853 server_info,
6854 servername,
6855 architecture,
6856 level,
6857 info_p,
6858 count_p);
6861 /****************************************************************
6862 _spoolss_EnumPrinterDrivers
6863 ****************************************************************/
6865 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
6866 struct spoolss_EnumPrinterDrivers *r)
6868 const char *cservername;
6869 WERROR result;
6871 /* that's an [in out] buffer */
6873 if (!r->in.buffer && (r->in.offered != 0)) {
6874 return WERR_INVALID_PARAM;
6877 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6879 *r->out.needed = 0;
6880 *r->out.count = 0;
6881 *r->out.info = NULL;
6883 cservername = canon_servername(r->in.server);
6885 if (!is_myname_or_ipaddr(cservername)) {
6886 return WERR_UNKNOWN_PRINTER_DRIVER;
6889 result = enumprinterdrivers_level(p->mem_ctx,
6890 p->server_info,
6891 cservername,
6892 r->in.environment,
6893 r->in.level,
6894 r->out.info,
6895 r->out.count);
6896 if (!W_ERROR_IS_OK(result)) {
6897 return result;
6900 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6901 spoolss_EnumPrinterDrivers,
6902 *r->out.info, r->in.level,
6903 *r->out.count);
6904 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6905 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6907 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6910 /****************************************************************
6911 _spoolss_EnumForms
6912 ****************************************************************/
6914 WERROR _spoolss_EnumForms(struct pipes_struct *p,
6915 struct spoolss_EnumForms *r)
6917 WERROR result;
6919 *r->out.count = 0;
6920 *r->out.needed = 0;
6921 *r->out.info = NULL;
6923 /* that's an [in out] buffer */
6925 if (!r->in.buffer && (r->in.offered != 0) ) {
6926 return WERR_INVALID_PARAM;
6929 DEBUG(4,("_spoolss_EnumForms\n"));
6930 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6931 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6933 switch (r->in.level) {
6934 case 1:
6935 result = winreg_printer_enumforms1(p->mem_ctx,
6936 p->server_info,
6937 r->out.count,
6938 r->out.info);
6939 break;
6940 default:
6941 result = WERR_UNKNOWN_LEVEL;
6942 break;
6945 if (!W_ERROR_IS_OK(result)) {
6946 return result;
6949 if (*r->out.count == 0) {
6950 return WERR_NO_MORE_ITEMS;
6953 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6954 spoolss_EnumForms,
6955 *r->out.info, r->in.level,
6956 *r->out.count);
6957 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6958 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6960 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6963 /****************************************************************
6964 _spoolss_GetForm
6965 ****************************************************************/
6967 WERROR _spoolss_GetForm(struct pipes_struct *p,
6968 struct spoolss_GetForm *r)
6970 WERROR result;
6972 /* that's an [in out] buffer */
6974 if (!r->in.buffer && (r->in.offered != 0)) {
6975 return WERR_INVALID_PARAM;
6978 DEBUG(4,("_spoolss_GetForm\n"));
6979 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6980 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6982 switch (r->in.level) {
6983 case 1:
6984 result = winreg_printer_getform1(p->mem_ctx,
6985 p->server_info,
6986 r->in.form_name,
6987 &r->out.info->info1);
6988 break;
6989 default:
6990 result = WERR_UNKNOWN_LEVEL;
6991 break;
6994 if (!W_ERROR_IS_OK(result)) {
6995 TALLOC_FREE(r->out.info);
6996 return result;
6999 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7000 r->out.info, r->in.level);
7001 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7003 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7006 /****************************************************************************
7007 ****************************************************************************/
7009 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7010 struct spoolss_PortInfo1 *r,
7011 const char *name)
7013 r->port_name = talloc_strdup(mem_ctx, name);
7014 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7016 return WERR_OK;
7019 /****************************************************************************
7020 TODO: This probably needs distinguish between TCP/IP and Local ports
7021 somehow.
7022 ****************************************************************************/
7024 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7025 struct spoolss_PortInfo2 *r,
7026 const char *name)
7028 r->port_name = talloc_strdup(mem_ctx, name);
7029 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7031 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7032 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7034 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7035 W_ERROR_HAVE_NO_MEMORY(r->description);
7037 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7038 r->reserved = 0;
7040 return WERR_OK;
7044 /****************************************************************************
7045 wrapper around the enumer ports command
7046 ****************************************************************************/
7048 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7050 char *cmd = lp_enumports_cmd();
7051 char **qlines = NULL;
7052 char *command = NULL;
7053 int numlines;
7054 int ret;
7055 int fd;
7057 *count = 0;
7058 *lines = NULL;
7060 /* if no hook then just fill in the default port */
7062 if ( !*cmd ) {
7063 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7064 return WERR_NOMEM;
7066 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7067 TALLOC_FREE(qlines);
7068 return WERR_NOMEM;
7070 qlines[1] = NULL;
7071 numlines = 1;
7073 else {
7074 /* we have a valid enumport command */
7076 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7077 if (!command) {
7078 return WERR_NOMEM;
7081 DEBUG(10,("Running [%s]\n", command));
7082 ret = smbrun(command, &fd);
7083 DEBUG(10,("Returned [%d]\n", ret));
7084 TALLOC_FREE(command);
7085 if (ret != 0) {
7086 if (fd != -1) {
7087 close(fd);
7089 return WERR_ACCESS_DENIED;
7092 numlines = 0;
7093 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7094 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7095 close(fd);
7098 *count = numlines;
7099 *lines = qlines;
7101 return WERR_OK;
7104 /****************************************************************************
7105 enumports level 1.
7106 ****************************************************************************/
7108 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7109 union spoolss_PortInfo **info_p,
7110 uint32_t *count)
7112 union spoolss_PortInfo *info = NULL;
7113 int i=0;
7114 WERROR result = WERR_OK;
7115 char **qlines = NULL;
7116 int numlines = 0;
7118 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7119 if (!W_ERROR_IS_OK(result)) {
7120 goto out;
7123 if (numlines) {
7124 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7125 if (!info) {
7126 DEBUG(10,("Returning WERR_NOMEM\n"));
7127 result = WERR_NOMEM;
7128 goto out;
7131 for (i=0; i<numlines; i++) {
7132 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7133 result = fill_port_1(info, &info[i].info1, qlines[i]);
7134 if (!W_ERROR_IS_OK(result)) {
7135 goto out;
7139 TALLOC_FREE(qlines);
7141 out:
7142 if (!W_ERROR_IS_OK(result)) {
7143 TALLOC_FREE(info);
7144 TALLOC_FREE(qlines);
7145 *count = 0;
7146 *info_p = NULL;
7147 return result;
7150 *info_p = info;
7151 *count = numlines;
7153 return WERR_OK;
7156 /****************************************************************************
7157 enumports level 2.
7158 ****************************************************************************/
7160 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7161 union spoolss_PortInfo **info_p,
7162 uint32_t *count)
7164 union spoolss_PortInfo *info = NULL;
7165 int i=0;
7166 WERROR result = WERR_OK;
7167 char **qlines = NULL;
7168 int numlines = 0;
7170 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7171 if (!W_ERROR_IS_OK(result)) {
7172 goto out;
7175 if (numlines) {
7176 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7177 if (!info) {
7178 DEBUG(10,("Returning WERR_NOMEM\n"));
7179 result = WERR_NOMEM;
7180 goto out;
7183 for (i=0; i<numlines; i++) {
7184 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7185 result = fill_port_2(info, &info[i].info2, qlines[i]);
7186 if (!W_ERROR_IS_OK(result)) {
7187 goto out;
7191 TALLOC_FREE(qlines);
7193 out:
7194 if (!W_ERROR_IS_OK(result)) {
7195 TALLOC_FREE(info);
7196 TALLOC_FREE(qlines);
7197 *count = 0;
7198 *info_p = NULL;
7199 return result;
7202 *info_p = info;
7203 *count = numlines;
7205 return WERR_OK;
7208 /****************************************************************
7209 _spoolss_EnumPorts
7210 ****************************************************************/
7212 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7213 struct spoolss_EnumPorts *r)
7215 WERROR result;
7217 /* that's an [in out] buffer */
7219 if (!r->in.buffer && (r->in.offered != 0)) {
7220 return WERR_INVALID_PARAM;
7223 DEBUG(4,("_spoolss_EnumPorts\n"));
7225 *r->out.count = 0;
7226 *r->out.needed = 0;
7227 *r->out.info = NULL;
7229 switch (r->in.level) {
7230 case 1:
7231 result = enumports_level_1(p->mem_ctx, r->out.info,
7232 r->out.count);
7233 break;
7234 case 2:
7235 result = enumports_level_2(p->mem_ctx, r->out.info,
7236 r->out.count);
7237 break;
7238 default:
7239 return WERR_UNKNOWN_LEVEL;
7242 if (!W_ERROR_IS_OK(result)) {
7243 return result;
7246 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7247 spoolss_EnumPorts,
7248 *r->out.info, r->in.level,
7249 *r->out.count);
7250 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7251 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7253 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7256 /****************************************************************************
7257 ****************************************************************************/
7259 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7260 const char *server,
7261 struct spoolss_SetPrinterInfoCtr *info_ctr,
7262 struct spoolss_DeviceMode *devmode,
7263 struct security_descriptor *secdesc,
7264 struct spoolss_UserLevelCtr *user_ctr,
7265 struct policy_handle *handle)
7267 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7268 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7269 int snum;
7270 WERROR err = WERR_OK;
7272 /* samba does not have a concept of local, non-shared printers yet, so
7273 * make sure we always setup sharename - gd */
7274 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7275 (info2->printername != NULL && info2->printername[0] != '\0')) {
7276 DEBUG(5, ("spoolss_addprinterex_level_2: "
7277 "no sharename has been set, setting printername %s as sharename\n",
7278 info2->printername));
7279 info2->sharename = info2->printername;
7282 /* check to see if the printer already exists */
7283 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7284 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7285 info2->sharename));
7286 return WERR_PRINTER_ALREADY_EXISTS;
7289 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7290 if ((snum = print_queue_snum(info2->printername)) != -1) {
7291 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7292 info2->printername));
7293 return WERR_PRINTER_ALREADY_EXISTS;
7297 /* validate printer info struct */
7298 if (!info2->printername || strlen(info2->printername) == 0) {
7299 return WERR_INVALID_PRINTER_NAME;
7301 if (!info2->portname || strlen(info2->portname) == 0) {
7302 return WERR_UNKNOWN_PORT;
7304 if (!info2->drivername || strlen(info2->drivername) == 0) {
7305 return WERR_UNKNOWN_PRINTER_DRIVER;
7307 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7308 return WERR_UNKNOWN_PRINTPROCESSOR;
7311 /* FIXME!!! smbd should check to see if the driver is installed before
7312 trying to add a printer like this --jerry */
7314 if (*lp_addprinter_cmd() ) {
7315 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7316 info2, p->client_address) ) {
7317 return WERR_ACCESS_DENIED;
7319 } else {
7320 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7321 "smb.conf parameter \"addprinter command\" is defined. This"
7322 "parameter must exist for this call to succeed\n",
7323 info2->sharename ));
7326 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7327 return WERR_ACCESS_DENIED;
7330 /* you must be a printer admin to add a new printer */
7331 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7332 return WERR_ACCESS_DENIED;
7336 * Do sanity check on the requested changes for Samba.
7339 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7340 return WERR_INVALID_PARAM;
7343 if (devmode == NULL) {
7344 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7347 update_dsspooler(p->mem_ctx,
7348 p->server_info,
7350 info2,
7351 NULL);
7353 err = winreg_update_printer(p->mem_ctx,
7354 p->server_info,
7355 info2->sharename,
7356 info2_mask,
7357 info2,
7358 devmode,
7359 secdesc);
7360 if (!W_ERROR_IS_OK(err)) {
7361 return err;
7364 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7365 /* Handle open failed - remove addition. */
7366 ZERO_STRUCTP(handle);
7367 return WERR_ACCESS_DENIED;
7370 return WERR_OK;
7373 /****************************************************************
7374 _spoolss_AddPrinterEx
7375 ****************************************************************/
7377 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7378 struct spoolss_AddPrinterEx *r)
7380 switch (r->in.info_ctr->level) {
7381 case 1:
7382 /* we don't handle yet */
7383 /* but I know what to do ... */
7384 return WERR_UNKNOWN_LEVEL;
7385 case 2:
7386 return spoolss_addprinterex_level_2(p, r->in.server,
7387 r->in.info_ctr,
7388 r->in.devmode_ctr->devmode,
7389 r->in.secdesc_ctr->sd,
7390 r->in.userlevel_ctr,
7391 r->out.handle);
7392 default:
7393 return WERR_UNKNOWN_LEVEL;
7397 /****************************************************************
7398 _spoolss_AddPrinter
7399 ****************************************************************/
7401 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7402 struct spoolss_AddPrinter *r)
7404 struct spoolss_AddPrinterEx a;
7405 struct spoolss_UserLevelCtr userlevel_ctr;
7407 ZERO_STRUCT(userlevel_ctr);
7409 userlevel_ctr.level = 1;
7411 a.in.server = r->in.server;
7412 a.in.info_ctr = r->in.info_ctr;
7413 a.in.devmode_ctr = r->in.devmode_ctr;
7414 a.in.secdesc_ctr = r->in.secdesc_ctr;
7415 a.in.userlevel_ctr = &userlevel_ctr;
7416 a.out.handle = r->out.handle;
7418 return _spoolss_AddPrinterEx(p, &a);
7421 /****************************************************************
7422 _spoolss_AddPrinterDriverEx
7423 ****************************************************************/
7425 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7426 struct spoolss_AddPrinterDriverEx *r)
7428 WERROR err = WERR_OK;
7429 const char *driver_name = NULL;
7430 uint32_t version;
7431 const char *fn;
7433 switch (p->opnum) {
7434 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7435 fn = "_spoolss_AddPrinterDriver";
7436 break;
7437 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7438 fn = "_spoolss_AddPrinterDriverEx";
7439 break;
7440 default:
7441 return WERR_INVALID_PARAM;
7445 * we only support the semantics of AddPrinterDriver()
7446 * i.e. only copy files that are newer than existing ones
7449 if (r->in.flags == 0) {
7450 return WERR_INVALID_PARAM;
7453 if (r->in.flags != APD_COPY_NEW_FILES) {
7454 return WERR_ACCESS_DENIED;
7457 /* FIXME */
7458 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7459 /* Clever hack from Martin Zielinski <mz@seh.de>
7460 * to allow downgrade from level 8 (Vista).
7462 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7463 r->in.info_ctr->level));
7464 return WERR_UNKNOWN_LEVEL;
7467 DEBUG(5,("Cleaning driver's information\n"));
7468 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7469 if (!W_ERROR_IS_OK(err))
7470 goto done;
7472 DEBUG(5,("Moving driver to final destination\n"));
7473 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7474 &err)) ) {
7475 goto done;
7478 err = winreg_add_driver(p->mem_ctx, p->server_info,
7479 r->in.info_ctr, &driver_name, &version);
7480 if (!W_ERROR_IS_OK(err)) {
7481 goto done;
7485 * I think this is where he DrvUpgradePrinter() hook would be
7486 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7487 * server. Right now, we just need to send ourselves a message
7488 * to update each printer bound to this driver. --jerry
7491 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7492 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7493 fn, driver_name));
7496 done:
7497 return err;
7500 /****************************************************************
7501 _spoolss_AddPrinterDriver
7502 ****************************************************************/
7504 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7505 struct spoolss_AddPrinterDriver *r)
7507 struct spoolss_AddPrinterDriverEx a;
7509 switch (r->in.info_ctr->level) {
7510 case 2:
7511 case 3:
7512 case 4:
7513 case 5:
7514 break;
7515 default:
7516 return WERR_UNKNOWN_LEVEL;
7519 a.in.servername = r->in.servername;
7520 a.in.info_ctr = r->in.info_ctr;
7521 a.in.flags = APD_COPY_NEW_FILES;
7523 return _spoolss_AddPrinterDriverEx(p, &a);
7526 /****************************************************************************
7527 ****************************************************************************/
7529 struct _spoolss_paths {
7530 int type;
7531 const char *share;
7532 const char *dir;
7535 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7537 static const struct _spoolss_paths spoolss_paths[]= {
7538 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7539 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7542 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7543 const char *servername,
7544 const char *environment,
7545 int component,
7546 char **path)
7548 const char *pservername = NULL;
7549 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7550 const char *short_archi;
7552 *path = NULL;
7554 /* environment may be empty */
7555 if (environment && strlen(environment)) {
7556 long_archi = environment;
7559 /* servername may be empty */
7560 if (servername && strlen(servername)) {
7561 pservername = canon_servername(servername);
7563 if (!is_myname_or_ipaddr(pservername)) {
7564 return WERR_INVALID_PARAM;
7568 if (!(short_archi = get_short_archi(long_archi))) {
7569 return WERR_INVALID_ENVIRONMENT;
7572 switch (component) {
7573 case SPOOLSS_PRTPROCS_PATH:
7574 case SPOOLSS_DRIVER_PATH:
7575 if (pservername) {
7576 *path = talloc_asprintf(mem_ctx,
7577 "\\\\%s\\%s\\%s",
7578 pservername,
7579 spoolss_paths[component].share,
7580 short_archi);
7581 } else {
7582 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7583 SPOOLSS_DEFAULT_SERVER_PATH,
7584 spoolss_paths[component].dir,
7585 short_archi);
7587 break;
7588 default:
7589 return WERR_INVALID_PARAM;
7592 if (!*path) {
7593 return WERR_NOMEM;
7596 return WERR_OK;
7599 /****************************************************************************
7600 ****************************************************************************/
7602 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7603 const char *servername,
7604 const char *environment,
7605 struct spoolss_DriverDirectoryInfo1 *r)
7607 WERROR werr;
7608 char *path = NULL;
7610 werr = compose_spoolss_server_path(mem_ctx,
7611 servername,
7612 environment,
7613 SPOOLSS_DRIVER_PATH,
7614 &path);
7615 if (!W_ERROR_IS_OK(werr)) {
7616 return werr;
7619 DEBUG(4,("printer driver directory: [%s]\n", path));
7621 r->directory_name = path;
7623 return WERR_OK;
7626 /****************************************************************
7627 _spoolss_GetPrinterDriverDirectory
7628 ****************************************************************/
7630 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
7631 struct spoolss_GetPrinterDriverDirectory *r)
7633 WERROR werror;
7635 /* that's an [in out] buffer */
7637 if (!r->in.buffer && (r->in.offered != 0)) {
7638 return WERR_INVALID_PARAM;
7641 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7642 r->in.level));
7644 *r->out.needed = 0;
7646 /* r->in.level is ignored */
7648 werror = getprinterdriverdir_level_1(p->mem_ctx,
7649 r->in.server,
7650 r->in.environment,
7651 &r->out.info->info1);
7652 if (!W_ERROR_IS_OK(werror)) {
7653 TALLOC_FREE(r->out.info);
7654 return werror;
7657 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7658 r->out.info, r->in.level);
7659 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7661 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7664 /****************************************************************
7665 _spoolss_EnumPrinterData
7666 ****************************************************************/
7668 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
7669 struct spoolss_EnumPrinterData *r)
7671 WERROR result;
7672 struct spoolss_EnumPrinterDataEx r2;
7673 uint32_t count;
7674 struct spoolss_PrinterEnumValues *info, *val = NULL;
7675 uint32_t needed;
7677 r2.in.handle = r->in.handle;
7678 r2.in.key_name = "PrinterDriverData";
7679 r2.in.offered = 0;
7680 r2.out.count = &count;
7681 r2.out.info = &info;
7682 r2.out.needed = &needed;
7684 result = _spoolss_EnumPrinterDataEx(p, &r2);
7685 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7686 r2.in.offered = needed;
7687 result = _spoolss_EnumPrinterDataEx(p, &r2);
7689 if (!W_ERROR_IS_OK(result)) {
7690 return result;
7694 * The NT machine wants to know the biggest size of value and data
7696 * cf: MSDN EnumPrinterData remark section
7699 if (!r->in.value_offered && !r->in.data_offered) {
7700 uint32_t biggest_valuesize = 0;
7701 uint32_t biggest_datasize = 0;
7702 int i, name_length;
7704 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7706 for (i=0; i<count; i++) {
7708 name_length = strlen(info[i].value_name);
7709 if (strlen(info[i].value_name) > biggest_valuesize) {
7710 biggest_valuesize = name_length;
7713 if (info[i].data_length > biggest_datasize) {
7714 biggest_datasize = info[i].data_length;
7717 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7718 biggest_datasize));
7721 /* the value is an UNICODE string but real_value_size is the length
7722 in bytes including the trailing 0 */
7724 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7725 *r->out.data_needed = biggest_datasize;
7727 DEBUG(6,("final values: [%d], [%d]\n",
7728 *r->out.value_needed, *r->out.data_needed));
7730 return WERR_OK;
7733 if (r->in.enum_index < count) {
7734 val = &info[r->in.enum_index];
7737 if (val == NULL) {
7738 /* out_value should default to "" or else NT4 has
7739 problems unmarshalling the response */
7741 if (r->in.value_offered) {
7742 *r->out.value_needed = 1;
7743 r->out.value_name = talloc_strdup(r, "");
7744 if (!r->out.value_name) {
7745 return WERR_NOMEM;
7747 } else {
7748 r->out.value_name = NULL;
7749 *r->out.value_needed = 0;
7752 /* the data is counted in bytes */
7754 *r->out.data_needed = r->in.data_offered;
7756 result = WERR_NO_MORE_ITEMS;
7757 } else {
7759 * the value is:
7760 * - counted in bytes in the request
7761 * - counted in UNICODE chars in the max reply
7762 * - counted in bytes in the real size
7764 * take a pause *before* coding not *during* coding
7767 /* name */
7768 if (r->in.value_offered) {
7769 r->out.value_name = talloc_strdup(r, val->value_name);
7770 if (!r->out.value_name) {
7771 return WERR_NOMEM;
7773 *r->out.value_needed = val->value_name_len;
7774 } else {
7775 r->out.value_name = NULL;
7776 *r->out.value_needed = 0;
7779 /* type */
7781 *r->out.type = val->type;
7783 /* data - counted in bytes */
7786 * See the section "Dynamically Typed Query Parameters"
7787 * in MS-RPRN.
7790 if (r->out.data && val->data && val->data->data &&
7791 val->data_length && r->in.data_offered) {
7792 memcpy(r->out.data, val->data->data,
7793 MIN(val->data_length,r->in.data_offered));
7796 *r->out.data_needed = val->data_length;
7798 result = WERR_OK;
7801 return result;
7804 /****************************************************************
7805 _spoolss_SetPrinterData
7806 ****************************************************************/
7808 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
7809 struct spoolss_SetPrinterData *r)
7811 struct spoolss_SetPrinterDataEx r2;
7813 r2.in.handle = r->in.handle;
7814 r2.in.key_name = "PrinterDriverData";
7815 r2.in.value_name = r->in.value_name;
7816 r2.in.type = r->in.type;
7817 r2.in.data = r->in.data;
7818 r2.in.offered = r->in.offered;
7820 return _spoolss_SetPrinterDataEx(p, &r2);
7823 /****************************************************************
7824 _spoolss_ResetPrinter
7825 ****************************************************************/
7827 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
7828 struct spoolss_ResetPrinter *r)
7830 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7831 int snum;
7833 DEBUG(5,("_spoolss_ResetPrinter\n"));
7836 * All we do is to check to see if the handle and queue is valid.
7837 * This call really doesn't mean anything to us because we only
7838 * support RAW printing. --jerry
7841 if (!Printer) {
7842 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7843 OUR_HANDLE(r->in.handle)));
7844 return WERR_BADFID;
7847 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7848 return WERR_BADFID;
7851 /* blindly return success */
7852 return WERR_OK;
7855 /****************************************************************
7856 _spoolss_DeletePrinterData
7857 ****************************************************************/
7859 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
7860 struct spoolss_DeletePrinterData *r)
7862 struct spoolss_DeletePrinterDataEx r2;
7864 r2.in.handle = r->in.handle;
7865 r2.in.key_name = "PrinterDriverData";
7866 r2.in.value_name = r->in.value_name;
7868 return _spoolss_DeletePrinterDataEx(p, &r2);
7871 /****************************************************************
7872 _spoolss_AddForm
7873 ****************************************************************/
7875 WERROR _spoolss_AddForm(struct pipes_struct *p,
7876 struct spoolss_AddForm *r)
7878 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7879 int snum = -1;
7880 WERROR status = WERR_OK;
7881 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7883 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7885 DEBUG(5,("_spoolss_AddForm\n"));
7887 if (!Printer) {
7888 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7889 OUR_HANDLE(r->in.handle)));
7890 return WERR_BADFID;
7893 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7894 and not a printer admin, then fail */
7896 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7897 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7898 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7899 p->server_info->info3->base.domain.string,
7900 NULL,
7901 p->server_info->ptok,
7902 lp_printer_admin(snum))) {
7903 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7904 return WERR_ACCESS_DENIED;
7907 switch (form->flags) {
7908 case SPOOLSS_FORM_USER:
7909 case SPOOLSS_FORM_BUILTIN:
7910 case SPOOLSS_FORM_PRINTER:
7911 break;
7912 default:
7913 return WERR_INVALID_PARAM;
7916 status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7917 if (!W_ERROR_IS_OK(status)) {
7918 return status;
7922 * ChangeID must always be set if this is a printer
7924 if (Printer->printer_type == SPLHND_PRINTER) {
7925 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7926 return WERR_BADFID;
7929 status = winreg_printer_update_changeid(p->mem_ctx,
7930 p->server_info,
7931 lp_const_servicename(snum));
7932 if (!W_ERROR_IS_OK(status)) {
7933 return status;
7937 return status;
7940 /****************************************************************
7941 _spoolss_DeleteForm
7942 ****************************************************************/
7944 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
7945 struct spoolss_DeleteForm *r)
7947 const char *form_name = r->in.form_name;
7948 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7949 int snum = -1;
7950 WERROR status = WERR_OK;
7951 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7953 DEBUG(5,("_spoolss_DeleteForm\n"));
7955 if (!Printer) {
7956 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7957 OUR_HANDLE(r->in.handle)));
7958 return WERR_BADFID;
7961 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7962 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7963 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7964 p->server_info->info3->base.domain.string,
7965 NULL,
7966 p->server_info->ptok,
7967 lp_printer_admin(snum))) {
7968 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7969 return WERR_ACCESS_DENIED;
7972 status = winreg_printer_deleteform1(p->mem_ctx,
7973 p->server_info,
7974 form_name);
7975 if (!W_ERROR_IS_OK(status)) {
7976 return status;
7980 * ChangeID must always be set if this is a printer
7982 if (Printer->printer_type == SPLHND_PRINTER) {
7983 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7984 return WERR_BADFID;
7987 status = winreg_printer_update_changeid(p->mem_ctx,
7988 p->server_info,
7989 lp_const_servicename(snum));
7990 if (!W_ERROR_IS_OK(status)) {
7991 return status;
7995 return status;
7998 /****************************************************************
7999 _spoolss_SetForm
8000 ****************************************************************/
8002 WERROR _spoolss_SetForm(struct pipes_struct *p,
8003 struct spoolss_SetForm *r)
8005 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8006 const char *form_name = r->in.form_name;
8007 int snum = -1;
8008 WERROR status = WERR_OK;
8009 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8011 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8013 DEBUG(5,("_spoolss_SetForm\n"));
8015 if (!Printer) {
8016 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8017 OUR_HANDLE(r->in.handle)));
8018 return WERR_BADFID;
8021 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8022 and not a printer admin, then fail */
8024 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8025 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8026 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8027 p->server_info->info3->base.domain.string,
8028 NULL,
8029 p->server_info->ptok,
8030 lp_printer_admin(snum))) {
8031 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8032 return WERR_ACCESS_DENIED;
8035 status = winreg_printer_setform1(p->mem_ctx,
8036 p->server_info,
8037 form_name,
8038 form);
8039 if (!W_ERROR_IS_OK(status)) {
8040 return status;
8044 * ChangeID must always be set if this is a printer
8046 if (Printer->printer_type == SPLHND_PRINTER) {
8047 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8048 return WERR_BADFID;
8051 status = winreg_printer_update_changeid(p->mem_ctx,
8052 p->server_info,
8053 lp_const_servicename(snum));
8054 if (!W_ERROR_IS_OK(status)) {
8055 return status;
8059 return status;
8062 /****************************************************************************
8063 fill_print_processor1
8064 ****************************************************************************/
8066 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8067 struct spoolss_PrintProcessorInfo1 *r,
8068 const char *print_processor_name)
8070 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8071 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8073 return WERR_OK;
8076 /****************************************************************************
8077 enumprintprocessors level 1.
8078 ****************************************************************************/
8080 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8081 union spoolss_PrintProcessorInfo **info_p,
8082 uint32_t *count)
8084 union spoolss_PrintProcessorInfo *info;
8085 WERROR result;
8087 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8088 W_ERROR_HAVE_NO_MEMORY(info);
8090 *count = 1;
8092 result = fill_print_processor1(info, &info[0].info1, "winprint");
8093 if (!W_ERROR_IS_OK(result)) {
8094 goto out;
8097 out:
8098 if (!W_ERROR_IS_OK(result)) {
8099 TALLOC_FREE(info);
8100 *count = 0;
8101 return result;
8104 *info_p = info;
8106 return WERR_OK;
8109 /****************************************************************
8110 _spoolss_EnumPrintProcessors
8111 ****************************************************************/
8113 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8114 struct spoolss_EnumPrintProcessors *r)
8116 WERROR result;
8118 /* that's an [in out] buffer */
8120 if (!r->in.buffer && (r->in.offered != 0)) {
8121 return WERR_INVALID_PARAM;
8124 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8127 * Enumerate the print processors ...
8129 * Just reply with "winprint", to keep NT happy
8130 * and I can use my nice printer checker.
8133 *r->out.count = 0;
8134 *r->out.needed = 0;
8135 *r->out.info = NULL;
8137 if (!get_short_archi(r->in.environment)) {
8138 return WERR_INVALID_ENVIRONMENT;
8141 switch (r->in.level) {
8142 case 1:
8143 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8144 r->out.count);
8145 break;
8146 default:
8147 return WERR_UNKNOWN_LEVEL;
8150 if (!W_ERROR_IS_OK(result)) {
8151 return result;
8154 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8155 spoolss_EnumPrintProcessors,
8156 *r->out.info, r->in.level,
8157 *r->out.count);
8158 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8159 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8161 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8164 /****************************************************************************
8165 fill_printprocdatatype1
8166 ****************************************************************************/
8168 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8169 struct spoolss_PrintProcDataTypesInfo1 *r,
8170 const char *name_array)
8172 r->name_array = talloc_strdup(mem_ctx, name_array);
8173 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8175 return WERR_OK;
8178 /****************************************************************************
8179 enumprintprocdatatypes level 1.
8180 ****************************************************************************/
8182 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8183 union spoolss_PrintProcDataTypesInfo **info_p,
8184 uint32_t *count)
8186 WERROR result;
8187 union spoolss_PrintProcDataTypesInfo *info;
8189 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8190 W_ERROR_HAVE_NO_MEMORY(info);
8192 *count = 1;
8194 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8195 if (!W_ERROR_IS_OK(result)) {
8196 goto out;
8199 out:
8200 if (!W_ERROR_IS_OK(result)) {
8201 TALLOC_FREE(info);
8202 *count = 0;
8203 return result;
8206 *info_p = info;
8208 return WERR_OK;
8211 /****************************************************************
8212 _spoolss_EnumPrintProcDataTypes
8213 ****************************************************************/
8215 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8216 struct spoolss_EnumPrintProcDataTypes *r)
8218 WERROR result;
8220 /* that's an [in out] buffer */
8222 if (!r->in.buffer && (r->in.offered != 0)) {
8223 return WERR_INVALID_PARAM;
8226 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8228 *r->out.count = 0;
8229 *r->out.needed = 0;
8230 *r->out.info = NULL;
8232 if (r->in.print_processor_name == NULL ||
8233 !strequal(r->in.print_processor_name, "winprint")) {
8234 return WERR_UNKNOWN_PRINTPROCESSOR;
8237 switch (r->in.level) {
8238 case 1:
8239 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8240 r->out.count);
8241 break;
8242 default:
8243 return WERR_UNKNOWN_LEVEL;
8246 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8247 spoolss_EnumPrintProcDataTypes,
8248 *r->out.info, r->in.level,
8249 *r->out.count);
8250 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8251 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8253 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8256 /****************************************************************************
8257 fill_monitor_1
8258 ****************************************************************************/
8260 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8261 struct spoolss_MonitorInfo1 *r,
8262 const char *monitor_name)
8264 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8265 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8267 return WERR_OK;
8270 /****************************************************************************
8271 fill_monitor_2
8272 ****************************************************************************/
8274 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8275 struct spoolss_MonitorInfo2 *r,
8276 const char *monitor_name,
8277 const char *environment,
8278 const char *dll_name)
8280 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8281 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8282 r->environment = talloc_strdup(mem_ctx, environment);
8283 W_ERROR_HAVE_NO_MEMORY(r->environment);
8284 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8285 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8287 return WERR_OK;
8290 /****************************************************************************
8291 enumprintmonitors level 1.
8292 ****************************************************************************/
8294 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8295 union spoolss_MonitorInfo **info_p,
8296 uint32_t *count)
8298 union spoolss_MonitorInfo *info;
8299 WERROR result = WERR_OK;
8301 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8302 W_ERROR_HAVE_NO_MEMORY(info);
8304 *count = 2;
8306 result = fill_monitor_1(info, &info[0].info1,
8307 SPL_LOCAL_PORT);
8308 if (!W_ERROR_IS_OK(result)) {
8309 goto out;
8312 result = fill_monitor_1(info, &info[1].info1,
8313 SPL_TCPIP_PORT);
8314 if (!W_ERROR_IS_OK(result)) {
8315 goto out;
8318 out:
8319 if (!W_ERROR_IS_OK(result)) {
8320 TALLOC_FREE(info);
8321 *count = 0;
8322 return result;
8325 *info_p = info;
8327 return WERR_OK;
8330 /****************************************************************************
8331 enumprintmonitors level 2.
8332 ****************************************************************************/
8334 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8335 union spoolss_MonitorInfo **info_p,
8336 uint32_t *count)
8338 union spoolss_MonitorInfo *info;
8339 WERROR result = WERR_OK;
8341 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8342 W_ERROR_HAVE_NO_MEMORY(info);
8344 *count = 2;
8346 result = fill_monitor_2(info, &info[0].info2,
8347 SPL_LOCAL_PORT,
8348 "Windows NT X86", /* FIXME */
8349 "localmon.dll");
8350 if (!W_ERROR_IS_OK(result)) {
8351 goto out;
8354 result = fill_monitor_2(info, &info[1].info2,
8355 SPL_TCPIP_PORT,
8356 "Windows NT X86", /* FIXME */
8357 "tcpmon.dll");
8358 if (!W_ERROR_IS_OK(result)) {
8359 goto out;
8362 out:
8363 if (!W_ERROR_IS_OK(result)) {
8364 TALLOC_FREE(info);
8365 *count = 0;
8366 return result;
8369 *info_p = info;
8371 return WERR_OK;
8374 /****************************************************************
8375 _spoolss_EnumMonitors
8376 ****************************************************************/
8378 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8379 struct spoolss_EnumMonitors *r)
8381 WERROR result;
8383 /* that's an [in out] buffer */
8385 if (!r->in.buffer && (r->in.offered != 0)) {
8386 return WERR_INVALID_PARAM;
8389 DEBUG(5,("_spoolss_EnumMonitors\n"));
8392 * Enumerate the print monitors ...
8394 * Just reply with "Local Port", to keep NT happy
8395 * and I can use my nice printer checker.
8398 *r->out.count = 0;
8399 *r->out.needed = 0;
8400 *r->out.info = NULL;
8402 switch (r->in.level) {
8403 case 1:
8404 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8405 r->out.count);
8406 break;
8407 case 2:
8408 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8409 r->out.count);
8410 break;
8411 default:
8412 return WERR_UNKNOWN_LEVEL;
8415 if (!W_ERROR_IS_OK(result)) {
8416 return result;
8419 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8420 spoolss_EnumMonitors,
8421 *r->out.info, r->in.level,
8422 *r->out.count);
8423 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8424 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8426 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8429 /****************************************************************************
8430 ****************************************************************************/
8432 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8433 const print_queue_struct *queue,
8434 int count, int snum,
8435 struct spoolss_PrinterInfo2 *pinfo2,
8436 uint32_t jobid,
8437 struct spoolss_JobInfo1 *r)
8439 int i = 0;
8440 bool found = false;
8442 for (i=0; i<count; i++) {
8443 if (queue[i].job == (int)jobid) {
8444 found = true;
8445 break;
8449 if (found == false) {
8450 /* NT treats not found as bad param... yet another bad choice */
8451 return WERR_INVALID_PARAM;
8454 return fill_job_info1(mem_ctx,
8456 &queue[i],
8458 snum,
8459 pinfo2);
8462 /****************************************************************************
8463 ****************************************************************************/
8465 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8466 const print_queue_struct *queue,
8467 int count, int snum,
8468 struct spoolss_PrinterInfo2 *pinfo2,
8469 uint32_t jobid,
8470 struct spoolss_JobInfo2 *r)
8472 int i = 0;
8473 bool found = false;
8474 struct spoolss_DeviceMode *devmode;
8475 WERROR result;
8477 for (i=0; i<count; i++) {
8478 if (queue[i].job == (int)jobid) {
8479 found = true;
8480 break;
8484 if (found == false) {
8485 /* NT treats not found as bad param... yet another bad
8486 choice */
8487 return WERR_INVALID_PARAM;
8491 * if the print job does not have a DEVMODE associated with it,
8492 * just use the one for the printer. A NULL devicemode is not
8493 * a failure condition
8496 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8497 if (!devmode) {
8498 result = spoolss_create_default_devmode(mem_ctx,
8499 pinfo2->printername,
8500 &devmode);
8501 if (!W_ERROR_IS_OK(result)) {
8502 DEBUG(3, ("Can't proceed w/o a devmode!"));
8503 return result;
8507 return fill_job_info2(mem_ctx,
8509 &queue[i],
8511 snum,
8512 pinfo2,
8513 devmode);
8516 /****************************************************************
8517 _spoolss_GetJob
8518 ****************************************************************/
8520 WERROR _spoolss_GetJob(struct pipes_struct *p,
8521 struct spoolss_GetJob *r)
8523 WERROR result = WERR_OK;
8524 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8525 int snum;
8526 int count;
8527 print_queue_struct *queue = NULL;
8528 print_status_struct prt_status;
8530 /* that's an [in out] buffer */
8532 if (!r->in.buffer && (r->in.offered != 0)) {
8533 return WERR_INVALID_PARAM;
8536 DEBUG(5,("_spoolss_GetJob\n"));
8538 *r->out.needed = 0;
8540 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8541 return WERR_BADFID;
8544 result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
8545 lp_servicename(snum), &pinfo2);
8546 if (!W_ERROR_IS_OK(result)) {
8547 return result;
8550 count = print_queue_status(snum, &queue, &prt_status);
8552 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8553 count, prt_status.status, prt_status.message));
8555 switch (r->in.level) {
8556 case 1:
8557 result = getjob_level_1(p->mem_ctx,
8558 queue, count, snum, pinfo2,
8559 r->in.job_id, &r->out.info->info1);
8560 break;
8561 case 2:
8562 result = getjob_level_2(p->mem_ctx,
8563 queue, count, snum, pinfo2,
8564 r->in.job_id, &r->out.info->info2);
8565 break;
8566 default:
8567 result = WERR_UNKNOWN_LEVEL;
8568 break;
8571 SAFE_FREE(queue);
8572 TALLOC_FREE(pinfo2);
8574 if (!W_ERROR_IS_OK(result)) {
8575 TALLOC_FREE(r->out.info);
8576 return result;
8579 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8580 r->in.level);
8581 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8583 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8586 /****************************************************************
8587 _spoolss_GetPrinterDataEx
8588 ****************************************************************/
8590 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8591 struct spoolss_GetPrinterDataEx *r)
8594 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8595 const char *printer;
8596 int snum = 0;
8597 WERROR result = WERR_OK;
8598 DATA_BLOB blob;
8599 enum winreg_Type val_type;
8600 uint8_t *val_data;
8601 uint32_t val_size;
8604 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8606 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8607 r->in.key_name, r->in.value_name));
8609 /* in case of problem, return some default values */
8611 *r->out.needed = 0;
8612 *r->out.type = REG_NONE;
8614 if (!Printer) {
8615 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8616 OUR_HANDLE(r->in.handle)));
8617 result = WERR_BADFID;
8618 goto done;
8621 /* Is the handle to a printer or to the server? */
8623 if (Printer->printer_type == SPLHND_SERVER) {
8625 union spoolss_PrinterData data;
8627 result = getprinterdata_printer_server(p->mem_ctx,
8628 r->in.value_name,
8629 r->out.type,
8630 &data);
8631 if (!W_ERROR_IS_OK(result)) {
8632 return result;
8635 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8636 *r->out.type, &data);
8637 if (!W_ERROR_IS_OK(result)) {
8638 return result;
8641 *r->out.needed = blob.length;
8643 if (r->in.offered >= *r->out.needed) {
8644 memcpy(r->out.data, blob.data, blob.length);
8647 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8650 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8651 return WERR_BADFID;
8653 printer = lp_const_servicename(snum);
8655 /* check to see if the keyname is valid */
8656 if (!strlen(r->in.key_name)) {
8657 return WERR_INVALID_PARAM;
8660 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8661 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8662 strequal(r->in.value_name, "ChangeId")) {
8663 *r->out.type = REG_DWORD;
8664 *r->out.needed = 4;
8665 if (r->in.offered >= *r->out.needed) {
8666 uint32_t changeid = 0;
8668 result = winreg_printer_get_changeid(p->mem_ctx,
8669 p->server_info,
8670 printer,
8671 &changeid);
8672 if (!W_ERROR_IS_OK(result)) {
8673 return result;
8676 SIVAL(r->out.data, 0, changeid);
8677 result = WERR_OK;
8679 goto done;
8682 result = winreg_get_printer_dataex(p->mem_ctx,
8683 p->server_info,
8684 printer,
8685 r->in.key_name,
8686 r->in.value_name,
8687 &val_type,
8688 &val_data,
8689 &val_size);
8690 if (!W_ERROR_IS_OK(result)) {
8691 return result;
8694 *r->out.needed = val_size;
8695 *r->out.type = val_type;
8697 if (r->in.offered >= *r->out.needed) {
8698 memcpy(r->out.data, val_data, val_size);
8701 done:
8702 /* retain type when returning WERR_MORE_DATA */
8703 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8705 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8708 /****************************************************************
8709 _spoolss_SetPrinterDataEx
8710 ****************************************************************/
8712 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
8713 struct spoolss_SetPrinterDataEx *r)
8715 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8716 int snum = 0;
8717 WERROR result = WERR_OK;
8718 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8719 char *oid_string;
8721 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8723 /* From MSDN documentation of SetPrinterDataEx: pass request to
8724 SetPrinterData if key is "PrinterDriverData" */
8726 if (!Printer) {
8727 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8728 OUR_HANDLE(r->in.handle)));
8729 return WERR_BADFID;
8732 if (Printer->printer_type == SPLHND_SERVER) {
8733 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8734 "Not implemented for server handles yet\n"));
8735 return WERR_INVALID_PARAM;
8738 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8739 return WERR_BADFID;
8743 * Access check : NT returns "access denied" if you make a
8744 * SetPrinterData call without the necessary privildge.
8745 * we were originally returning OK if nothing changed
8746 * which made Win2k issue **a lot** of SetPrinterData
8747 * when connecting to a printer --jerry
8750 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8751 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8752 "change denied by handle access permissions\n"));
8753 return WERR_ACCESS_DENIED;
8756 result = winreg_get_printer(Printer, p->server_info,
8757 Printer->servername,
8758 lp_servicename(snum),
8759 &pinfo2);
8760 if (!W_ERROR_IS_OK(result)) {
8761 return result;
8764 /* check for OID in valuename */
8766 oid_string = strchr(r->in.value_name, ',');
8767 if (oid_string) {
8768 *oid_string = '\0';
8769 oid_string++;
8772 /* save the registry data */
8774 result = winreg_set_printer_dataex(p->mem_ctx,
8775 p->server_info,
8776 pinfo2->sharename,
8777 r->in.key_name,
8778 r->in.value_name,
8779 r->in.type,
8780 r->in.data,
8781 r->in.offered);
8783 if (W_ERROR_IS_OK(result)) {
8784 /* save the OID if one was specified */
8785 if (oid_string) {
8786 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8787 r->in.key_name, SPOOL_OID_KEY);
8788 if (!str) {
8789 result = WERR_NOMEM;
8790 goto done;
8794 * I'm not checking the status here on purpose. Don't know
8795 * if this is right, but I'm returning the status from the
8796 * previous set_printer_dataex() call. I have no idea if
8797 * this is right. --jerry
8799 winreg_set_printer_dataex(p->mem_ctx,
8800 p->server_info,
8801 pinfo2->sharename,
8802 str,
8803 r->in.value_name,
8804 REG_SZ,
8805 (uint8_t *) oid_string,
8806 strlen(oid_string) + 1);
8809 result = winreg_printer_update_changeid(p->mem_ctx,
8810 p->server_info,
8811 lp_const_servicename(snum));
8815 done:
8816 talloc_free(pinfo2);
8817 return result;
8820 /****************************************************************
8821 _spoolss_DeletePrinterDataEx
8822 ****************************************************************/
8824 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
8825 struct spoolss_DeletePrinterDataEx *r)
8827 const char *printer;
8828 int snum=0;
8829 WERROR status = WERR_OK;
8830 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8832 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8834 if (!Printer) {
8835 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8836 "Invalid handle (%s:%u:%u).\n",
8837 OUR_HANDLE(r->in.handle)));
8838 return WERR_BADFID;
8841 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8842 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8843 "printer properties change denied by handle\n"));
8844 return WERR_ACCESS_DENIED;
8847 if (!r->in.value_name || !r->in.key_name) {
8848 return WERR_NOMEM;
8851 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8852 return WERR_BADFID;
8854 printer = lp_const_servicename(snum);
8856 status = winreg_delete_printer_dataex(p->mem_ctx,
8857 p->server_info,
8858 printer,
8859 r->in.key_name,
8860 r->in.value_name);
8861 if (W_ERROR_IS_OK(status)) {
8862 status = winreg_printer_update_changeid(p->mem_ctx,
8863 p->server_info,
8864 printer);
8867 return status;
8870 /****************************************************************
8871 _spoolss_EnumPrinterKey
8872 ****************************************************************/
8874 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
8875 struct spoolss_EnumPrinterKey *r)
8877 uint32_t num_keys;
8878 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8879 int snum = 0;
8880 WERROR result = WERR_BADFILE;
8881 const char **array = NULL;
8882 DATA_BLOB blob;
8884 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8886 if (!Printer) {
8887 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8888 OUR_HANDLE(r->in.handle)));
8889 return WERR_BADFID;
8892 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8893 return WERR_BADFID;
8896 result = winreg_enum_printer_key(p->mem_ctx,
8897 p->server_info,
8898 lp_const_servicename(snum),
8899 r->in.key_name,
8900 &num_keys,
8901 &array);
8902 if (!W_ERROR_IS_OK(result)) {
8903 goto done;
8906 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8907 result = WERR_NOMEM;
8908 goto done;
8911 *r->out._ndr_size = r->in.offered / 2;
8912 *r->out.needed = blob.length;
8914 if (r->in.offered < *r->out.needed) {
8915 result = WERR_MORE_DATA;
8916 } else {
8917 result = WERR_OK;
8918 r->out.key_buffer->string_array = array;
8921 done:
8922 if (!W_ERROR_IS_OK(result)) {
8923 TALLOC_FREE(array);
8924 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8925 *r->out.needed = 0;
8929 return result;
8932 /****************************************************************
8933 _spoolss_DeletePrinterKey
8934 ****************************************************************/
8936 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
8937 struct spoolss_DeletePrinterKey *r)
8939 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8940 int snum=0;
8941 WERROR status;
8942 const char *printer;
8944 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8946 if (!Printer) {
8947 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8948 OUR_HANDLE(r->in.handle)));
8949 return WERR_BADFID;
8952 /* if keyname == NULL, return error */
8953 if ( !r->in.key_name )
8954 return WERR_INVALID_PARAM;
8956 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8957 return WERR_BADFID;
8960 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8961 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8962 "printer properties change denied by handle\n"));
8963 return WERR_ACCESS_DENIED;
8966 printer = lp_const_servicename(snum);
8968 /* delete the key and all subkeys */
8969 status = winreg_delete_printer_key(p->mem_ctx,
8970 p->server_info,
8971 printer,
8972 r->in.key_name);
8973 if (W_ERROR_IS_OK(status)) {
8974 status = winreg_printer_update_changeid(p->mem_ctx,
8975 p->server_info,
8976 printer);
8979 return status;
8982 /****************************************************************
8983 _spoolss_EnumPrinterDataEx
8984 ****************************************************************/
8986 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
8987 struct spoolss_EnumPrinterDataEx *r)
8989 uint32_t count = 0;
8990 struct spoolss_PrinterEnumValues *info = NULL;
8991 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8992 int snum;
8993 WERROR result;
8995 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8997 *r->out.count = 0;
8998 *r->out.needed = 0;
8999 *r->out.info = NULL;
9001 if (!Printer) {
9002 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9003 OUR_HANDLE(r->in.handle)));
9004 return WERR_BADFID;
9008 * first check for a keyname of NULL or "". Win2k seems to send
9009 * this a lot and we should send back WERR_INVALID_PARAM
9010 * no need to spend time looking up the printer in this case.
9011 * --jerry
9014 if (!strlen(r->in.key_name)) {
9015 result = WERR_INVALID_PARAM;
9016 goto done;
9019 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9020 return WERR_BADFID;
9023 /* now look for a match on the key name */
9024 result = winreg_enum_printer_dataex(p->mem_ctx,
9025 p->server_info,
9026 lp_const_servicename(snum),
9027 r->in.key_name,
9028 &count,
9029 &info);
9030 if (!W_ERROR_IS_OK(result)) {
9031 goto done;
9034 #if 0 /* FIXME - gd */
9035 /* housekeeping information in the reply */
9037 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9038 * the hand marshalled container size is a multiple
9039 * of 4 bytes for RPC alignment.
9042 if (needed % 4) {
9043 needed += 4-(needed % 4);
9045 #endif
9046 *r->out.count = count;
9047 *r->out.info = info;
9049 done:
9050 if (!W_ERROR_IS_OK(result)) {
9051 return result;
9054 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9055 spoolss_EnumPrinterDataEx,
9056 *r->out.info,
9057 *r->out.count);
9058 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9059 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9061 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9064 /****************************************************************************
9065 ****************************************************************************/
9067 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9068 const char *servername,
9069 const char *environment,
9070 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9072 WERROR werr;
9073 char *path = NULL;
9075 werr = compose_spoolss_server_path(mem_ctx,
9076 servername,
9077 environment,
9078 SPOOLSS_PRTPROCS_PATH,
9079 &path);
9080 if (!W_ERROR_IS_OK(werr)) {
9081 return werr;
9084 DEBUG(4,("print processor directory: [%s]\n", path));
9086 r->directory_name = path;
9088 return WERR_OK;
9091 /****************************************************************
9092 _spoolss_GetPrintProcessorDirectory
9093 ****************************************************************/
9095 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9096 struct spoolss_GetPrintProcessorDirectory *r)
9098 WERROR result;
9100 /* that's an [in out] buffer */
9102 if (!r->in.buffer && (r->in.offered != 0)) {
9103 return WERR_INVALID_PARAM;
9106 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9107 r->in.level));
9109 *r->out.needed = 0;
9111 /* r->in.level is ignored */
9113 /* We always should reply with a local print processor directory so that
9114 * users are not forced to have a [prnproc$] share on the Samba spoolss
9115 * server - Guenther */
9117 result = getprintprocessordirectory_level_1(p->mem_ctx,
9118 NULL, /* r->in.server */
9119 r->in.environment,
9120 &r->out.info->info1);
9121 if (!W_ERROR_IS_OK(result)) {
9122 TALLOC_FREE(r->out.info);
9123 return result;
9126 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9127 r->out.info, r->in.level);
9128 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9130 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9133 /*******************************************************************
9134 ********************************************************************/
9136 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9137 const char *dllname)
9139 enum ndr_err_code ndr_err;
9140 struct spoolss_MonitorUi ui;
9142 ui.dll_name = dllname;
9144 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9145 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9146 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9147 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9149 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9152 /*******************************************************************
9153 Streams the monitor UI DLL name in UNICODE
9154 *******************************************************************/
9156 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9157 NT_USER_TOKEN *token, DATA_BLOB *in,
9158 DATA_BLOB *out, uint32_t *needed)
9160 const char *dllname = "tcpmonui.dll";
9162 *needed = (strlen(dllname)+1) * 2;
9164 if (out->length < *needed) {
9165 return WERR_INSUFFICIENT_BUFFER;
9168 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9169 return WERR_NOMEM;
9172 return WERR_OK;
9175 /*******************************************************************
9176 ********************************************************************/
9178 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9179 struct spoolss_PortData1 *port1,
9180 const DATA_BLOB *buf)
9182 enum ndr_err_code ndr_err;
9183 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9184 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9185 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9186 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9188 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9191 /*******************************************************************
9192 ********************************************************************/
9194 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9195 struct spoolss_PortData2 *port2,
9196 const DATA_BLOB *buf)
9198 enum ndr_err_code ndr_err;
9199 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9200 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9201 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9202 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9204 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9207 /*******************************************************************
9208 Create a new TCP/IP port
9209 *******************************************************************/
9211 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9212 NT_USER_TOKEN *token, DATA_BLOB *in,
9213 DATA_BLOB *out, uint32_t *needed)
9215 struct spoolss_PortData1 port1;
9216 struct spoolss_PortData2 port2;
9217 char *device_uri = NULL;
9218 uint32_t version;
9220 const char *portname;
9221 const char *hostaddress;
9222 const char *queue;
9223 uint32_t port_number;
9224 uint32_t protocol;
9226 /* peek for spoolss_PortData version */
9228 if (!in || (in->length < (128 + 4))) {
9229 return WERR_GENERAL_FAILURE;
9232 version = IVAL(in->data, 128);
9234 switch (version) {
9235 case 1:
9236 ZERO_STRUCT(port1);
9238 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9239 return WERR_NOMEM;
9242 portname = port1.portname;
9243 hostaddress = port1.hostaddress;
9244 queue = port1.queue;
9245 protocol = port1.protocol;
9246 port_number = port1.port_number;
9248 break;
9249 case 2:
9250 ZERO_STRUCT(port2);
9252 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9253 return WERR_NOMEM;
9256 portname = port2.portname;
9257 hostaddress = port2.hostaddress;
9258 queue = port2.queue;
9259 protocol = port2.protocol;
9260 port_number = port2.port_number;
9262 break;
9263 default:
9264 DEBUG(1,("xcvtcp_addport: "
9265 "unknown version of port_data: %d\n", version));
9266 return WERR_UNKNOWN_PORT;
9269 /* create the device URI and call the add_port_hook() */
9271 switch (protocol) {
9272 case PROTOCOL_RAWTCP_TYPE:
9273 device_uri = talloc_asprintf(mem_ctx,
9274 "socket://%s:%d/", hostaddress,
9275 port_number);
9276 break;
9278 case PROTOCOL_LPR_TYPE:
9279 device_uri = talloc_asprintf(mem_ctx,
9280 "lpr://%s/%s", hostaddress, queue );
9281 break;
9283 default:
9284 return WERR_UNKNOWN_PORT;
9287 if (!device_uri) {
9288 return WERR_NOMEM;
9291 return add_port_hook(mem_ctx, token, portname, device_uri);
9294 /*******************************************************************
9295 *******************************************************************/
9297 struct xcv_api_table xcvtcp_cmds[] = {
9298 { "MonitorUI", xcvtcp_monitorui },
9299 { "AddPort", xcvtcp_addport},
9300 { NULL, NULL }
9303 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9304 NT_USER_TOKEN *token, const char *command,
9305 DATA_BLOB *inbuf,
9306 DATA_BLOB *outbuf,
9307 uint32_t *needed )
9309 int i;
9311 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9313 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9314 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9315 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9318 return WERR_BADFUNC;
9321 /*******************************************************************
9322 *******************************************************************/
9323 #if 0 /* don't support management using the "Local Port" monitor */
9325 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9326 NT_USER_TOKEN *token, DATA_BLOB *in,
9327 DATA_BLOB *out, uint32_t *needed)
9329 const char *dllname = "localui.dll";
9331 *needed = (strlen(dllname)+1) * 2;
9333 if (out->length < *needed) {
9334 return WERR_INSUFFICIENT_BUFFER;
9337 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9338 return WERR_NOMEM;
9341 return WERR_OK;
9344 /*******************************************************************
9345 *******************************************************************/
9347 struct xcv_api_table xcvlocal_cmds[] = {
9348 { "MonitorUI", xcvlocal_monitorui },
9349 { NULL, NULL }
9351 #else
9352 struct xcv_api_table xcvlocal_cmds[] = {
9353 { NULL, NULL }
9355 #endif
9359 /*******************************************************************
9360 *******************************************************************/
9362 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9363 NT_USER_TOKEN *token, const char *command,
9364 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9365 uint32_t *needed)
9367 int i;
9369 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9371 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9372 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9373 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9375 return WERR_BADFUNC;
9378 /****************************************************************
9379 _spoolss_XcvData
9380 ****************************************************************/
9382 WERROR _spoolss_XcvData(struct pipes_struct *p,
9383 struct spoolss_XcvData *r)
9385 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9386 DATA_BLOB out_data = data_blob_null;
9387 WERROR werror;
9389 if (!Printer) {
9390 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9391 OUR_HANDLE(r->in.handle)));
9392 return WERR_BADFID;
9395 /* Has to be a handle to the TCP/IP port monitor */
9397 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9398 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9399 return WERR_BADFID;
9402 /* requires administrative access to the server */
9404 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9405 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9406 return WERR_ACCESS_DENIED;
9409 /* Allocate the outgoing buffer */
9411 if (r->in.out_data_size) {
9412 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9413 if (out_data.data == NULL) {
9414 return WERR_NOMEM;
9418 switch ( Printer->printer_type ) {
9419 case SPLHND_PORTMON_TCP:
9420 werror = process_xcvtcp_command(p->mem_ctx,
9421 p->server_info->ptok,
9422 r->in.function_name,
9423 &r->in.in_data, &out_data,
9424 r->out.needed);
9425 break;
9426 case SPLHND_PORTMON_LOCAL:
9427 werror = process_xcvlocal_command(p->mem_ctx,
9428 p->server_info->ptok,
9429 r->in.function_name,
9430 &r->in.in_data, &out_data,
9431 r->out.needed);
9432 break;
9433 default:
9434 werror = WERR_INVALID_PRINT_MONITOR;
9437 if (!W_ERROR_IS_OK(werror)) {
9438 return werror;
9441 *r->out.status_code = 0;
9443 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9444 memcpy(r->out.out_data, out_data.data,
9445 MIN(r->in.out_data_size, out_data.length));
9448 return WERR_OK;
9451 /****************************************************************
9452 _spoolss_AddPrintProcessor
9453 ****************************************************************/
9455 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9456 struct spoolss_AddPrintProcessor *r)
9458 /* for now, just indicate success and ignore the add. We'll
9459 automatically set the winprint processor for printer
9460 entries later. Used to debug the LexMark Optra S 1855 PCL
9461 driver --jerry */
9463 return WERR_OK;
9466 /****************************************************************
9467 _spoolss_AddPort
9468 ****************************************************************/
9470 WERROR _spoolss_AddPort(struct pipes_struct *p,
9471 struct spoolss_AddPort *r)
9473 /* do what w2k3 does */
9475 return WERR_NOT_SUPPORTED;
9478 /****************************************************************
9479 _spoolss_GetPrinterDriver
9480 ****************************************************************/
9482 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9483 struct spoolss_GetPrinterDriver *r)
9485 p->rng_fault_state = true;
9486 return WERR_NOT_SUPPORTED;
9489 /****************************************************************
9490 _spoolss_ReadPrinter
9491 ****************************************************************/
9493 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9494 struct spoolss_ReadPrinter *r)
9496 p->rng_fault_state = true;
9497 return WERR_NOT_SUPPORTED;
9500 /****************************************************************
9501 _spoolss_WaitForPrinterChange
9502 ****************************************************************/
9504 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9505 struct spoolss_WaitForPrinterChange *r)
9507 p->rng_fault_state = true;
9508 return WERR_NOT_SUPPORTED;
9511 /****************************************************************
9512 _spoolss_ConfigurePort
9513 ****************************************************************/
9515 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9516 struct spoolss_ConfigurePort *r)
9518 p->rng_fault_state = true;
9519 return WERR_NOT_SUPPORTED;
9522 /****************************************************************
9523 _spoolss_DeletePort
9524 ****************************************************************/
9526 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9527 struct spoolss_DeletePort *r)
9529 p->rng_fault_state = true;
9530 return WERR_NOT_SUPPORTED;
9533 /****************************************************************
9534 _spoolss_CreatePrinterIC
9535 ****************************************************************/
9537 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9538 struct spoolss_CreatePrinterIC *r)
9540 p->rng_fault_state = true;
9541 return WERR_NOT_SUPPORTED;
9544 /****************************************************************
9545 _spoolss_PlayGDIScriptOnPrinterIC
9546 ****************************************************************/
9548 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9549 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9551 p->rng_fault_state = true;
9552 return WERR_NOT_SUPPORTED;
9555 /****************************************************************
9556 _spoolss_DeletePrinterIC
9557 ****************************************************************/
9559 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9560 struct spoolss_DeletePrinterIC *r)
9562 p->rng_fault_state = true;
9563 return WERR_NOT_SUPPORTED;
9566 /****************************************************************
9567 _spoolss_AddPrinterConnection
9568 ****************************************************************/
9570 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9571 struct spoolss_AddPrinterConnection *r)
9573 p->rng_fault_state = true;
9574 return WERR_NOT_SUPPORTED;
9577 /****************************************************************
9578 _spoolss_DeletePrinterConnection
9579 ****************************************************************/
9581 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9582 struct spoolss_DeletePrinterConnection *r)
9584 p->rng_fault_state = true;
9585 return WERR_NOT_SUPPORTED;
9588 /****************************************************************
9589 _spoolss_PrinterMessageBox
9590 ****************************************************************/
9592 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9593 struct spoolss_PrinterMessageBox *r)
9595 p->rng_fault_state = true;
9596 return WERR_NOT_SUPPORTED;
9599 /****************************************************************
9600 _spoolss_AddMonitor
9601 ****************************************************************/
9603 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9604 struct spoolss_AddMonitor *r)
9606 p->rng_fault_state = true;
9607 return WERR_NOT_SUPPORTED;
9610 /****************************************************************
9611 _spoolss_DeleteMonitor
9612 ****************************************************************/
9614 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
9615 struct spoolss_DeleteMonitor *r)
9617 p->rng_fault_state = true;
9618 return WERR_NOT_SUPPORTED;
9621 /****************************************************************
9622 _spoolss_DeletePrintProcessor
9623 ****************************************************************/
9625 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
9626 struct spoolss_DeletePrintProcessor *r)
9628 p->rng_fault_state = true;
9629 return WERR_NOT_SUPPORTED;
9632 /****************************************************************
9633 _spoolss_AddPrintProvidor
9634 ****************************************************************/
9636 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
9637 struct spoolss_AddPrintProvidor *r)
9639 p->rng_fault_state = true;
9640 return WERR_NOT_SUPPORTED;
9643 /****************************************************************
9644 _spoolss_DeletePrintProvidor
9645 ****************************************************************/
9647 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
9648 struct spoolss_DeletePrintProvidor *r)
9650 p->rng_fault_state = true;
9651 return WERR_NOT_SUPPORTED;
9654 /****************************************************************
9655 _spoolss_FindFirstPrinterChangeNotification
9656 ****************************************************************/
9658 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
9659 struct spoolss_FindFirstPrinterChangeNotification *r)
9661 p->rng_fault_state = true;
9662 return WERR_NOT_SUPPORTED;
9665 /****************************************************************
9666 _spoolss_FindNextPrinterChangeNotification
9667 ****************************************************************/
9669 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
9670 struct spoolss_FindNextPrinterChangeNotification *r)
9672 p->rng_fault_state = true;
9673 return WERR_NOT_SUPPORTED;
9676 /****************************************************************
9677 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9678 ****************************************************************/
9680 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
9681 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9683 p->rng_fault_state = true;
9684 return WERR_NOT_SUPPORTED;
9687 /****************************************************************
9688 _spoolss_ReplyOpenPrinter
9689 ****************************************************************/
9691 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
9692 struct spoolss_ReplyOpenPrinter *r)
9694 p->rng_fault_state = true;
9695 return WERR_NOT_SUPPORTED;
9698 /****************************************************************
9699 _spoolss_RouterReplyPrinter
9700 ****************************************************************/
9702 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
9703 struct spoolss_RouterReplyPrinter *r)
9705 p->rng_fault_state = true;
9706 return WERR_NOT_SUPPORTED;
9709 /****************************************************************
9710 _spoolss_ReplyClosePrinter
9711 ****************************************************************/
9713 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
9714 struct spoolss_ReplyClosePrinter *r)
9716 p->rng_fault_state = true;
9717 return WERR_NOT_SUPPORTED;
9720 /****************************************************************
9721 _spoolss_AddPortEx
9722 ****************************************************************/
9724 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
9725 struct spoolss_AddPortEx *r)
9727 p->rng_fault_state = true;
9728 return WERR_NOT_SUPPORTED;
9731 /****************************************************************
9732 _spoolss_RouterFindFirstPrinterChangeNotification
9733 ****************************************************************/
9735 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
9736 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9738 p->rng_fault_state = true;
9739 return WERR_NOT_SUPPORTED;
9742 /****************************************************************
9743 _spoolss_SpoolerInit
9744 ****************************************************************/
9746 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
9747 struct spoolss_SpoolerInit *r)
9749 p->rng_fault_state = true;
9750 return WERR_NOT_SUPPORTED;
9753 /****************************************************************
9754 _spoolss_ResetPrinterEx
9755 ****************************************************************/
9757 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
9758 struct spoolss_ResetPrinterEx *r)
9760 p->rng_fault_state = true;
9761 return WERR_NOT_SUPPORTED;
9764 /****************************************************************
9765 _spoolss_RouterReplyPrinterEx
9766 ****************************************************************/
9768 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
9769 struct spoolss_RouterReplyPrinterEx *r)
9771 p->rng_fault_state = true;
9772 return WERR_NOT_SUPPORTED;
9775 /****************************************************************
9776 _spoolss_44
9777 ****************************************************************/
9779 WERROR _spoolss_44(struct pipes_struct *p,
9780 struct spoolss_44 *r)
9782 p->rng_fault_state = true;
9783 return WERR_NOT_SUPPORTED;
9786 /****************************************************************
9787 _spoolss_47
9788 ****************************************************************/
9790 WERROR _spoolss_47(struct pipes_struct *p,
9791 struct spoolss_47 *r)
9793 p->rng_fault_state = true;
9794 return WERR_NOT_SUPPORTED;
9797 /****************************************************************
9798 _spoolss_4a
9799 ****************************************************************/
9801 WERROR _spoolss_4a(struct pipes_struct *p,
9802 struct spoolss_4a *r)
9804 p->rng_fault_state = true;
9805 return WERR_NOT_SUPPORTED;
9808 /****************************************************************
9809 _spoolss_4b
9810 ****************************************************************/
9812 WERROR _spoolss_4b(struct pipes_struct *p,
9813 struct spoolss_4b *r)
9815 p->rng_fault_state = true;
9816 return WERR_NOT_SUPPORTED;
9819 /****************************************************************
9820 _spoolss_4c
9821 ****************************************************************/
9823 WERROR _spoolss_4c(struct pipes_struct *p,
9824 struct spoolss_4c *r)
9826 p->rng_fault_state = true;
9827 return WERR_NOT_SUPPORTED;
9830 /****************************************************************
9831 _spoolss_53
9832 ****************************************************************/
9834 WERROR _spoolss_53(struct pipes_struct *p,
9835 struct spoolss_53 *r)
9837 p->rng_fault_state = true;
9838 return WERR_NOT_SUPPORTED;
9841 /****************************************************************
9842 _spoolss_55
9843 ****************************************************************/
9845 WERROR _spoolss_55(struct pipes_struct *p,
9846 struct spoolss_55 *r)
9848 p->rng_fault_state = true;
9849 return WERR_NOT_SUPPORTED;
9852 /****************************************************************
9853 _spoolss_56
9854 ****************************************************************/
9856 WERROR _spoolss_56(struct pipes_struct *p,
9857 struct spoolss_56 *r)
9859 p->rng_fault_state = true;
9860 return WERR_NOT_SUPPORTED;
9863 /****************************************************************
9864 _spoolss_57
9865 ****************************************************************/
9867 WERROR _spoolss_57(struct pipes_struct *p,
9868 struct spoolss_57 *r)
9870 p->rng_fault_state = true;
9871 return WERR_NOT_SUPPORTED;
9874 /****************************************************************
9875 _spoolss_5a
9876 ****************************************************************/
9878 WERROR _spoolss_5a(struct pipes_struct *p,
9879 struct spoolss_5a *r)
9881 p->rng_fault_state = true;
9882 return WERR_NOT_SUPPORTED;
9885 /****************************************************************
9886 _spoolss_5b
9887 ****************************************************************/
9889 WERROR _spoolss_5b(struct pipes_struct *p,
9890 struct spoolss_5b *r)
9892 p->rng_fault_state = true;
9893 return WERR_NOT_SUPPORTED;
9896 /****************************************************************
9897 _spoolss_5c
9898 ****************************************************************/
9900 WERROR _spoolss_5c(struct pipes_struct *p,
9901 struct spoolss_5c *r)
9903 p->rng_fault_state = true;
9904 return WERR_NOT_SUPPORTED;
9907 /****************************************************************
9908 _spoolss_5d
9909 ****************************************************************/
9911 WERROR _spoolss_5d(struct pipes_struct *p,
9912 struct spoolss_5d *r)
9914 p->rng_fault_state = true;
9915 return WERR_NOT_SUPPORTED;
9918 /****************************************************************
9919 _spoolss_5e
9920 ****************************************************************/
9922 WERROR _spoolss_5e(struct pipes_struct *p,
9923 struct spoolss_5e *r)
9925 p->rng_fault_state = true;
9926 return WERR_NOT_SUPPORTED;
9929 /****************************************************************
9930 _spoolss_5f
9931 ****************************************************************/
9933 WERROR _spoolss_5f(struct pipes_struct *p,
9934 struct spoolss_5f *r)
9936 p->rng_fault_state = true;
9937 return WERR_NOT_SUPPORTED;
9940 /****************************************************************
9941 _spoolss_60
9942 ****************************************************************/
9944 WERROR _spoolss_60(struct pipes_struct *p,
9945 struct spoolss_60 *r)
9947 p->rng_fault_state = true;
9948 return WERR_NOT_SUPPORTED;
9951 /****************************************************************
9952 _spoolss_61
9953 ****************************************************************/
9955 WERROR _spoolss_61(struct pipes_struct *p,
9956 struct spoolss_61 *r)
9958 p->rng_fault_state = true;
9959 return WERR_NOT_SUPPORTED;
9962 /****************************************************************
9963 _spoolss_62
9964 ****************************************************************/
9966 WERROR _spoolss_62(struct pipes_struct *p,
9967 struct spoolss_62 *r)
9969 p->rng_fault_state = true;
9970 return WERR_NOT_SUPPORTED;
9973 /****************************************************************
9974 _spoolss_63
9975 ****************************************************************/
9977 WERROR _spoolss_63(struct pipes_struct *p,
9978 struct spoolss_63 *r)
9980 p->rng_fault_state = true;
9981 return WERR_NOT_SUPPORTED;
9984 /****************************************************************
9985 _spoolss_64
9986 ****************************************************************/
9988 WERROR _spoolss_64(struct pipes_struct *p,
9989 struct spoolss_64 *r)
9991 p->rng_fault_state = true;
9992 return WERR_NOT_SUPPORTED;
9995 /****************************************************************
9996 _spoolss_65
9997 ****************************************************************/
9999 WERROR _spoolss_65(struct pipes_struct *p,
10000 struct spoolss_65 *r)
10002 p->rng_fault_state = true;
10003 return WERR_NOT_SUPPORTED;
10006 /****************************************************************
10007 _spoolss_GetCorePrinterDrivers
10008 ****************************************************************/
10010 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10011 struct spoolss_GetCorePrinterDrivers *r)
10013 p->rng_fault_state = true;
10014 return WERR_NOT_SUPPORTED;
10017 /****************************************************************
10018 _spoolss_67
10019 ****************************************************************/
10021 WERROR _spoolss_67(struct pipes_struct *p,
10022 struct spoolss_67 *r)
10024 p->rng_fault_state = true;
10025 return WERR_NOT_SUPPORTED;
10028 /****************************************************************
10029 _spoolss_GetPrinterDriverPackagePath
10030 ****************************************************************/
10032 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10033 struct spoolss_GetPrinterDriverPackagePath *r)
10035 p->rng_fault_state = true;
10036 return WERR_NOT_SUPPORTED;
10039 /****************************************************************
10040 _spoolss_69
10041 ****************************************************************/
10043 WERROR _spoolss_69(struct pipes_struct *p,
10044 struct spoolss_69 *r)
10046 p->rng_fault_state = true;
10047 return WERR_NOT_SUPPORTED;
10050 /****************************************************************
10051 _spoolss_6a
10052 ****************************************************************/
10054 WERROR _spoolss_6a(struct pipes_struct *p,
10055 struct spoolss_6a *r)
10057 p->rng_fault_state = true;
10058 return WERR_NOT_SUPPORTED;
10061 /****************************************************************
10062 _spoolss_6b
10063 ****************************************************************/
10065 WERROR _spoolss_6b(struct pipes_struct *p,
10066 struct spoolss_6b *r)
10068 p->rng_fault_state = true;
10069 return WERR_NOT_SUPPORTED;
10072 /****************************************************************
10073 _spoolss_6c
10074 ****************************************************************/
10076 WERROR _spoolss_6c(struct pipes_struct *p,
10077 struct spoolss_6c *r)
10079 p->rng_fault_state = true;
10080 return WERR_NOT_SUPPORTED;
10083 /****************************************************************
10084 _spoolss_6d
10085 ****************************************************************/
10087 WERROR _spoolss_6d(struct pipes_struct *p,
10088 struct spoolss_6d *r)
10090 p->rng_fault_state = true;
10091 return WERR_NOT_SUPPORTED;