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