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