spoolss: add stubs for new JobNamedProperty dcerpc calls.
[kai/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
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.
12  *
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.
17  *
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.
22  *
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/>.
25  */
26
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. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd(talloc_tos());
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         const struct auth_session_info *session_info = get_session_info_system();
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         WERROR result;
1528         const char *drivername;
1529         int snum;
1530         int n_services = lp_numservices();
1531         struct dcerpc_binding_handle *b = NULL;
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537         if (!drivername) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539                 goto done;
1540         }
1541
1542         DEBUG(10, ("do_drv_upgrade_printer: "
1543                    "Got message for new driver [%s]\n", drivername));
1544
1545         /* Iterate the printer list */
1546
1547         for (snum = 0; snum < n_services; snum++) {
1548                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549                         continue;
1550                 }
1551
1552                 /* ignore [printers] share */
1553                 if (strequal(lp_const_servicename(snum), "printers")) {
1554                         continue;
1555                 }
1556
1557                 if (b == NULL) {
1558                         result = winreg_printer_binding_handle(tmp_ctx,
1559                                                                session_info,
1560                                                                msg,
1561                                                                &b);
1562                         if (!W_ERROR_IS_OK(result)) {
1563                                 break;
1564                         }
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, b,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx, b,
1587                                                         pinfo2->printername);
1588
1589                 if (!W_ERROR_IS_OK(result)) {
1590                         DEBUG(3, ("do_drv_upgrade_printer: "
1591                                   "Failed to update changeid [%s]\n",
1592                                   win_errstr(result)));
1593                 }
1594         }
1595
1596         /* all done */
1597 done:
1598         talloc_free(tmp_ctx);
1599 }
1600
1601 /********************************************************************
1602  Update the cache for all printq's with a registered client
1603  connection
1604  ********************************************************************/
1605
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 {
1608         struct printer_handle *printer = printers_list;
1609         int snum;
1610
1611         /* loop through all printers and update the cache where
1612            a client is connected */
1613         while (printer) {
1614                 if ((printer->printer_type == SPLHND_PRINTER) &&
1615                     ((printer->notify.cli_chan != NULL) &&
1616                      (printer->notify.cli_chan->active_connections > 0))) {
1617                         snum = print_queue_snum(printer->sharename);
1618                         print_queue_status(msg_ctx, snum, NULL, NULL);
1619                 }
1620
1621                 printer = printer->next;
1622         }
1623
1624         return;
1625 }
1626
1627 /****************************************************************
1628  _spoolss_OpenPrinter
1629 ****************************************************************/
1630
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632                             struct spoolss_OpenPrinter *r)
1633 {
1634         struct spoolss_OpenPrinterEx e;
1635         WERROR werr;
1636
1637         ZERO_STRUCT(e.in.userlevel);
1638
1639         e.in.printername        = r->in.printername;
1640         e.in.datatype           = r->in.datatype;
1641         e.in.devmode_ctr        = r->in.devmode_ctr;
1642         e.in.access_mask        = r->in.access_mask;
1643         e.in.level              = 0;
1644
1645         e.out.handle            = r->out.handle;
1646
1647         werr = _spoolss_OpenPrinterEx(p, &e);
1648
1649         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1650                 /* OpenPrinterEx returns this for a bad
1651                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1652                  * instead.
1653                  */
1654                 werr = WERR_INVALID_PRINTER_NAME;
1655         }
1656
1657         return werr;
1658 }
1659
1660 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1661                               struct spoolss_DeviceMode *orig,
1662                               struct spoolss_DeviceMode **dest)
1663 {
1664         struct spoolss_DeviceMode *dm;
1665
1666         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1667         if (!dm) {
1668                 return WERR_NOMEM;
1669         }
1670
1671         /* copy all values, then duplicate strings and structs */
1672         *dm = *orig;
1673
1674         dm->devicename = talloc_strdup(dm, orig->devicename);
1675         if (!dm->devicename) {
1676                 return WERR_NOMEM;
1677         }
1678         dm->formname = talloc_strdup(dm, orig->formname);
1679         if (!dm->formname) {
1680                 return WERR_NOMEM;
1681         }
1682         if (orig->driverextra_data.data) {
1683                 dm->driverextra_data.data =
1684                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1685                                         orig->driverextra_data.length);
1686                 if (!dm->driverextra_data.data) {
1687                         return WERR_NOMEM;
1688                 }
1689         }
1690
1691         *dest = dm;
1692         return WERR_OK;
1693 }
1694
1695 /****************************************************************
1696  _spoolss_OpenPrinterEx
1697 ****************************************************************/
1698
1699 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1700                               struct spoolss_OpenPrinterEx *r)
1701 {
1702         int snum;
1703         char *raddr;
1704         char *rhost;
1705         struct printer_handle *Printer=NULL;
1706         WERROR result;
1707         int rc;
1708
1709         if (!r->in.printername) {
1710                 return WERR_INVALID_PARAM;
1711         }
1712
1713         if (!*r->in.printername) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716
1717         if (r->in.level > 3) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1721             (r->in.level == 2 && !r->in.userlevel.level2) ||
1722             (r->in.level == 3 && !r->in.userlevel.level3)) {
1723                 return WERR_INVALID_PARAM;
1724         }
1725
1726         /* some sanity check because you can open a printer or a print server */
1727         /* aka: \\server\printer or \\server */
1728
1729         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1730
1731         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1732         if (!W_ERROR_IS_OK(result)) {
1733                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1734                         "for printer %s\n", r->in.printername));
1735                 ZERO_STRUCTP(r->out.handle);
1736                 return result;
1737         }
1738
1739         Printer = find_printer_index_by_hnd(p, r->out.handle);
1740         if ( !Printer ) {
1741                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1742                         "handle we created for printer %s\n", r->in.printername));
1743                 close_printer_handle(p, r->out.handle);
1744                 ZERO_STRUCTP(r->out.handle);
1745                 return WERR_INVALID_PARAM;
1746         }
1747
1748         /*
1749          * First case: the user is opening the print server:
1750          *
1751          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1752          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1753          *
1754          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1755          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1756          * or if the user is listed in the smb.conf printer admin parameter.
1757          *
1758          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1759          * client view printer folder, but does not show the MSAPW.
1760          *
1761          * Note: this test needs code to check access rights here too. Jeremy
1762          * could you look at this?
1763          *
1764          * Second case: the user is opening a printer:
1765          * NT doesn't let us connect to a printer if the connecting user
1766          * doesn't have print permission.
1767          *
1768          * Third case: user is opening a Port Monitor
1769          * access checks same as opening a handle to the print server.
1770          */
1771
1772         switch (Printer->printer_type )
1773         {
1774         case SPLHND_SERVER:
1775         case SPLHND_PORTMON_TCP:
1776         case SPLHND_PORTMON_LOCAL:
1777                 /* Printserver handles use global struct... */
1778
1779                 snum = -1;
1780
1781                 /* Map standard access rights to object specific access rights */
1782
1783                 se_map_standard(&r->in.access_mask,
1784                                 &printserver_std_mapping);
1785
1786                 /* Deny any object specific bits that don't apply to print
1787                    servers (i.e printer and job specific bits) */
1788
1789                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1790
1791                 if (r->in.access_mask &
1792                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1793                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1794                         close_printer_handle(p, r->out.handle);
1795                         ZERO_STRUCTP(r->out.handle);
1796                         return WERR_ACCESS_DENIED;
1797                 }
1798
1799                 /* Allow admin access */
1800
1801                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1802                 {
1803                         if (!lp_ms_add_printer_wizard()) {
1804                                 close_printer_handle(p, r->out.handle);
1805                                 ZERO_STRUCTP(r->out.handle);
1806                                 return WERR_ACCESS_DENIED;
1807                         }
1808
1809                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1810                            and not a printer admin, then fail */
1811
1812                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1813                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1814                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1815                                                 p->session_info->security_token)) {
1816                                 close_printer_handle(p, r->out.handle);
1817                                 ZERO_STRUCTP(r->out.handle);
1818                                 DEBUG(3,("access DENIED as user is not root, "
1819                                         "has no printoperator privilege, "
1820                                         "not a member of the printoperator builtin group and "
1821                                         "is not in printer admin list"));
1822                                 return WERR_ACCESS_DENIED;
1823                         }
1824
1825                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1826                 }
1827                 else
1828                 {
1829                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1830                 }
1831
1832                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1834
1835                 /* We fall through to return WERR_OK */
1836                 break;
1837
1838         case SPLHND_PRINTER:
1839                 /* NT doesn't let us connect to a printer if the connecting user
1840                    doesn't have print permission.  */
1841
1842                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843                         close_printer_handle(p, r->out.handle);
1844                         ZERO_STRUCTP(r->out.handle);
1845                         return WERR_BADFID;
1846                 }
1847
1848                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1850                 }
1851
1852                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1853
1854                 /* map an empty access mask to the minimum access mask */
1855                 if (r->in.access_mask == 0x0)
1856                         r->in.access_mask = PRINTER_ACCESS_USE;
1857
1858                 /*
1859                  * If we are not serving the printer driver for this printer,
1860                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1861                  * will keep NT clients happy  --jerry
1862                  */
1863
1864                 if (lp_use_client_driver(snum)
1865                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1866                 {
1867                         r->in.access_mask = PRINTER_ACCESS_USE;
1868                 }
1869
1870                 /* check smb.conf parameters and the the sec_desc */
1871                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1872                                                          p->mem_ctx);
1873                 if (raddr == NULL) {
1874                         return WERR_NOMEM;
1875                 }
1876
1877                 rc = get_remote_hostname(p->remote_address,
1878                                          &rhost,
1879                                          p->mem_ctx);
1880                 if (rc < 0) {
1881                         return WERR_NOMEM;
1882                 }
1883                 if (strequal(rhost, "UNKNOWN")) {
1884                         rhost = raddr;
1885                 }
1886
1887                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1888                                   rhost, raddr)) {
1889                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1890                         ZERO_STRUCTP(r->out.handle);
1891                         return WERR_ACCESS_DENIED;
1892                 }
1893
1894                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1895                                    p->session_info->security_token, snum) ||
1896                     !print_access_check(p->session_info,
1897                                         p->msg_ctx,
1898                                         snum,
1899                                         r->in.access_mask)) {
1900                         DEBUG(3, ("access DENIED for printer open\n"));
1901                         close_printer_handle(p, r->out.handle);
1902                         ZERO_STRUCTP(r->out.handle);
1903                         return WERR_ACCESS_DENIED;
1904                 }
1905
1906                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1907                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1908                         close_printer_handle(p, r->out.handle);
1909                         ZERO_STRUCTP(r->out.handle);
1910                         return WERR_ACCESS_DENIED;
1911                 }
1912
1913                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1914                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1915                 else
1916                         r->in.access_mask = PRINTER_ACCESS_USE;
1917
1918                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1919                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1920
1921                 winreg_create_printer_internal(p->mem_ctx,
1922                                       get_session_info_system(),
1923                                       p->msg_ctx,
1924                                       lp_const_servicename(snum));
1925
1926                 break;
1927
1928         default:
1929                 /* sanity check to prevent programmer error */
1930                 ZERO_STRUCTP(r->out.handle);
1931                 return WERR_BADFID;
1932         }
1933
1934         Printer->access_granted = r->in.access_mask;
1935
1936         /*
1937          * If the client sent a devmode in the OpenPrinter() call, then
1938          * save it here in case we get a job submission on this handle
1939          */
1940
1941          if ((Printer->printer_type != SPLHND_SERVER)
1942           && (r->in.devmode_ctr.devmode != NULL)) {
1943                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1944                                 &Printer->devmode);
1945          }
1946
1947         return WERR_OK;
1948 }
1949
1950 /****************************************************************
1951  _spoolss_ClosePrinter
1952 ****************************************************************/
1953
1954 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1955                              struct spoolss_ClosePrinter *r)
1956 {
1957         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1958
1959         if (Printer && Printer->document_started) {
1960                 struct spoolss_EndDocPrinter e;
1961
1962                 e.in.handle = r->in.handle;
1963
1964                 _spoolss_EndDocPrinter(p, &e);
1965         }
1966
1967         if (!close_printer_handle(p, r->in.handle))
1968                 return WERR_BADFID;
1969
1970         /* clear the returned printer handle.  Observed behavior
1971            from Win2k server.  Don't think this really matters.
1972            Previous code just copied the value of the closed
1973            handle.    --jerry */
1974
1975         ZERO_STRUCTP(r->out.handle);
1976
1977         return WERR_OK;
1978 }
1979
1980 /****************************************************************
1981  _spoolss_DeletePrinter
1982 ****************************************************************/
1983
1984 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1985                               struct spoolss_DeletePrinter *r)
1986 {
1987         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1988         WERROR result;
1989         int snum;
1990
1991         if (Printer && Printer->document_started) {
1992                 struct spoolss_EndDocPrinter e;
1993
1994                 e.in.handle = r->in.handle;
1995
1996                 _spoolss_EndDocPrinter(p, &e);
1997         }
1998
1999         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2000                 winreg_delete_printer_key_internal(p->mem_ctx,
2001                                           get_session_info_system(),
2002                                           p->msg_ctx,
2003                                           lp_const_servicename(snum),
2004                                           "");
2005         }
2006
2007         result = delete_printer_handle(p, r->in.handle);
2008
2009         return result;
2010 }
2011
2012 /*******************************************************************
2013  * static function to lookup the version id corresponding to an
2014  * long architecture string
2015  ******************************************************************/
2016
2017 static const struct print_architecture_table_node archi_table[]= {
2018
2019         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2020         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2021         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2022         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2023         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2024         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2025         {"Windows x64",          SPL_ARCH_X64,          3 },
2026         {NULL,                   "",            -1 }
2027 };
2028
2029 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2030                                    SPOOLSS_DRIVER_VERSION_NT35,
2031                                    SPOOLSS_DRIVER_VERSION_NT4,
2032                                    SPOOLSS_DRIVER_VERSION_200X,
2033                                    -1};
2034
2035 static int get_version_id(const char *arch)
2036 {
2037         int i;
2038
2039         for (i=0; archi_table[i].long_archi != NULL; i++)
2040         {
2041                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2042                         return (archi_table[i].version);
2043         }
2044
2045         return -1;
2046 }
2047
2048 /****************************************************************
2049  _spoolss_DeletePrinterDriver
2050 ****************************************************************/
2051
2052 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2053                                     struct spoolss_DeletePrinterDriver *r)
2054 {
2055
2056         struct spoolss_DriverInfo8 *info = NULL;
2057         int                             version;
2058         WERROR                          status;
2059         struct dcerpc_binding_handle *b;
2060         TALLOC_CTX *tmp_ctx = NULL;
2061         int i;
2062         bool found;
2063
2064         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2065            and not a printer admin, then fail */
2066
2067         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2068             !security_token_has_privilege(p->session_info->security_token,
2069                                           SEC_PRIV_PRINT_OPERATOR)) {
2070                 return WERR_ACCESS_DENIED;
2071         }
2072
2073         /* check that we have a valid driver name first */
2074
2075         if ((version = get_version_id(r->in.architecture)) == -1) {
2076                 return WERR_INVALID_ENVIRONMENT;
2077         }
2078
2079         tmp_ctx = talloc_new(p->mem_ctx);
2080         if (!tmp_ctx) {
2081                 return WERR_NOMEM;
2082         }
2083
2084         status = winreg_printer_binding_handle(tmp_ctx,
2085                                                get_session_info_system(),
2086                                                p->msg_ctx,
2087                                                &b);
2088         if (!W_ERROR_IS_OK(status)) {
2089                 goto done;
2090         }
2091
2092         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2093                 status = winreg_get_driver(tmp_ctx, b,
2094                                            r->in.architecture, r->in.driver,
2095                                            drv_cversion[i], &info);
2096                 if (!W_ERROR_IS_OK(status)) {
2097                         DEBUG(5, ("skipping del of driver with version %d\n",
2098                                   drv_cversion[i]));
2099                         continue;
2100                 }
2101                 found = true;
2102
2103                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2104                         status = WERR_PRINTER_DRIVER_IN_USE;
2105                         goto done;
2106                 }
2107
2108                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2109                 if (!W_ERROR_IS_OK(status)) {
2110                         DEBUG(0, ("failed del of driver with version %d\n",
2111                                   drv_cversion[i]));
2112                         goto done;
2113                 }
2114         }
2115         if (found == false) {
2116                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2117                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2118         } else {
2119                 status = WERR_OK;
2120         }
2121
2122 done:
2123         talloc_free(tmp_ctx);
2124
2125         return status;
2126 }
2127
2128 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2129                                   struct pipes_struct *p,
2130                                   struct spoolss_DeletePrinterDriverEx *r,
2131                                   struct dcerpc_binding_handle *b,
2132                                   struct spoolss_DriverInfo8 *info)
2133 {
2134         WERROR status;
2135         bool delete_files;
2136
2137         if (printer_driver_in_use(mem_ctx, b, info)) {
2138                 status = WERR_PRINTER_DRIVER_IN_USE;
2139                 goto done;
2140         }
2141
2142         /*
2143          * we have a couple of cases to consider.
2144          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2145          *     then the delete should fail if **any** files overlap with
2146          *     other drivers
2147          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2148          *     non-overlapping files
2149          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2150          *     are set, then do not delete any files
2151          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152          */
2153
2154         delete_files = r->in.delete_flags
2155                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2156
2157
2158         if (delete_files) {
2159                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2160                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2161                         status = WERR_PRINTER_DRIVER_IN_USE;
2162                         goto done;
2163                 }
2164                 /*
2165                  * printer_driver_files_in_use() has trimmed overlapping files
2166                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2167                  */
2168         }
2169
2170
2171         status = winreg_del_driver(mem_ctx, b, info, info->version);
2172         if (!W_ERROR_IS_OK(status)) {
2173                 goto done;
2174         }
2175
2176         /*
2177          * now delete any associated files if delete_files is
2178          * true. Even if this part failes, we return succes
2179          * because the driver doesn not exist any more
2180          */
2181         if (delete_files) {
2182                 delete_driver_files(p->session_info, info);
2183         }
2184
2185 done:
2186         return status;
2187 }
2188
2189 /****************************************************************
2190  _spoolss_DeletePrinterDriverEx
2191 ****************************************************************/
2192
2193 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2194                                       struct spoolss_DeletePrinterDriverEx *r)
2195 {
2196         struct spoolss_DriverInfo8 *info = NULL;
2197         WERROR                          status;
2198         struct dcerpc_binding_handle *b;
2199         TALLOC_CTX *tmp_ctx = NULL;
2200         int i;
2201         bool found;
2202
2203         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2204            and not a printer admin, then fail */
2205
2206         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2207             !security_token_has_privilege(p->session_info->security_token,
2208                                           SEC_PRIV_PRINT_OPERATOR)) {
2209                 return WERR_ACCESS_DENIED;
2210         }
2211
2212         /* check that we have a valid driver name first */
2213         if (get_version_id(r->in.architecture) == -1) {
2214                 /* this is what NT returns */
2215                 return WERR_INVALID_ENVIRONMENT;
2216         }
2217
2218         tmp_ctx = talloc_new(p->mem_ctx);
2219         if (!tmp_ctx) {
2220                 return WERR_NOMEM;
2221         }
2222
2223         status = winreg_printer_binding_handle(tmp_ctx,
2224                                                get_session_info_system(),
2225                                                p->msg_ctx,
2226                                                &b);
2227         if (!W_ERROR_IS_OK(status)) {
2228                 goto done;
2229         }
2230
2231         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2232                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2233                  && (drv_cversion[i] != r->in.version)) {
2234                         continue;
2235                 }
2236
2237                 /* check if a driver with this version exists before delete */
2238                 status = winreg_get_driver(tmp_ctx, b,
2239                                            r->in.architecture, r->in.driver,
2240                                            drv_cversion[i], &info);
2241                 if (!W_ERROR_IS_OK(status)) {
2242                         DEBUG(5, ("skipping del of driver with version %d\n",
2243                                   drv_cversion[i]));
2244                         continue;
2245                 }
2246                 found = true;
2247
2248                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2249                 if (!W_ERROR_IS_OK(status)) {
2250                         DEBUG(0, ("failed to delete driver with version %d\n",
2251                                   drv_cversion[i]));
2252                         goto done;
2253                 }
2254         }
2255         if (found == false) {
2256                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2257                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2258         } else {
2259                 status = WERR_OK;
2260         }
2261
2262 done:
2263         talloc_free(tmp_ctx);
2264         return status;
2265 }
2266
2267
2268 /********************************************************************
2269  GetPrinterData on a printer server Handle.
2270 ********************************************************************/
2271
2272 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2273                                             const char *value,
2274                                             enum winreg_Type *type,
2275                                             union spoolss_PrinterData *data)
2276 {
2277         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2278
2279         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2280                 *type = REG_DWORD;
2281                 SIVAL(&data->value, 0, 0x00);
2282                 return WERR_OK;
2283         }
2284
2285         if (!strcasecmp_m(value, "BeepEnabled")) {
2286                 *type = REG_DWORD;
2287                 SIVAL(&data->value, 0, 0x00);
2288                 return WERR_OK;
2289         }
2290
2291         if (!strcasecmp_m(value, "EventLog")) {
2292                 *type = REG_DWORD;
2293                 /* formally was 0x1b */
2294                 SIVAL(&data->value, 0, 0x00);
2295                 return WERR_OK;
2296         }
2297
2298         if (!strcasecmp_m(value, "NetPopup")) {
2299                 *type = REG_DWORD;
2300                 SIVAL(&data->value, 0, 0x00);
2301                 return WERR_OK;
2302         }
2303
2304         if (!strcasecmp_m(value, "MajorVersion")) {
2305                 *type = REG_DWORD;
2306
2307                 /* Windows NT 4.0 seems to not allow uploading of drivers
2308                    to a server that reports 0x3 as the MajorVersion.
2309                    need to investigate more how Win2k gets around this .
2310                    -- jerry */
2311
2312                 if (RA_WINNT == get_remote_arch()) {
2313                         SIVAL(&data->value, 0, 0x02);
2314                 } else {
2315                         SIVAL(&data->value, 0, 0x03);
2316                 }
2317
2318                 return WERR_OK;
2319         }
2320
2321         if (!strcasecmp_m(value, "MinorVersion")) {
2322                 *type = REG_DWORD;
2323                 SIVAL(&data->value, 0, 0x00);
2324                 return WERR_OK;
2325         }
2326
2327         /* REG_BINARY
2328          *  uint32_t size        = 0x114
2329          *  uint32_t major       = 5
2330          *  uint32_t minor       = [0|1]
2331          *  uint32_t build       = [2195|2600]
2332          *  extra unicode string = e.g. "Service Pack 3"
2333          */
2334         if (!strcasecmp_m(value, "OSVersion")) {
2335                 DATA_BLOB blob;
2336                 enum ndr_err_code ndr_err;
2337                 struct spoolss_OSVersion os;
2338
2339                 os.major                = 5;    /* Windows 2000 == 5.0 */
2340                 os.minor                = 0;
2341                 os.build                = 2195; /* build */
2342                 os.extra_string         = "";   /* leave extra string empty */
2343
2344                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2345                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2346                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2347                         return WERR_GENERAL_FAILURE;
2348                 }
2349
2350                 *type = REG_BINARY;
2351                 data->binary = blob;
2352
2353                 return WERR_OK;
2354         }
2355
2356
2357         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2358                 *type = REG_SZ;
2359
2360                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2361                 W_ERROR_HAVE_NO_MEMORY(data->string);
2362
2363                 return WERR_OK;
2364         }
2365
2366         if (!strcasecmp_m(value, "Architecture")) {
2367                 *type = REG_SZ;
2368                 data->string = talloc_strdup(mem_ctx,
2369                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2370                 W_ERROR_HAVE_NO_MEMORY(data->string);
2371
2372                 return WERR_OK;
2373         }
2374
2375         if (!strcasecmp_m(value, "DsPresent")) {
2376                 *type = REG_DWORD;
2377
2378                 /* only show the publish check box if we are a
2379                    member of a AD domain */
2380
2381                 if (lp_security() == SEC_ADS) {
2382                         SIVAL(&data->value, 0, 0x01);
2383                 } else {
2384                         SIVAL(&data->value, 0, 0x00);
2385                 }
2386                 return WERR_OK;
2387         }
2388
2389         if (!strcasecmp_m(value, "DNSMachineName")) {
2390                 const char *hostname = get_mydnsfullname();
2391
2392                 if (!hostname) {
2393                         return WERR_BADFILE;
2394                 }
2395
2396                 *type = REG_SZ;
2397                 data->string = talloc_strdup(mem_ctx, hostname);
2398                 W_ERROR_HAVE_NO_MEMORY(data->string);
2399
2400                 return WERR_OK;
2401         }
2402
2403         *type = REG_NONE;
2404
2405         return WERR_INVALID_PARAM;
2406 }
2407
2408 /****************************************************************
2409  _spoolss_GetPrinterData
2410 ****************************************************************/
2411
2412 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2413                                struct spoolss_GetPrinterData *r)
2414 {
2415         struct spoolss_GetPrinterDataEx r2;
2416
2417         r2.in.handle            = r->in.handle;
2418         r2.in.key_name          = "PrinterDriverData";
2419         r2.in.value_name        = r->in.value_name;
2420         r2.in.offered           = r->in.offered;
2421         r2.out.type             = r->out.type;
2422         r2.out.data             = r->out.data;
2423         r2.out.needed           = r->out.needed;
2424
2425         return _spoolss_GetPrinterDataEx(p, &r2);
2426 }
2427
2428 /*********************************************************
2429  Connect to the client machine.
2430 **********************************************************/
2431
2432 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2433                         struct sockaddr_storage *client_ss, const char *remote_machine)
2434 {
2435         NTSTATUS ret;
2436         struct cli_state *the_cli;
2437         struct sockaddr_storage rm_addr;
2438         char addr[INET6_ADDRSTRLEN];
2439
2440         if ( is_zero_addr(client_ss) ) {
2441                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2442                         remote_machine));
2443                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2444                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2445                         return false;
2446                 }
2447                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2448         } else {
2449                 rm_addr = *client_ss;
2450                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2451                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2452                         addr));
2453         }
2454
2455         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2456                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2457                         addr));
2458                 return false;
2459         }
2460
2461         /* setup the connection */
2462         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2463                 &rm_addr, 0, "IPC$", "IPC",
2464                 "", /* username */
2465                 "", /* domain */
2466                 "", /* password */
2467                 0, lp_client_signing());
2468
2469         if ( !NT_STATUS_IS_OK( ret ) ) {
2470                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2471                         remote_machine ));
2472                 return false;
2473         }
2474
2475         if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2476                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2477                 cli_shutdown(the_cli);
2478                 return false;
2479         }
2480
2481         /*
2482          * Ok - we have an anonymous connection to the IPC$ share.
2483          * Now start the NT Domain stuff :-).
2484          */
2485
2486         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2487         if (!NT_STATUS_IS_OK(ret)) {
2488                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2489                         remote_machine, nt_errstr(ret)));
2490                 cli_shutdown(the_cli);
2491                 return false;
2492         }
2493
2494         return true;
2495 }
2496
2497 /***************************************************************************
2498  Connect to the client.
2499 ****************************************************************************/
2500
2501 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2502                                         uint32_t localprinter,
2503                                         enum winreg_Type type,
2504                                         struct policy_handle *handle,
2505                                         struct notify_back_channel **_chan,
2506                                         struct sockaddr_storage *client_ss,
2507                                         struct messaging_context *msg_ctx)
2508 {
2509         WERROR result;
2510         NTSTATUS status;
2511         struct notify_back_channel *chan;
2512
2513         for (chan = back_channels; chan; chan = chan->next) {
2514                 if (memcmp(&chan->client_address, client_ss,
2515                            sizeof(struct sockaddr_storage)) == 0) {
2516                         break;
2517                 }
2518         }
2519
2520         /*
2521          * If it's the first connection, contact the client
2522          * and connect to the IPC$ share anonymously
2523          */
2524         if (!chan) {
2525                 fstring unix_printer;
2526
2527                 /* the +2 is to strip the leading 2 backslashs */
2528                 fstrcpy(unix_printer, printer + 2);
2529
2530                 chan = talloc_zero(NULL, struct notify_back_channel);
2531                 if (!chan) {
2532                         return false;
2533                 }
2534                 chan->client_address = *client_ss;
2535
2536                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2537                         TALLOC_FREE(chan);
2538                         return false;
2539                 }
2540
2541                 DLIST_ADD(back_channels, chan);
2542
2543                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2544                                    receive_notify2_message_list);
2545         }
2546
2547         if (chan->cli_pipe == NULL ||
2548             chan->cli_pipe->binding_handle == NULL) {
2549                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2550                         "NULL %s for printer %s\n",
2551                         chan->cli_pipe == NULL ?
2552                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2553                         printer));
2554                 return false;
2555         }
2556
2557         /*
2558          * Tell the specific printing tdb we want messages for this printer
2559          * by registering our PID.
2560          */
2561
2562         if (!print_notify_register_pid(snum)) {
2563                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2564                           printer));
2565         }
2566
2567         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2568                                                  talloc_tos(),
2569                                                  printer,
2570                                                  localprinter,
2571                                                  type,
2572                                                  0,
2573                                                  NULL,
2574                                                  handle,
2575                                                  &result);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2578                 result = ntstatus_to_werror(status);
2579         } else if (!W_ERROR_IS_OK(result)) {
2580                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2581         }
2582
2583         chan->active_connections++;
2584         *_chan = chan;
2585
2586         return (W_ERROR_IS_OK(result));
2587 }
2588
2589 /****************************************************************
2590  ****************************************************************/
2591
2592 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2593                                                              const struct spoolss_NotifyOption *r)
2594 {
2595         struct spoolss_NotifyOption *option;
2596         uint32_t i,k;
2597
2598         if (!r) {
2599                 return NULL;
2600         }
2601
2602         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2603         if (!option) {
2604                 return NULL;
2605         }
2606
2607         *option = *r;
2608
2609         if (!option->count) {
2610                 return option;
2611         }
2612
2613         option->types = talloc_zero_array(option,
2614                 struct spoolss_NotifyOptionType, option->count);
2615         if (!option->types) {
2616                 talloc_free(option);
2617                 return NULL;
2618         }
2619
2620         for (i=0; i < option->count; i++) {
2621                 option->types[i] = r->types[i];
2622
2623                 if (option->types[i].count) {
2624                         option->types[i].fields = talloc_zero_array(option,
2625                                 union spoolss_Field, option->types[i].count);
2626                         if (!option->types[i].fields) {
2627                                 talloc_free(option);
2628                                 return NULL;
2629                         }
2630                         for (k=0; k<option->types[i].count; k++) {
2631                                 option->types[i].fields[k] =
2632                                         r->types[i].fields[k];
2633                         }
2634                 }
2635         }
2636
2637         return option;
2638 }
2639
2640 /****************************************************************
2641  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2642  *
2643  * before replying OK: status=0 a rpc call is made to the workstation
2644  * asking ReplyOpenPrinter
2645  *
2646  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2647  * called from api_spoolss_rffpcnex
2648 ****************************************************************/
2649
2650 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2651                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2652 {
2653         int snum = -1;
2654         struct spoolss_NotifyOption *option = r->in.notify_options;
2655         struct sockaddr_storage client_ss;
2656         ssize_t client_len;
2657
2658         /* store the notify value in the printer struct */
2659
2660         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2661
2662         if (!Printer) {
2663                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2664                         "Invalid handle (%s:%u:%u).\n",
2665                         OUR_HANDLE(r->in.handle)));
2666                 return WERR_BADFID;
2667         }
2668
2669         Printer->notify.flags           = r->in.flags;
2670         Printer->notify.options         = r->in.options;
2671         Printer->notify.printerlocal    = r->in.printer_local;
2672         Printer->notify.msg_ctx         = p->msg_ctx;
2673
2674         TALLOC_FREE(Printer->notify.option);
2675         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2676
2677         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2678
2679         /* Connect to the client machine and send a ReplyOpenPrinter */
2680
2681         if ( Printer->printer_type == SPLHND_SERVER)
2682                 snum = -1;
2683         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2684                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2685                 return WERR_BADFID;
2686
2687         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2688                   "remote_address is %s\n",
2689                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2690
2691         if (!lp_print_notify_backchannel(snum)) {
2692                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2693                         "backchannel disabled\n"));
2694                 return WERR_SERVER_UNAVAILABLE;
2695         }
2696
2697         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2698                                                   (struct sockaddr *) &client_ss,
2699                                                   sizeof(struct sockaddr_storage));
2700         if (client_len < 0) {
2701                 return WERR_NOMEM;
2702         }
2703
2704         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2705                                         Printer->notify.printerlocal, REG_SZ,
2706                                         &Printer->notify.cli_hnd,
2707                                         &Printer->notify.cli_chan,
2708                                         &client_ss, p->msg_ctx)) {
2709                 return WERR_SERVER_UNAVAILABLE;
2710         }
2711
2712         return WERR_OK;
2713 }
2714
2715 /*******************************************************************
2716  * fill a notify_info_data with the servername
2717  ********************************************************************/
2718
2719 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2720                                        int snum,
2721                                        struct spoolss_Notify *data,
2722                                        print_queue_struct *queue,
2723                                        struct spoolss_PrinterInfo2 *pinfo2,
2724                                        TALLOC_CTX *mem_ctx)
2725 {
2726         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2727 }
2728
2729 /*******************************************************************
2730  * fill a notify_info_data with the printername (not including the servername).
2731  ********************************************************************/
2732
2733 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2734                                         int snum,
2735                                         struct spoolss_Notify *data,
2736                                         print_queue_struct *queue,
2737                                         struct spoolss_PrinterInfo2 *pinfo2,
2738                                         TALLOC_CTX *mem_ctx)
2739 {
2740         /* the notify name should not contain the \\server\ part */
2741         const char *p = strrchr(pinfo2->printername, '\\');
2742
2743         if (!p) {
2744                 p = pinfo2->printername;
2745         } else {
2746                 p++;
2747         }
2748
2749         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2750 }
2751
2752 /*******************************************************************
2753  * fill a notify_info_data with the servicename
2754  ********************************************************************/
2755
2756 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2757                                       int snum,
2758                                       struct spoolss_Notify *data,
2759                                       print_queue_struct *queue,
2760                                       struct spoolss_PrinterInfo2 *pinfo2,
2761                                       TALLOC_CTX *mem_ctx)
2762 {
2763         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the port name
2768  ********************************************************************/
2769
2770 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2771                                      int snum,
2772                                      struct spoolss_Notify *data,
2773                                      print_queue_struct *queue,
2774                                      struct spoolss_PrinterInfo2 *pinfo2,
2775                                      TALLOC_CTX *mem_ctx)
2776 {
2777         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2778 }
2779
2780 /*******************************************************************
2781  * fill a notify_info_data with the printername
2782  * but it doesn't exist, have to see what to do
2783  ********************************************************************/
2784
2785 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2786                                        int snum,
2787                                        struct spoolss_Notify *data,
2788                                        print_queue_struct *queue,
2789                                        struct spoolss_PrinterInfo2 *pinfo2,
2790                                        TALLOC_CTX *mem_ctx)
2791 {
2792         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2793 }
2794
2795 /*******************************************************************
2796  * fill a notify_info_data with the comment
2797  ********************************************************************/
2798
2799 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2800                                    int snum,
2801                                    struct spoolss_Notify *data,
2802                                    print_queue_struct *queue,
2803                                    struct spoolss_PrinterInfo2 *pinfo2,
2804                                    TALLOC_CTX *mem_ctx)
2805 {
2806         const char *p;
2807
2808         if (*pinfo2->comment == '\0') {
2809                 p = lp_comment(talloc_tos(), snum);
2810         } else {
2811                 p = pinfo2->comment;
2812         }
2813
2814         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the comment
2819  * location = "Room 1, floor 2, building 3"
2820  ********************************************************************/
2821
2822 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2823                                     int snum,
2824                                     struct spoolss_Notify *data,
2825                                     print_queue_struct *queue,
2826                                     struct spoolss_PrinterInfo2 *pinfo2,
2827                                     TALLOC_CTX *mem_ctx)
2828 {
2829         const char *loc = pinfo2->location;
2830         NTSTATUS status;
2831
2832         status = printer_list_get_printer(mem_ctx,
2833                                           pinfo2->sharename,
2834                                           NULL,
2835                                           &loc,
2836                                           NULL);
2837         if (NT_STATUS_IS_OK(status)) {
2838                 if (loc == NULL) {
2839                         loc = pinfo2->location;
2840                 }
2841         }
2842
2843         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the device mode
2848  * jfm:xxxx don't to it for know but that's a real problem !!!
2849  ********************************************************************/
2850
2851 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2852                                    int snum,
2853                                    struct spoolss_Notify *data,
2854                                    print_queue_struct *queue,
2855                                    struct spoolss_PrinterInfo2 *pinfo2,
2856                                    TALLOC_CTX *mem_ctx)
2857 {
2858         /* for a dummy implementation we have to zero the fields */
2859         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2860 }
2861
2862 /*******************************************************************
2863  * fill a notify_info_data with the separator file name
2864  ********************************************************************/
2865
2866 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2867                                    int snum,
2868                                    struct spoolss_Notify *data,
2869                                    print_queue_struct *queue,
2870                                    struct spoolss_PrinterInfo2 *pinfo2,
2871                                    TALLOC_CTX *mem_ctx)
2872 {
2873         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2874 }
2875
2876 /*******************************************************************
2877  * fill a notify_info_data with the print processor
2878  * jfm:xxxx return always winprint to indicate we don't do anything to it
2879  ********************************************************************/
2880
2881 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2882                                            int snum,
2883                                            struct spoolss_Notify *data,
2884                                            print_queue_struct *queue,
2885                                            struct spoolss_PrinterInfo2 *pinfo2,
2886                                            TALLOC_CTX *mem_ctx)
2887 {
2888         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2889 }
2890
2891 /*******************************************************************
2892  * fill a notify_info_data with the print processor options
2893  * jfm:xxxx send an empty string
2894  ********************************************************************/
2895
2896 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2897                                       int snum,
2898                                       struct spoolss_Notify *data,
2899                                       print_queue_struct *queue,
2900                                       struct spoolss_PrinterInfo2 *pinfo2,
2901                                       TALLOC_CTX *mem_ctx)
2902 {
2903         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2904 }
2905
2906 /*******************************************************************
2907  * fill a notify_info_data with the data type
2908  * jfm:xxxx always send RAW as data type
2909  ********************************************************************/
2910
2911 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2912                                     int snum,
2913                                     struct spoolss_Notify *data,
2914                                     print_queue_struct *queue,
2915                                     struct spoolss_PrinterInfo2 *pinfo2,
2916                                     TALLOC_CTX *mem_ctx)
2917 {
2918         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2919 }
2920
2921 /*******************************************************************
2922  * fill a notify_info_data with the security descriptor
2923  * jfm:xxxx send an null pointer to say no security desc
2924  * have to implement security before !
2925  ********************************************************************/
2926
2927 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2928                                          int snum,
2929                                          struct spoolss_Notify *data,
2930                                          print_queue_struct *queue,
2931                                          struct spoolss_PrinterInfo2 *pinfo2,
2932                                          TALLOC_CTX *mem_ctx)
2933 {
2934         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2935 }
2936
2937 /*******************************************************************
2938  * fill a notify_info_data with the attributes
2939  * jfm:xxxx a samba printer is always shared
2940  ********************************************************************/
2941
2942 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2943                                       int snum,
2944                                       struct spoolss_Notify *data,
2945                                       print_queue_struct *queue,
2946                                       struct spoolss_PrinterInfo2 *pinfo2,
2947                                       TALLOC_CTX *mem_ctx)
2948 {
2949         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2950 }
2951
2952 /*******************************************************************
2953  * fill a notify_info_data with the priority
2954  ********************************************************************/
2955
2956 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2957                                     int snum,
2958                                     struct spoolss_Notify *data,
2959                                     print_queue_struct *queue,
2960                                     struct spoolss_PrinterInfo2 *pinfo2,
2961                                     TALLOC_CTX *mem_ctx)
2962 {
2963         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2964 }
2965
2966 /*******************************************************************
2967  * fill a notify_info_data with the default priority
2968  ********************************************************************/
2969
2970 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2971                                             int snum,
2972                                             struct spoolss_Notify *data,
2973                                             print_queue_struct *queue,
2974                                             struct spoolss_PrinterInfo2 *pinfo2,
2975                                             TALLOC_CTX *mem_ctx)
2976 {
2977         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2978 }
2979
2980 /*******************************************************************
2981  * fill a notify_info_data with the start time
2982  ********************************************************************/
2983
2984 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2985                                       int snum,
2986                                       struct spoolss_Notify *data,
2987                                       print_queue_struct *queue,
2988                                       struct spoolss_PrinterInfo2 *pinfo2,
2989                                       TALLOC_CTX *mem_ctx)
2990 {
2991         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2992 }
2993
2994 /*******************************************************************
2995  * fill a notify_info_data with the until time
2996  ********************************************************************/
2997
2998 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2999                                       int snum,
3000                                       struct spoolss_Notify *data,
3001                                       print_queue_struct *queue,
3002                                       struct spoolss_PrinterInfo2 *pinfo2,
3003                                       TALLOC_CTX *mem_ctx)
3004 {
3005         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3006 }
3007
3008 /*******************************************************************
3009  * fill a notify_info_data with the status
3010  ********************************************************************/
3011
3012 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3013                                   int snum,
3014                                   struct spoolss_Notify *data,
3015                                   print_queue_struct *queue,
3016                                   struct spoolss_PrinterInfo2 *pinfo2,
3017                                   TALLOC_CTX *mem_ctx)
3018 {
3019         print_status_struct status;
3020
3021         print_queue_length(msg_ctx, snum, &status);
3022         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3023 }
3024
3025 /*******************************************************************
3026  * fill a notify_info_data with the number of jobs queued
3027  ********************************************************************/
3028
3029 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3030                                  int snum,
3031                                  struct spoolss_Notify *data,
3032                                  print