3a71e7cef33e928e3f1e6b2b5daaca25d30f4381
[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  *  Copyright (C) Guenther Deschner            2009-2010.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "librpc/gen_ndr/messaging.h"
33
34 /* macros stolen from s4 spoolss server */
35 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
36         ((info)?ndr_size_##fn(info, level, ic, 0):0)
37
38 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
39         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
40
41 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
42         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
43
44 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
45
46
47 extern userdom_struct current_user_info;
48
49 #undef DBGC_CLASS
50 #define DBGC_CLASS DBGC_RPC_SRV
51
52 #ifndef MAX_OPEN_PRINTER_EXS
53 #define MAX_OPEN_PRINTER_EXS 50
54 #endif
55
56 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
57 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
58
59 static Printer_entry *printers_list;
60
61 typedef struct _counter_printer_0 {
62         struct _counter_printer_0 *next;
63         struct _counter_printer_0 *prev;
64
65         int snum;
66         uint32_t counter;
67 } counter_printer_0;
68
69 static counter_printer_0 *counter_list;
70
71 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
72 static uint32_t smb_connections = 0;
73
74
75 /* in printing/nt_printing.c */
76
77 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
78
79 /* API table for Xcv Monitor functions */
80
81 struct xcv_api_table {
82         const char *name;
83         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
84 };
85
86 /********************************************************************
87  * Canonicalize servername.
88  ********************************************************************/
89
90 static const char *canon_servername(const char *servername)
91 {
92         const char *pservername = servername;
93         while (*pservername == '\\') {
94                 pservername++;
95         }
96         return pservername;
97 }
98
99 /* translate between internal status numbers and NT status numbers */
100 static int nt_printj_status(int v)
101 {
102         switch (v) {
103         case LPQ_QUEUED:
104                 return 0;
105         case LPQ_PAUSED:
106                 return JOB_STATUS_PAUSED;
107         case LPQ_SPOOLING:
108                 return JOB_STATUS_SPOOLING;
109         case LPQ_PRINTING:
110                 return JOB_STATUS_PRINTING;
111         case LPQ_ERROR:
112                 return JOB_STATUS_ERROR;
113         case LPQ_DELETING:
114                 return JOB_STATUS_DELETING;
115         case LPQ_OFFLINE:
116                 return JOB_STATUS_OFFLINE;
117         case LPQ_PAPEROUT:
118                 return JOB_STATUS_PAPEROUT;
119         case LPQ_PRINTED:
120                 return JOB_STATUS_PRINTED;
121         case LPQ_DELETED:
122                 return JOB_STATUS_DELETED;
123         case LPQ_BLOCKED:
124                 return JOB_STATUS_BLOCKED_DEVQ;
125         case LPQ_USER_INTERVENTION:
126                 return JOB_STATUS_USER_INTERVENTION;
127         }
128         return 0;
129 }
130
131 static int nt_printq_status(int v)
132 {
133         switch (v) {
134         case LPQ_PAUSED:
135                 return PRINTER_STATUS_PAUSED;
136         case LPQ_QUEUED:
137         case LPQ_SPOOLING:
138         case LPQ_PRINTING:
139                 return 0;
140         }
141         return 0;
142 }
143
144 /***************************************************************************
145  Disconnect from the client
146 ****************************************************************************/
147
148 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
149 {
150         WERROR result;
151         NTSTATUS status;
152
153         /*
154          * Tell the specific printing tdb we no longer want messages for this printer
155          * by deregistering our PID.
156          */
157
158         if (!print_notify_deregister_pid(snum))
159                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
160
161         /* weird if the test succeds !!! */
162         if (smb_connections==0) {
163                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164                 return;
165         }
166
167         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
168                                                   handle,
169                                                   &result);
170         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
171                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
172                         win_errstr(result)));
173
174         /* if it's the last connection, deconnect the IPC$ share */
175         if (smb_connections==1) {
176
177                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
178                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
179
180                 messaging_deregister(smbd_messaging_context(),
181                                      MSG_PRINTER_NOTIFY2, NULL);
182
183                 /* Tell the connections db we're no longer interested in
184                  * printer notify messages. */
185
186                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
187         }
188
189         smb_connections--;
190 }
191
192 /****************************************************************************
193  Functions to free a printer entry datastruct.
194 ****************************************************************************/
195
196 static int printer_entry_destructor(Printer_entry *Printer)
197 {
198         if (Printer->notify.client_connected == true) {
199                 int snum = -1;
200
201                 if ( Printer->printer_type == SPLHND_SERVER) {
202                         snum = -1;
203                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
204                 } else if (Printer->printer_type == SPLHND_PRINTER) {
205                         snum = print_queue_snum(Printer->sharename);
206                         if (snum != -1)
207                                 srv_spoolss_replycloseprinter(snum,
208                                                 &Printer->notify.client_hnd);
209                 }
210         }
211
212         Printer->notify.flags=0;
213         Printer->notify.options=0;
214         Printer->notify.localmachine[0]='\0';
215         Printer->notify.printerlocal=0;
216         TALLOC_FREE(Printer->notify.option);
217         Printer->notify.client_connected = false;
218
219         free_nt_devicemode( &Printer->nt_devmode );
220         free_a_printer( &Printer->printer_info, 2 );
221
222         /* Remove from the internal list. */
223         DLIST_REMOVE(printers_list, Printer);
224         return 0;
225 }
226
227 /****************************************************************************
228   find printer index by handle
229 ****************************************************************************/
230
231 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
232                                                 struct policy_handle *hnd)
233 {
234         Printer_entry *find_printer = NULL;
235
236         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
237                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
238                 return NULL;
239         }
240
241         return find_printer;
242 }
243
244 /****************************************************************************
245  Close printer index by handle.
246 ****************************************************************************/
247
248 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
249 {
250         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
251
252         if (!Printer) {
253                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
254                         OUR_HANDLE(hnd)));
255                 return false;
256         }
257
258         close_policy_hnd(p, hnd);
259
260         return true;
261 }
262
263 /****************************************************************************
264  Delete a printer given a handle.
265 ****************************************************************************/
266
267 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
268 {
269         char *cmd = lp_deleteprinter_cmd();
270         char *command = NULL;
271         int ret;
272         SE_PRIV se_printop = SE_PRINT_OPERATOR;
273         bool is_print_op = false;
274
275         /* can't fail if we don't try */
276
277         if ( !*cmd )
278                 return WERR_OK;
279
280         command = talloc_asprintf(ctx,
281                         "%s \"%s\"",
282                         cmd, sharename);
283         if (!command) {
284                 return WERR_NOMEM;
285         }
286         if ( token )
287                 is_print_op = user_has_privileges( token, &se_printop );
288
289         DEBUG(10,("Running [%s]\n", command));
290
291         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
292
293         if ( is_print_op )
294                 become_root();
295
296         if ( (ret = smbrun(command, NULL)) == 0 ) {
297                 /* Tell everyone we updated smb.conf. */
298                 message_send_all(smbd_messaging_context(),
299                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
300         }
301
302         if ( is_print_op )
303                 unbecome_root();
304
305         /********** END SePrintOperatorPrivlege BLOCK **********/
306
307         DEBUGADD(10,("returned [%d]\n", ret));
308
309         TALLOC_FREE(command);
310
311         if (ret != 0)
312                 return WERR_BADFID; /* What to return here? */
313
314         /* go ahead and re-read the services immediately */
315         become_root();
316         reload_services(false);
317         unbecome_root();
318
319         if ( lp_servicenumber( sharename )  > 0 )
320                 return WERR_ACCESS_DENIED;
321
322         return WERR_OK;
323 }
324
325 /****************************************************************************
326  Delete a printer given a handle.
327 ****************************************************************************/
328
329 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
330 {
331         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
332
333         if (!Printer) {
334                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
335                         OUR_HANDLE(hnd)));
336                 return WERR_BADFID;
337         }
338
339         /*
340          * It turns out that Windows allows delete printer on a handle
341          * opened by an admin user, then used on a pipe handle created
342          * by an anonymous user..... but they're working on security.... riiight !
343          * JRA.
344          */
345
346         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
347                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
348                 return WERR_ACCESS_DENIED;
349         }
350
351         /* this does not need a become root since the access check has been
352            done on the handle already */
353
354         if (del_a_printer( Printer->sharename ) != 0) {
355                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
356                 return WERR_BADFID;
357         }
358
359         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
360                                    Printer->sharename );
361 }
362
363 /****************************************************************************
364  Return the snum of a printer corresponding to an handle.
365 ****************************************************************************/
366
367 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
368                              int *number, struct share_params **params)
369 {
370         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
371
372         if (!Printer) {
373                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
374                         OUR_HANDLE(hnd)));
375                 return false;
376         }
377
378         switch (Printer->printer_type) {
379                 case SPLHND_PRINTER:
380                         DEBUG(4,("short name:%s\n", Printer->sharename));
381                         *number = print_queue_snum(Printer->sharename);
382                         return (*number != -1);
383                 case SPLHND_SERVER:
384                         return false;
385                 default:
386                         return false;
387         }
388 }
389
390 /****************************************************************************
391  Set printer handle type.
392  Check if it's \\server or \\server\printer
393 ****************************************************************************/
394
395 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
396 {
397         DEBUG(3,("Setting printer type=%s\n", handlename));
398
399         if ( strlen(handlename) < 3 ) {
400                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401                 return false;
402         }
403
404         /* it's a print server */
405         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
406                 DEBUGADD(4,("Printer is a print server\n"));
407                 Printer->printer_type = SPLHND_SERVER;
408         }
409         /* it's a printer (set_printer_hnd_name() will handle port monitors */
410         else {
411                 DEBUGADD(4,("Printer is a printer\n"));
412                 Printer->printer_type = SPLHND_PRINTER;
413         }
414
415         return true;
416 }
417
418 /****************************************************************************
419  Set printer handle name..  Accept names like \\server, \\server\printer,
420  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
421  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
422  XcvDataPort() interface.
423 ****************************************************************************/
424
425 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
426 {
427         int snum;
428         int n_services=lp_numservices();
429         char *aprinter, *printername;
430         const char *servername;
431         fstring sname;
432         bool found = false;
433         NT_PRINTER_INFO_LEVEL *printer = NULL;
434         WERROR result;
435
436         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
437                 (unsigned long)strlen(handlename)));
438
439         aprinter = CONST_DISCARD(char *, handlename);
440         if ( *handlename == '\\' ) {
441                 servername = canon_servername(handlename);
442                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
443                         *aprinter = '\0';
444                         aprinter++;
445                 }
446         } else {
447                 servername = global_myname();
448         }
449
450         /* save the servername to fill in replies on this handle */
451
452         if ( !is_myname_or_ipaddr( servername ) )
453                 return false;
454
455         fstrcpy( Printer->servername, servername );
456
457         if ( Printer->printer_type == SPLHND_SERVER )
458                 return true;
459
460         if ( Printer->printer_type != SPLHND_PRINTER )
461                 return false;
462
463         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
464
465         /* check for the Port Monitor Interface */
466
467         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
468                 Printer->printer_type = SPLHND_PORTMON_TCP;
469                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
470                 found = true;
471         }
472         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
473                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
474                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
475                 found = true;
476         }
477
478         /* Search all sharenames first as this is easier than pulling
479            the printer_info_2 off of disk. Don't use find_service() since
480            that calls out to map_username() */
481
482         /* do another loop to look for printernames */
483
484         for (snum=0; !found && snum<n_services; snum++) {
485
486                 /* no point going on if this is not a printer */
487
488                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
489                         continue;
490
491                 fstrcpy(sname, lp_servicename(snum));
492                 if ( strequal( aprinter, sname ) ) {
493                         found = true;
494                         break;
495                 }
496
497                 /* no point looking up the printer object if
498                    we aren't allowing printername != sharename */
499
500                 if ( lp_force_printername(snum) )
501                         continue;
502
503                 fstrcpy(sname, lp_servicename(snum));
504
505                 printer = NULL;
506
507                 /* This call doesn't fill in the location or comment from
508                  * a CUPS server for efficiency with large numbers of printers.
509                  * JRA.
510                  */
511
512                 result = get_a_printer_search( NULL, &printer, 2, sname );
513                 if ( !W_ERROR_IS_OK(result) ) {
514                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
515                                 sname, win_errstr(result)));
516                         continue;
517                 }
518
519                 /* printername is always returned as \\server\printername */
520                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
521                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
522                                 printer->info_2->printername));
523                         free_a_printer( &printer, 2);
524                         continue;
525                 }
526
527                 printername++;
528
529                 if ( strequal(printername, aprinter) ) {
530                         free_a_printer( &printer, 2);
531                         found = true;
532                         break;
533                 }
534
535                 DEBUGADD(10, ("printername: %s\n", printername));
536
537                 free_a_printer( &printer, 2);
538         }
539
540         free_a_printer( &printer, 2);
541
542         if ( !found ) {
543                 DEBUGADD(4,("Printer not found\n"));
544                 return false;
545         }
546
547         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
548
549         fstrcpy(Printer->sharename, sname);
550
551         return true;
552 }
553
554 /****************************************************************************
555  Find first available printer slot. creates a printer handle for you.
556  ****************************************************************************/
557
558 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
559                              const char *name, uint32_t access_granted)
560 {
561         Printer_entry *new_printer;
562
563         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
564
565         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
566         if (new_printer == NULL) {
567                 return false;
568         }
569         talloc_set_destructor(new_printer, printer_entry_destructor);
570
571         if (!create_policy_hnd(p, hnd, new_printer)) {
572                 TALLOC_FREE(new_printer);
573                 return false;
574         }
575
576         /* Add to the internal list. */
577         DLIST_ADD(printers_list, new_printer);
578
579         new_printer->notify.option=NULL;
580
581         if (!set_printer_hnd_printertype(new_printer, name)) {
582                 close_printer_handle(p, hnd);
583                 return false;
584         }
585
586         if (!set_printer_hnd_name(new_printer, name)) {
587                 close_printer_handle(p, hnd);
588                 return false;
589         }
590
591         new_printer->access_granted = access_granted;
592
593         DEBUG(5, ("%d printer handles active\n",
594                   (int)num_pipe_handles(p->pipe_handles)));
595
596         return true;
597 }
598
599 /***************************************************************************
600  check to see if the client motify handle is monitoring the notification
601  given by (notify_type, notify_field).
602  **************************************************************************/
603
604 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
605                                       uint16_t notify_field)
606 {
607         return true;
608 }
609
610 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
611                                 uint16_t notify_field)
612 {
613         struct spoolss_NotifyOption *option = p->notify.option;
614         uint32_t i, j;
615
616         /*
617          * Flags should always be zero when the change notify
618          * is registered by the client's spooler.  A user Win32 app
619          * might use the flags though instead of the NOTIFY_OPTION_INFO
620          * --jerry
621          */
622
623         if (!option) {
624                 return false;
625         }
626
627         if (p->notify.flags)
628                 return is_monitoring_event_flags(
629                         p->notify.flags, notify_type, notify_field);
630
631         for (i = 0; i < option->count; i++) {
632
633                 /* Check match for notify_type */
634
635                 if (option->types[i].type != notify_type)
636                         continue;
637
638                 /* Check match for field */
639
640                 for (j = 0; j < option->types[i].count; j++) {
641                         if (option->types[i].fields[j].field == notify_field) {
642                                 return true;
643                         }
644                 }
645         }
646
647         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
648                    p->servername, p->sharename, notify_type, notify_field));
649
650         return false;
651 }
652
653 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
654         _data->data.integer[0] = _integer; \
655         _data->data.integer[1] = 0;
656
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
659         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
660         if (!_data->data.string.string) {\
661                 _data->data.string.size = 0; \
662         } \
663         _data->data.string.size = strlen_m_term(_p) * 2;
664
665 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
666         _data->data.devmode.devmode = _devmode;
667
668 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
669         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
670         if (!_data->data.sd.sd) { \
671                 _data->data.sd.sd_size = 0; \
672         } \
673         _data->data.sd.sd_size = _size;
674
675 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
676                                    struct tm *t,
677                                    const char **pp,
678                                    uint32_t *plen)
679 {
680         struct spoolss_Time st;
681         uint32_t len = 16;
682         char *p;
683
684         if (!init_systemtime(&st, t)) {
685                 return;
686         }
687
688         p = talloc_array(mem_ctx, char, len);
689         if (!p) {
690                 return;
691         }
692
693         /*
694          * Systemtime must be linearized as a set of UINT16's.
695          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
696          */
697
698         SSVAL(p, 0, st.year);
699         SSVAL(p, 2, st.month);
700         SSVAL(p, 4, st.day_of_week);
701         SSVAL(p, 6, st.day);
702         SSVAL(p, 8, st.hour);
703         SSVAL(p, 10, st.minute);
704         SSVAL(p, 12, st.second);
705         SSVAL(p, 14, st.millisecond);
706
707         *pp = p;
708         *plen = len;
709 }
710
711 /* Convert a notification message to a struct spoolss_Notify */
712
713 static void notify_one_value(struct spoolss_notify_msg *msg,
714                              struct spoolss_Notify *data,
715                              TALLOC_CTX *mem_ctx)
716 {
717         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
718 }
719
720 static void notify_string(struct spoolss_notify_msg *msg,
721                           struct spoolss_Notify *data,
722                           TALLOC_CTX *mem_ctx)
723 {
724         /* The length of the message includes the trailing \0 */
725
726         data->data.string.size = msg->len * 2;
727         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
728         if (!data->data.string.string) {
729                 data->data.string.size = 0;
730                 return;
731         }
732 }
733
734 static void notify_system_time(struct spoolss_notify_msg *msg,
735                                struct spoolss_Notify *data,
736                                TALLOC_CTX *mem_ctx)
737 {
738         data->data.string.string = NULL;
739         data->data.string.size = 0;
740
741         if (msg->len != sizeof(time_t)) {
742                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
743                           msg->len));
744                 return;
745         }
746
747         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
748                                &data->data.string.string,
749                                &data->data.string.size);
750 }
751
752 struct notify2_message_table {
753         const char *name;
754         void (*fn)(struct spoolss_notify_msg *msg,
755                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
756 };
757
758 static struct notify2_message_table printer_notify_table[] = {
759         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
760         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
761         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
762         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
763         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
764         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
765         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
766         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
767         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
768         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
769         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
770         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
771         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
772         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
773         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
774         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
775         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
776         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
777         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
778 };
779
780 static struct notify2_message_table job_notify_table[] = {
781         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
782         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
783         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
784         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
785         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
786         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
787         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
788         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
789         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
790         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
791         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
792         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
793         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
794         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
795         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
796         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
797         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
798         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
799         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
800         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
801         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
802         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
803         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
804         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
805 };
806
807
808 /***********************************************************************
809  Allocate talloc context for container object
810  **********************************************************************/
811
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 {
814         if ( !ctr )
815                 return;
816
817         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
818
819         return;
820 }
821
822 /***********************************************************************
823  release all allocated memory and zero out structure
824  **********************************************************************/
825
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
827 {
828         if ( !ctr )
829                 return;
830
831         if ( ctr->ctx )
832                 talloc_destroy(ctr->ctx);
833
834         ZERO_STRUCTP(ctr);
835
836         return;
837 }
838
839 /***********************************************************************
840  **********************************************************************/
841
842 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
843 {
844         if ( !ctr )
845                 return NULL;
846
847         return ctr->ctx;
848 }
849
850 /***********************************************************************
851  **********************************************************************/
852
853 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
854 {
855         if ( !ctr || !ctr->msg_groups )
856                 return NULL;
857
858         if ( idx >= ctr->num_groups )
859                 return NULL;
860
861         return &ctr->msg_groups[idx];
862
863 }
864
865 /***********************************************************************
866  How many groups of change messages do we have ?
867  **********************************************************************/
868
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
870 {
871         if ( !ctr )
872                 return 0;
873
874         return ctr->num_groups;
875 }
876
877 /***********************************************************************
878  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879  **********************************************************************/
880
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
882 {
883         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
884         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
885         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
886         int                             i, new_slot;
887
888         if ( !ctr || !msg )
889                 return 0;
890
891         /* loop over all groups looking for a matching printer name */
892
893         for ( i=0; i<ctr->num_groups; i++ ) {
894                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895                         break;
896         }
897
898         /* add a new group? */
899
900         if ( i == ctr->num_groups ) {
901                 ctr->num_groups++;
902
903                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
904                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
905                         return 0;
906                 }
907                 ctr->msg_groups = groups;
908
909                 /* clear the new entry and set the printer name */
910
911                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
912                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913         }
914
915         /* add the change messages; 'i' is the correct index now regardless */
916
917         msg_grp = &ctr->msg_groups[i];
918
919         msg_grp->num_msgs++;
920
921         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
922                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
923                 return 0;
924         }
925         msg_grp->msgs = msg_list;
926
927         new_slot = msg_grp->num_msgs-1;
928         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
929
930         /* need to allocate own copy of data */
931
932         if ( msg->len != 0 )
933                 msg_grp->msgs[new_slot].notify.data = (char *)
934                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
935
936         return ctr->num_groups;
937 }
938
939 void construct_info_data(struct spoolss_Notify *info_data,
940                          enum spoolss_NotifyType type,
941                          uint16_t field,
942                          int id);
943
944 /***********************************************************************
945  Send a change notication message on all handles which have a call
946  back registered
947  **********************************************************************/
948
949 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
950 {
951         Printer_entry            *p;
952         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
953         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
954         SPOOLSS_NOTIFY_MSG       *messages;
955         int                      sending_msg_count;
956
957         if ( !msg_group ) {
958                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
959                 return;
960         }
961
962         messages = msg_group->msgs;
963
964         if ( !messages ) {
965                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
966                 return;
967         }
968
969         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
970
971         /* loop over all printers */
972
973         for (p = printers_list; p; p = p->next) {
974                 struct spoolss_Notify *notifies;
975                 uint32_t count = 0;
976                 uint32_t id;
977                 int     i;
978
979                 /* Is there notification on this handle? */
980
981                 if ( !p->notify.client_connected )
982                         continue;
983
984                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
985
986                 /* For this printer?  Print servers always receive
987                    notifications. */
988
989                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
990                     ( !strequal(msg_group->printername, p->sharename) ) )
991                         continue;
992
993                 DEBUG(10,("Our printer\n"));
994
995                 /* allocate the max entries possible */
996
997                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
998                 if (!notifies) {
999                         return;
1000                 }
1001
1002                 /* build the array of change notifications */
1003
1004                 sending_msg_count = 0;
1005
1006                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1007                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1008
1009                         /* Are we monitoring this event? */
1010
1011                         if (!is_monitoring_event(p, msg->type, msg->field))
1012                                 continue;
1013
1014                         sending_msg_count++;
1015
1016
1017                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1018                                 msg->type, msg->field, p->sharename));
1019
1020                         /*
1021                          * if the is a printer notification handle and not a job notification
1022                          * type, then set the id to 0.  Other wise just use what was specified
1023                          * in the message.
1024                          *
1025                          * When registering change notification on a print server handle
1026                          * we always need to send back the id (snum) matching the printer
1027                          * for which the change took place.  For change notify registered
1028                          * on a printer handle, this does not matter and the id should be 0.
1029                          *
1030                          * --jerry
1031                          */
1032
1033                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1034                                 id = 0;
1035                         else
1036                                 id = msg->id;
1037
1038
1039                         /* Convert unix jobid to smb jobid */
1040
1041                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1042                                 id = sysjob_to_jobid(msg->id);
1043
1044                                 if (id == -1) {
1045                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1046                                         goto done;
1047                                 }
1048                         }
1049
1050                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1051
1052                         switch(msg->type) {
1053                         case PRINTER_NOTIFY_TYPE:
1054                                 if ( printer_notify_table[msg->field].fn )
1055                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1056                                 break;
1057
1058                         case JOB_NOTIFY_TYPE:
1059                                 if ( job_notify_table[msg->field].fn )
1060                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1061                                 break;
1062
1063                         default:
1064                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1065                                 goto done;
1066                         }
1067
1068                         count++;
1069                 }
1070
1071                 if ( sending_msg_count ) {
1072                         NTSTATUS status;
1073                         WERROR werr;
1074                         union spoolss_ReplyPrinterInfo info;
1075                         struct spoolss_NotifyInfo info0;
1076                         uint32_t reply_result;
1077
1078                         info0.version   = 0x2;
1079                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1080                         info0.count     = count;
1081                         info0.notifies  = notifies;
1082
1083                         info.info0 = &info0;
1084
1085                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1086                                                                      &p->notify.client_hnd,
1087                                                                      p->notify.change, /* color */
1088                                                                      p->notify.flags,
1089                                                                      &reply_result,
1090                                                                      0, /* reply_type, must be 0 */
1091                                                                      info,
1092                                                                      &werr);
1093                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1094                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1095                                         notify_cli_pipe->srv_name_slash,
1096                                         win_errstr(werr)));
1097                         }
1098                         switch (reply_result) {
1099                                 case 0:
1100                                         break;
1101                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1102                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1103                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1104                                         break;
1105                                 default:
1106                                         break;
1107                         }
1108                 }
1109         }
1110
1111 done:
1112         DEBUG(8,("send_notify2_changes: Exit...\n"));
1113         return;
1114 }
1115
1116 /***********************************************************************
1117  **********************************************************************/
1118
1119 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1120 {
1121
1122         uint32_t tv_sec, tv_usec;
1123         size_t offset = 0;
1124
1125         /* Unpack message */
1126
1127         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1128                              msg->printer);
1129
1130         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1131                                 &tv_sec, &tv_usec,
1132                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1133
1134         if (msg->len == 0)
1135                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1136                            &msg->notify.value[0], &msg->notify.value[1]);
1137         else
1138                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1139                            &msg->len, &msg->notify.data);
1140
1141         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1142                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1143
1144         tv->tv_sec = tv_sec;
1145         tv->tv_usec = tv_usec;
1146
1147         if (msg->len == 0)
1148                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1149                           msg->notify.value[1]));
1150         else
1151                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1152
1153         return true;
1154 }
1155
1156 /********************************************************************
1157  Receive a notify2 message list
1158  ********************************************************************/
1159
1160 static void receive_notify2_message_list(struct messaging_context *msg,
1161                                          void *private_data,
1162                                          uint32_t msg_type,
1163                                          struct server_id server_id,
1164                                          DATA_BLOB *data)
1165 {
1166         size_t                  msg_count, i;
1167         char                    *buf = (char *)data->data;
1168         char                    *msg_ptr;
1169         size_t                  msg_len;
1170         SPOOLSS_NOTIFY_MSG      notify;
1171         SPOOLSS_NOTIFY_MSG_CTR  messages;
1172         int                     num_groups;
1173
1174         if (data->length < 4) {
1175                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1176                 return;
1177         }
1178
1179         msg_count = IVAL(buf, 0);
1180         msg_ptr = buf + 4;
1181
1182         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1183
1184         if (msg_count == 0) {
1185                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1186                 return;
1187         }
1188
1189         /* initialize the container */
1190
1191         ZERO_STRUCT( messages );
1192         notify_msg_ctr_init( &messages );
1193
1194         /*
1195          * build message groups for each printer identified
1196          * in a change_notify msg.  Remember that a PCN message
1197          * includes the handle returned for the srv_spoolss_replyopenprinter()
1198          * call.  Therefore messages are grouped according to printer handle.
1199          */
1200
1201         for ( i=0; i<msg_count; i++ ) {
1202                 struct timeval msg_tv;
1203
1204                 if (msg_ptr + 4 - buf > data->length) {
1205                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1206                         return;
1207                 }
1208
1209                 msg_len = IVAL(msg_ptr,0);
1210                 msg_ptr += 4;
1211
1212                 if (msg_ptr + msg_len - buf > data->length) {
1213                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1214                         return;
1215                 }
1216
1217                 /* unpack messages */
1218
1219                 ZERO_STRUCT( notify );
1220                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1221                 msg_ptr += msg_len;
1222
1223                 /* add to correct list in container */
1224
1225                 notify_msg_ctr_addmsg( &messages, &notify );
1226
1227                 /* free memory that might have been allocated by notify2_unpack_msg() */
1228
1229                 if ( notify.len != 0 )
1230                         SAFE_FREE( notify.notify.data );
1231         }
1232
1233         /* process each group of messages */
1234
1235         num_groups = notify_msg_ctr_numgroups( &messages );
1236         for ( i=0; i<num_groups; i++ )
1237                 send_notify2_changes( &messages, i );
1238
1239
1240         /* cleanup */
1241
1242         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1243                 (uint32_t)msg_count ));
1244
1245         notify_msg_ctr_destroy( &messages );
1246
1247         return;
1248 }
1249
1250 /********************************************************************
1251  Send a message to ourself about new driver being installed
1252  so we can upgrade the information for each printer bound to this
1253  driver
1254  ********************************************************************/
1255
1256 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1257 {
1258         int len = strlen(drivername);
1259
1260         if (!len)
1261                 return false;
1262
1263         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1264                 drivername));
1265
1266         messaging_send_buf(smbd_messaging_context(), procid_self(),
1267                            MSG_PRINTER_DRVUPGRADE,
1268                            (uint8_t *)drivername, len+1);
1269
1270         return true;
1271 }
1272
1273 /**********************************************************************
1274  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1275  over all printers, upgrading ones as necessary
1276  **********************************************************************/
1277
1278 void do_drv_upgrade_printer(struct messaging_context *msg,
1279                             void *private_data,
1280                             uint32_t msg_type,
1281                             struct server_id server_id,
1282                             DATA_BLOB *data)
1283 {
1284         fstring drivername;
1285         int snum;
1286         int n_services = lp_numservices();
1287         size_t len;
1288
1289         len = MIN(data->length,sizeof(drivername)-1);
1290         strncpy(drivername, (const char *)data->data, len);
1291
1292         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1293
1294         /* Iterate the printer list */
1295
1296         for (snum=0; snum<n_services; snum++)
1297         {
1298                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1299                 {
1300                         WERROR result;
1301                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1302
1303                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1304                         if (!W_ERROR_IS_OK(result))
1305                                 continue;
1306
1307                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1308                         {
1309                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1310
1311                                 /* all we care about currently is the change_id */
1312
1313                                 result = mod_a_printer(printer, 2);
1314                                 if (!W_ERROR_IS_OK(result)) {
1315                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1316                                                 win_errstr(result)));
1317                                 }
1318                         }
1319
1320                         free_a_printer(&printer, 2);
1321                 }
1322         }
1323
1324         /* all done */
1325 }
1326
1327 /********************************************************************
1328  Update the cache for all printq's with a registered client
1329  connection
1330  ********************************************************************/
1331
1332 void update_monitored_printq_cache( void )
1333 {
1334         Printer_entry *printer = printers_list;
1335         int snum;
1336
1337         /* loop through all printers and update the cache where
1338            client_connected == true */
1339         while ( printer )
1340         {
1341                 if ( (printer->printer_type == SPLHND_PRINTER)
1342                         && printer->notify.client_connected )
1343                 {
1344                         snum = print_queue_snum(printer->sharename);
1345                         print_queue_status( snum, NULL, NULL );
1346                 }
1347
1348                 printer = printer->next;
1349         }
1350
1351         return;
1352 }
1353 /********************************************************************
1354  Send a message to ourself about new driver being installed
1355  so we can upgrade the information for each printer bound to this
1356  driver
1357  ********************************************************************/
1358
1359 static bool srv_spoolss_reset_printerdata(char* drivername)
1360 {
1361         int len = strlen(drivername);
1362
1363         if (!len)
1364                 return false;
1365
1366         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1367                 drivername));
1368
1369         messaging_send_buf(smbd_messaging_context(), procid_self(),
1370                            MSG_PRINTERDATA_INIT_RESET,
1371                            (uint8_t *)drivername, len+1);
1372
1373         return true;
1374 }
1375
1376 /**********************************************************************
1377  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1378  over all printers, resetting printer data as neessary
1379  **********************************************************************/
1380
1381 void reset_all_printerdata(struct messaging_context *msg,
1382                            void *private_data,
1383                            uint32_t msg_type,
1384                            struct server_id server_id,
1385                            DATA_BLOB *data)
1386 {
1387         fstring drivername;
1388         int snum;
1389         int n_services = lp_numservices();
1390         size_t len;
1391
1392         len = MIN( data->length, sizeof(drivername)-1 );
1393         strncpy( drivername, (const char *)data->data, len );
1394
1395         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1396
1397         /* Iterate the printer list */
1398
1399         for ( snum=0; snum<n_services; snum++ )
1400         {
1401                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1402                 {
1403                         WERROR result;
1404                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1405
1406                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1407                         if ( !W_ERROR_IS_OK(result) )
1408                                 continue;
1409
1410                         /*
1411                          * if the printer is bound to the driver,
1412                          * then reset to the new driver initdata
1413                          */
1414
1415                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1416                         {
1417                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1418
1419                                 if ( !set_driver_init(printer, 2) ) {
1420                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1421                                                 printer->info_2->printername, printer->info_2->drivername));
1422                                 }
1423
1424                                 result = mod_a_printer( printer, 2 );
1425                                 if ( !W_ERROR_IS_OK(result) ) {
1426                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1427                                                 get_dos_error_msg(result)));
1428                                 }
1429                         }
1430
1431                         free_a_printer( &printer, 2 );
1432                 }
1433         }
1434
1435         /* all done */
1436
1437         return;
1438 }
1439
1440 /****************************************************************
1441  _spoolss_OpenPrinter
1442 ****************************************************************/
1443
1444 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1445                             struct spoolss_OpenPrinter *r)
1446 {
1447         struct spoolss_OpenPrinterEx e;
1448         WERROR werr;
1449
1450         ZERO_STRUCT(e.in.userlevel);
1451
1452         e.in.printername        = r->in.printername;
1453         e.in.datatype           = r->in.datatype;
1454         e.in.devmode_ctr        = r->in.devmode_ctr;
1455         e.in.access_mask        = r->in.access_mask;
1456         e.in.level              = 0;
1457
1458         e.out.handle            = r->out.handle;
1459
1460         werr = _spoolss_OpenPrinterEx(p, &e);
1461
1462         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1463                 /* OpenPrinterEx returns this for a bad
1464                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1465                  * instead.
1466                  */
1467                 werr = WERR_INVALID_PRINTER_NAME;
1468         }
1469
1470         return werr;
1471 }
1472
1473 /********************************************************************
1474  ********************************************************************/
1475
1476 bool convert_devicemode(const char *printername,
1477                         const struct spoolss_DeviceMode *devmode,
1478                         NT_DEVICEMODE **pp_nt_devmode)
1479 {
1480         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1481
1482         /*
1483          * Ensure nt_devmode is a valid pointer
1484          * as we will be overwriting it.
1485          */
1486
1487         if (nt_devmode == NULL) {
1488                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1489                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1490                         return false;
1491         }
1492
1493         fstrcpy(nt_devmode->devicename, devmode->devicename);
1494         fstrcpy(nt_devmode->formname, devmode->formname);
1495
1496         nt_devmode->devicename[31] = '\0';
1497         nt_devmode->formname[31] = '\0';
1498
1499         nt_devmode->specversion         = devmode->specversion;
1500         nt_devmode->driverversion       = devmode->driverversion;
1501         nt_devmode->size                = devmode->size;
1502         nt_devmode->fields              = devmode->fields;
1503         nt_devmode->orientation         = devmode->orientation;
1504         nt_devmode->papersize           = devmode->papersize;
1505         nt_devmode->paperlength         = devmode->paperlength;
1506         nt_devmode->paperwidth          = devmode->paperwidth;
1507         nt_devmode->scale               = devmode->scale;
1508         nt_devmode->copies              = devmode->copies;
1509         nt_devmode->defaultsource       = devmode->defaultsource;
1510         nt_devmode->printquality        = devmode->printquality;
1511         nt_devmode->color               = devmode->color;
1512         nt_devmode->duplex              = devmode->duplex;
1513         nt_devmode->yresolution         = devmode->yresolution;
1514         nt_devmode->ttoption            = devmode->ttoption;
1515         nt_devmode->collate             = devmode->collate;
1516
1517         nt_devmode->logpixels           = devmode->logpixels;
1518         nt_devmode->bitsperpel          = devmode->bitsperpel;
1519         nt_devmode->pelswidth           = devmode->pelswidth;
1520         nt_devmode->pelsheight          = devmode->pelsheight;
1521         nt_devmode->displayflags        = devmode->displayflags;
1522         nt_devmode->displayfrequency    = devmode->displayfrequency;
1523         nt_devmode->icmmethod           = devmode->icmmethod;
1524         nt_devmode->icmintent           = devmode->icmintent;
1525         nt_devmode->mediatype           = devmode->mediatype;
1526         nt_devmode->dithertype          = devmode->dithertype;
1527         nt_devmode->reserved1           = devmode->reserved1;
1528         nt_devmode->reserved2           = devmode->reserved2;
1529         nt_devmode->panningwidth        = devmode->panningwidth;
1530         nt_devmode->panningheight       = devmode->panningheight;
1531
1532         /*
1533          * Only change private and driverextra if the incoming devmode
1534          * has a new one. JRA.
1535          */
1536
1537         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1538                 SAFE_FREE(nt_devmode->nt_dev_private);
1539                 nt_devmode->driverextra = devmode->__driverextra_length;
1540                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1541                         return false;
1542                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1543         }
1544
1545         *pp_nt_devmode = nt_devmode;
1546
1547         return true;
1548 }
1549
1550 /****************************************************************
1551  _spoolss_OpenPrinterEx
1552 ****************************************************************/
1553
1554 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1555                               struct spoolss_OpenPrinterEx *r)
1556 {
1557         int snum;
1558         Printer_entry *Printer=NULL;
1559
1560         if (!r->in.printername) {
1561                 return WERR_INVALID_PARAM;
1562         }
1563
1564         /* some sanity check because you can open a printer or a print server */
1565         /* aka: \\server\printer or \\server */
1566
1567         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1568
1569         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1570                 ZERO_STRUCTP(r->out.handle);
1571                 return WERR_INVALID_PARAM;
1572         }
1573
1574         Printer = find_printer_index_by_hnd(p, r->out.handle);
1575         if ( !Printer ) {
1576                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1577                         "handle we created for printer %s\n", r->in.printername));
1578                 close_printer_handle(p, r->out.handle);
1579                 ZERO_STRUCTP(r->out.handle);
1580                 return WERR_INVALID_PARAM;
1581         }
1582
1583         /*
1584          * First case: the user is opening the print server:
1585          *
1586          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1587          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1588          *
1589          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1590          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1591          * or if the user is listed in the smb.conf printer admin parameter.
1592          *
1593          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1594          * client view printer folder, but does not show the MSAPW.
1595          *
1596          * Note: this test needs code to check access rights here too. Jeremy
1597          * could you look at this?
1598          *
1599          * Second case: the user is opening a printer:
1600          * NT doesn't let us connect to a printer if the connecting user
1601          * doesn't have print permission.
1602          *
1603          * Third case: user is opening a Port Monitor
1604          * access checks same as opening a handle to the print server.
1605          */
1606
1607         switch (Printer->printer_type )
1608         {
1609         case SPLHND_SERVER:
1610         case SPLHND_PORTMON_TCP:
1611         case SPLHND_PORTMON_LOCAL:
1612                 /* Printserver handles use global struct... */
1613
1614                 snum = -1;
1615
1616                 /* Map standard access rights to object specific access rights */
1617
1618                 se_map_standard(&r->in.access_mask,
1619                                 &printserver_std_mapping);
1620
1621                 /* Deny any object specific bits that don't apply to print
1622                    servers (i.e printer and job specific bits) */
1623
1624                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1625
1626                 if (r->in.access_mask &
1627                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1628                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1629                         close_printer_handle(p, r->out.handle);
1630                         ZERO_STRUCTP(r->out.handle);
1631                         return WERR_ACCESS_DENIED;
1632                 }
1633
1634                 /* Allow admin access */
1635
1636                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1637                 {
1638                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1639
1640                         if (!lp_ms_add_printer_wizard()) {
1641                                 close_printer_handle(p, r->out.handle);
1642                                 ZERO_STRUCTP(r->out.handle);
1643                                 return WERR_ACCESS_DENIED;
1644                         }
1645
1646                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1647                            and not a printer admin, then fail */
1648
1649                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1650                             !user_has_privileges(p->server_info->ptok,
1651                                                  &se_printop ) &&
1652                             !token_contains_name_in_list(
1653                                     uidtoname(p->server_info->utok.uid),
1654                                     NULL, NULL,
1655                                     p->server_info->ptok,
1656                                     lp_printer_admin(snum))) {
1657                                 close_printer_handle(p, r->out.handle);
1658                                 ZERO_STRUCTP(r->out.handle);
1659                                 return WERR_ACCESS_DENIED;
1660                         }
1661
1662                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1663                 }
1664                 else
1665                 {
1666                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1667                 }
1668
1669                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1670                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1671
1672                 /* We fall through to return WERR_OK */
1673                 break;
1674
1675         case SPLHND_PRINTER:
1676                 /* NT doesn't let us connect to a printer if the connecting user
1677                    doesn't have print permission.  */
1678
1679                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1680                         close_printer_handle(p, r->out.handle);
1681                         ZERO_STRUCTP(r->out.handle);
1682                         return WERR_BADFID;
1683                 }
1684
1685                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1686                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1687                 }
1688
1689                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1690
1691                 /* map an empty access mask to the minimum access mask */
1692                 if (r->in.access_mask == 0x0)
1693                         r->in.access_mask = PRINTER_ACCESS_USE;
1694
1695                 /*
1696                  * If we are not serving the printer driver for this printer,
1697                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1698                  * will keep NT clients happy  --jerry
1699                  */
1700
1701                 if (lp_use_client_driver(snum)
1702                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1703                 {
1704                         r->in.access_mask = PRINTER_ACCESS_USE;
1705                 }
1706
1707                 /* check smb.conf parameters and the the sec_desc */
1708
1709                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1710                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1711                         ZERO_STRUCTP(r->out.handle);
1712                         return WERR_ACCESS_DENIED;
1713                 }
1714
1715                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1716                                    p->server_info->ptok, snum) ||
1717                     !print_access_check(p->server_info, snum,
1718                                         r->in.access_mask)) {
1719                         DEBUG(3, ("access DENIED for printer open\n"));
1720                         close_printer_handle(p, r->out.handle);
1721                         ZERO_STRUCTP(r->out.handle);
1722                         return WERR_ACCESS_DENIED;
1723                 }
1724
1725                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1726                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1727                         close_printer_handle(p, r->out.handle);
1728                         ZERO_STRUCTP(r->out.handle);
1729                         return WERR_ACCESS_DENIED;
1730                 }
1731
1732                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1733                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1734                 else
1735                         r->in.access_mask = PRINTER_ACCESS_USE;
1736
1737                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1738                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1739
1740                 break;
1741
1742         default:
1743                 /* sanity check to prevent programmer error */
1744                 ZERO_STRUCTP(r->out.handle);
1745                 return WERR_BADFID;
1746         }
1747
1748         Printer->access_granted = r->in.access_mask;
1749
1750         /*
1751          * If the client sent a devmode in the OpenPrinter() call, then
1752          * save it here in case we get a job submission on this handle
1753          */
1754
1755          if ((Printer->printer_type != SPLHND_SERVER) &&
1756              r->in.devmode_ctr.devmode) {
1757                 convert_devicemode(Printer->sharename,
1758                                    r->in.devmode_ctr.devmode,
1759                                    &Printer->nt_devmode);
1760          }
1761
1762 #if 0   /* JERRY -- I'm doubtful this is really effective */
1763         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1764            optimization in Windows 2000 clients  --jerry */
1765
1766         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1767                 && (RA_WIN2K == get_remote_arch()) )
1768         {
1769                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1770                 sys_usleep( 500000 );
1771         }
1772 #endif
1773
1774         return WERR_OK;
1775 }
1776
1777 /****************************************************************************
1778 ****************************************************************************/
1779
1780 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1781                                               NT_PRINTER_INFO_LEVEL_2 *d)
1782 {
1783         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1784
1785         if (!r || !d) {
1786                 return false;
1787         }
1788
1789         d->attributes           = r->attributes;
1790         d->priority             = r->priority;
1791         d->default_priority     = r->defaultpriority;
1792         d->starttime            = r->starttime;
1793         d->untiltime            = r->untiltime;
1794         d->status               = r->status;
1795         d->cjobs                = r->cjobs;
1796
1797         fstrcpy(d->servername,  r->servername);
1798         fstrcpy(d->printername, r->printername);
1799         fstrcpy(d->sharename,   r->sharename);
1800         fstrcpy(d->portname,    r->portname);
1801         fstrcpy(d->drivername,  r->drivername);
1802         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1803         fstrcpy(d->location,    r->location);
1804         fstrcpy(d->sepfile,     r->sepfile);
1805         fstrcpy(d->printprocessor, r->printprocessor);
1806         fstrcpy(d->datatype,    r->datatype);
1807         fstrcpy(d->parameters,  r->parameters);
1808
1809         return true;
1810 }
1811
1812 /****************************************************************************
1813 ****************************************************************************/
1814
1815 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1816                                  NT_PRINTER_INFO_LEVEL *printer)
1817 {
1818         bool ret;
1819
1820         switch (info_ctr->level) {
1821         case 2:
1822                 /* allocate memory if needed.  Messy because
1823                    convert_printer_info is used to update an existing
1824                    printer or build a new one */
1825
1826                 if (!printer->info_2) {
1827                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1828                         if (!printer->info_2) {
1829                                 DEBUG(0,("convert_printer_info: "
1830                                         "talloc() failed!\n"));
1831                                 return false;
1832                         }
1833                 }
1834
1835                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1836                                                         printer->info_2);
1837                 printer->info_2->setuptime = time(NULL);
1838                 return ret;
1839         }
1840
1841         return false;
1842 }
1843
1844 /****************************************************************
1845  _spoolss_ClosePrinter
1846 ****************************************************************/
1847
1848 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1849                              struct spoolss_ClosePrinter *r)
1850 {
1851         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1852
1853         if (Printer && Printer->document_started) {
1854                 struct spoolss_EndDocPrinter e;
1855
1856                 e.in.handle = r->in.handle;
1857
1858                 _spoolss_EndDocPrinter(p, &e);
1859         }
1860
1861         if (!close_printer_handle(p, r->in.handle))
1862                 return WERR_BADFID;
1863
1864         /* clear the returned printer handle.  Observed behavior
1865            from Win2k server.  Don't think this really matters.
1866            Previous code just copied the value of the closed
1867            handle.    --jerry */
1868
1869         ZERO_STRUCTP(r->out.handle);
1870
1871         return WERR_OK;
1872 }
1873
1874 /****************************************************************
1875  _spoolss_DeletePrinter
1876 ****************************************************************/
1877
1878 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1879                               struct spoolss_DeletePrinter *r)
1880 {
1881         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1882         WERROR result;
1883
1884         if (Printer && Printer->document_started) {
1885                 struct spoolss_EndDocPrinter e;
1886
1887                 e.in.handle = r->in.handle;
1888
1889                 _spoolss_EndDocPrinter(p, &e);
1890         }
1891
1892         result = delete_printer_handle(p, r->in.handle);
1893
1894         update_c_setprinter(false);
1895
1896         return result;
1897 }
1898
1899 /*******************************************************************
1900  * static function to lookup the version id corresponding to an
1901  * long architecture string
1902  ******************************************************************/
1903
1904 static const struct print_architecture_table_node archi_table[]= {
1905
1906         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1907         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1908         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1909         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1910         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1911         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1912         {"Windows x64",          SPL_ARCH_X64,          3 },
1913         {NULL,                   "",            -1 }
1914 };
1915
1916 static int get_version_id(const char *arch)
1917 {
1918         int i;
1919
1920         for (i=0; archi_table[i].long_archi != NULL; i++)
1921         {
1922                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1923                         return (archi_table[i].version);
1924         }
1925
1926         return -1;
1927 }
1928
1929 /****************************************************************
1930  _spoolss_DeletePrinterDriver
1931 ****************************************************************/
1932
1933 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1934                                     struct spoolss_DeletePrinterDriver *r)
1935 {
1936
1937         struct spoolss_DriverInfo8 *info = NULL;
1938         struct spoolss_DriverInfo8 *info_win2k = NULL;
1939         int                             version;
1940         WERROR                          status;
1941         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1942         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1943
1944         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1945            and not a printer admin, then fail */
1946
1947         if ( (p->server_info->utok.uid != sec_initial_uid())
1948                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1949                 && !token_contains_name_in_list(
1950                         uidtoname(p->server_info->utok.uid), NULL,
1951                         NULL, p->server_info->ptok,
1952                         lp_printer_admin(-1)) )
1953         {
1954                 return WERR_ACCESS_DENIED;
1955         }
1956
1957         /* check that we have a valid driver name first */
1958
1959         if ((version = get_version_id(r->in.architecture)) == -1)
1960                 return WERR_INVALID_ENVIRONMENT;
1961
1962         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1963                                                 r->in.architecture,
1964                                                 version)))
1965         {
1966                 /* try for Win2k driver if "Windows NT x86" */
1967
1968                 if ( version == 2 ) {
1969                         version = 3;
1970                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1971                                                                 &info,
1972                                                                 r->in.driver,
1973                                                                 r->in.architecture,
1974                                                                 version))) {
1975                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1976                                 goto done;
1977                         }
1978                 }
1979                 /* otherwise it was a failure */
1980                 else {
1981                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1982                         goto done;
1983                 }
1984
1985         }
1986
1987         if (printer_driver_in_use(info)) {
1988                 status = WERR_PRINTER_DRIVER_IN_USE;
1989                 goto done;
1990         }
1991
1992         if ( version == 2 )
1993         {
1994                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1995                                                        &info_win2k,
1996                                                        r->in.driver,
1997                                                        r->in.architecture, 3)))
1998                 {
1999                         /* if we get to here, we now have 2 driver info structures to remove */
2000                         /* remove the Win2k driver first*/
2001
2002                         status_win2k = delete_printer_driver(
2003                                 p, info_win2k, 3, false);
2004                         free_a_printer_driver(info_win2k);
2005
2006                         /* this should not have failed---if it did, report to client */
2007                         if ( !W_ERROR_IS_OK(status_win2k) )
2008                         {
2009                                 status = status_win2k;
2010                                 goto done;
2011                         }
2012                 }
2013         }
2014
2015         status = delete_printer_driver(p, info, version, false);
2016
2017         /* if at least one of the deletes succeeded return OK */
2018
2019         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2020                 status = WERR_OK;
2021
2022 done:
2023         free_a_printer_driver(info);
2024
2025         return status;
2026 }
2027
2028 /****************************************************************
2029  _spoolss_DeletePrinterDriverEx
2030 ****************************************************************/
2031
2032 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2033                                       struct spoolss_DeletePrinterDriverEx *r)
2034 {
2035         struct spoolss_DriverInfo8      *info = NULL;
2036         struct spoolss_DriverInfo8      *info_win2k = NULL;
2037         int                             version;
2038         bool                            delete_files;
2039         WERROR                          status;
2040         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2041         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2042
2043         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2044            and not a printer admin, then fail */
2045
2046         if ( (p->server_info->utok.uid != sec_initial_uid())
2047                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2048                 && !token_contains_name_in_list(
2049                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2050                         p->server_info->ptok, lp_printer_admin(-1)) )
2051         {
2052                 return WERR_ACCESS_DENIED;
2053         }
2054
2055         /* check that we have a valid driver name first */
2056         if ((version = get_version_id(r->in.architecture)) == -1) {
2057                 /* this is what NT returns */
2058                 return WERR_INVALID_ENVIRONMENT;
2059         }
2060
2061         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2062                 version = r->in.version;
2063
2064         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2065                                       r->in.architecture, version);
2066
2067         if ( !W_ERROR_IS_OK(status) )
2068         {
2069                 /*
2070                  * if the client asked for a specific version,
2071                  * or this is something other than Windows NT x86,
2072                  * then we've failed
2073                  */
2074
2075                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2076                         goto done;
2077
2078                 /* try for Win2k driver if "Windows NT x86" */
2079
2080                 version = 3;
2081                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2082                                                         r->in.architecture,
2083                                                         version))) {
2084                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2085                         goto done;
2086                 }
2087         }
2088
2089         if (printer_driver_in_use(info)) {
2090                 status = WERR_PRINTER_DRIVER_IN_USE;
2091                 goto done;
2092         }
2093
2094         /*
2095          * we have a couple of cases to consider.
2096          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2097          *     then the delete should fail if **any** files overlap with
2098          *     other drivers
2099          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2100          *     non-overlapping files
2101          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2102          *     is set, the do not delete any files
2103          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2104          */
2105
2106         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2107
2108         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2109
2110         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2111                 /* no idea of the correct error here */
2112                 status = WERR_ACCESS_DENIED;
2113                 goto done;
2114         }
2115
2116
2117         /* also check for W32X86/3 if necessary; maybe we already have? */
2118
2119         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2120                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2121                                                        r->in.driver,
2122                                                        r->in.architecture, 3)))
2123                 {
2124
2125                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2126                                 /* no idea of the correct error here */
2127                                 free_a_printer_driver(info_win2k);
2128                                 status = WERR_ACCESS_DENIED;
2129                                 goto done;
2130                         }
2131
2132                         /* if we get to here, we now have 2 driver info structures to remove */
2133                         /* remove the Win2k driver first*/
2134
2135                         status_win2k = delete_printer_driver(
2136                                 p, info_win2k, 3, delete_files);
2137                         free_a_printer_driver(info_win2k);
2138
2139                         /* this should not have failed---if it did, report to client */
2140
2141                         if ( !W_ERROR_IS_OK(status_win2k) )
2142                                 goto done;
2143                 }
2144         }
2145
2146         status = delete_printer_driver(p, info, version, delete_files);
2147
2148         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2149                 status = WERR_OK;
2150 done:
2151         free_a_printer_driver(info);
2152
2153         return status;
2154 }
2155
2156
2157 /****************************************************************************
2158  Internal routine for removing printerdata
2159  ***************************************************************************/
2160
2161 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2162 {
2163         return delete_printer_data( printer->info_2, key, value );
2164 }
2165
2166 /****************************************************************************
2167  Internal routine for storing printerdata
2168  ***************************************************************************/
2169
2170 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2171                           const char *key, const char *value,
2172                           uint32_t type, uint8_t *data, int real_len)
2173 {
2174         /* the registry objects enforce uniqueness based on value name */
2175
2176         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2177 }
2178
2179 /********************************************************************
2180  GetPrinterData on a printer server Handle.
2181 ********************************************************************/
2182
2183 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2184                                             const char *value,
2185                                             enum winreg_Type *type,
2186                                             union spoolss_PrinterData *data)
2187 {
2188         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2189
2190         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2191                 *type = REG_DWORD;
2192                 data->value = 0x00;
2193                 return WERR_OK;
2194         }
2195
2196         if (!StrCaseCmp(value, "BeepEnabled")) {
2197                 *type = REG_DWORD;
2198                 data->value = 0x00;
2199                 return WERR_OK;
2200         }
2201
2202         if (!StrCaseCmp(value, "EventLog")) {
2203                 *type = REG_DWORD;
2204                 /* formally was 0x1b */
2205                 data->value = 0x00;
2206                 return WERR_OK;
2207         }
2208
2209         if (!StrCaseCmp(value, "NetPopup")) {
2210                 *type = REG_DWORD;
2211                 data->value = 0x00;
2212                 return WERR_OK;
2213         }
2214
2215         if (!StrCaseCmp(value, "MajorVersion")) {
2216                 *type = REG_DWORD;
2217
2218                 /* Windows NT 4.0 seems to not allow uploading of drivers
2219                    to a server that reports 0x3 as the MajorVersion.
2220                    need to investigate more how Win2k gets around this .
2221                    -- jerry */
2222
2223                 if (RA_WINNT == get_remote_arch()) {
2224                         data->value = 0x02;
2225                 } else {
2226                         data->value = 0x03;
2227                 }
2228
2229                 return WERR_OK;
2230         }
2231
2232         if (!StrCaseCmp(value, "MinorVersion")) {
2233                 *type = REG_DWORD;
2234                 data->value = 0x00;
2235                 return WERR_OK;
2236         }
2237
2238         /* REG_BINARY
2239          *  uint32_t size        = 0x114
2240          *  uint32_t major       = 5
2241          *  uint32_t minor       = [0|1]
2242          *  uint32_t build       = [2195|2600]
2243          *  extra unicode string = e.g. "Service Pack 3"
2244          */
2245         if (!StrCaseCmp(value, "OSVersion")) {
2246                 DATA_BLOB blob;
2247                 enum ndr_err_code ndr_err;
2248                 struct spoolss_OSVersion os;
2249
2250                 os.major                = 5;    /* Windows 2000 == 5.0 */
2251                 os.minor                = 0;
2252                 os.build                = 2195; /* build */
2253                 os.extra_string         = "";   /* leave extra string empty */
2254
2255                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2256                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2257                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2258                         return WERR_GENERAL_FAILURE;
2259                 }
2260
2261                 *type = REG_BINARY;
2262                 data->binary = blob;
2263
2264                 return WERR_OK;
2265         }
2266
2267
2268         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2269                 *type = REG_SZ;
2270
2271                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2272                 W_ERROR_HAVE_NO_MEMORY(data->string);
2273
2274                 return WERR_OK;
2275         }
2276
2277         if (!StrCaseCmp(value, "Architecture")) {
2278                 *type = REG_SZ;
2279                 data->string = talloc_strdup(mem_ctx,
2280                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2281                 W_ERROR_HAVE_NO_MEMORY(data->string);
2282
2283                 return WERR_OK;
2284         }
2285
2286         if (!StrCaseCmp(value, "DsPresent")) {
2287                 *type = REG_DWORD;
2288
2289                 /* only show the publish check box if we are a
2290                    member of a AD domain */
2291
2292                 if (lp_security() == SEC_ADS) {
2293                         data->value = 0x01;
2294                 } else {
2295                         data->value = 0x00;
2296                 }
2297                 return WERR_OK;
2298         }
2299
2300         if (!StrCaseCmp(value, "DNSMachineName")) {
2301                 const char *hostname = get_mydnsfullname();
2302
2303                 if (!hostname) {
2304                         return WERR_BADFILE;
2305                 }
2306
2307                 *type = REG_SZ;
2308                 data->string = talloc_strdup(mem_ctx, hostname);
2309                 W_ERROR_HAVE_NO_MEMORY(data->string);
2310
2311                 return WERR_OK;
2312         }
2313
2314         *type = REG_NONE;
2315
2316         return WERR_INVALID_PARAM;
2317 }
2318
2319 /****************************************************************
2320  _spoolss_GetPrinterData
2321 ****************************************************************/
2322
2323 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2324                                struct spoolss_GetPrinterData *r)
2325 {
2326         struct spoolss_GetPrinterDataEx r2;
2327
2328         r2.in.handle            = r->in.handle;
2329         r2.in.key_name          = "PrinterDriverData";
2330         r2.in.value_name        = r->in.value_name;
2331         r2.in.offered           = r->in.offered;
2332         r2.out.type             = r->out.type;
2333         r2.out.data             = r->out.data;
2334         r2.out.needed           = r->out.needed;
2335
2336         return _spoolss_GetPrinterDataEx(p, &r2);
2337 }
2338
2339 /*********************************************************
2340  Connect to the client machine.
2341 **********************************************************/
2342
2343 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2344                         struct sockaddr_storage *client_ss, const char *remote_machine)
2345 {
2346         NTSTATUS ret;
2347         struct cli_state *the_cli;
2348         struct sockaddr_storage rm_addr;
2349         char addr[INET6_ADDRSTRLEN];
2350
2351         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2352                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2353                         remote_machine));
2354                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2355                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2356                         return false;
2357                 }
2358                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2359         } else {
2360                 rm_addr = *client_ss;
2361                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2362                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2363                         addr));
2364         }
2365
2366         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2367                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2368                         addr));
2369                 return false;
2370         }
2371
2372         /* setup the connection */
2373         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2374                 &rm_addr, 0, "IPC$", "IPC",
2375                 "", /* username */
2376                 "", /* domain */
2377                 "", /* password */
2378                 0, lp_client_signing(), NULL );
2379
2380         if ( !NT_STATUS_IS_OK( ret ) ) {
2381                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2382                         remote_machine ));
2383                 return false;
2384         }
2385
2386         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2387                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2388                 cli_shutdown(the_cli);
2389                 return false;
2390         }
2391
2392         /*
2393          * Ok - we have an anonymous connection to the IPC$ share.
2394          * Now start the NT Domain stuff :-).
2395          */
2396
2397         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2398         if (!NT_STATUS_IS_OK(ret)) {
2399                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2400                         remote_machine, nt_errstr(ret)));
2401                 cli_shutdown(the_cli);
2402                 return false;
2403         }
2404
2405         return true;
2406 }
2407
2408 /***************************************************************************
2409  Connect to the client.
2410 ****************************************************************************/
2411
2412 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2413                                         uint32_t localprinter, uint32_t type,
2414                                         struct policy_handle *handle,
2415                                         struct sockaddr_storage *client_ss)
2416 {
2417         WERROR result;
2418         NTSTATUS status;
2419
2420         /*
2421          * If it's the first connection, contact the client
2422          * and connect to the IPC$ share anonymously
2423          */
2424         if (smb_connections==0) {
2425                 fstring unix_printer;
2426
2427                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2428
2429                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2430                         return false;
2431
2432                 messaging_register(smbd_messaging_context(), NULL,
2433                                    MSG_PRINTER_NOTIFY2,
2434                                    receive_notify2_message_list);
2435                 /* Tell the connections db we're now interested in printer
2436                  * notify messages. */
2437                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2438         }
2439
2440         /*
2441          * Tell the specific printing tdb we want messages for this printer
2442          * by registering our PID.
2443          */
2444
2445         if (!print_notify_register_pid(snum))
2446                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2447
2448         smb_connections++;
2449
2450         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2451                                                  printer,
2452                                                  localprinter,
2453                                                  type,
2454                                                  0,
2455                                                  NULL,
2456                                                  handle,
2457                                                  &result);
2458         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2459                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2460                         win_errstr(result)));
2461
2462         return (W_ERROR_IS_OK(result));
2463 }
2464
2465 /****************************************************************
2466  ****************************************************************/
2467
2468 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2469                                                              const struct spoolss_NotifyOption *r)
2470 {
2471         struct spoolss_NotifyOption *option;
2472         uint32_t i,k;
2473
2474         if (!r) {
2475                 return NULL;
2476         }
2477
2478         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2479         if (!option) {
2480                 return NULL;
2481         }
2482
2483         *option = *r;
2484
2485         if (!option->count) {
2486                 return option;
2487         }
2488
2489         option->types = talloc_zero_array(option,
2490                 struct spoolss_NotifyOptionType, option->count);
2491         if (!option->types) {
2492                 talloc_free(option);
2493                 return NULL;
2494         }
2495
2496         for (i=0; i < option->count; i++) {
2497                 option->types[i] = r->types[i];
2498
2499                 if (option->types[i].count) {
2500                         option->types[i].fields = talloc_zero_array(option,
2501                                 union spoolss_Field, option->types[i].count);
2502                         if (!option->types[i].fields) {
2503                                 talloc_free(option);
2504                                 return NULL;
2505                         }
2506                         for (k=0; k<option->types[i].count; k++) {
2507                                 option->types[i].fields[k] =
2508                                         r->types[i].fields[k];
2509                         }
2510                 }
2511         }
2512
2513         return option;
2514 }
2515
2516 /****************************************************************
2517  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2518  *
2519  * before replying OK: status=0 a rpc call is made to the workstation
2520  * asking ReplyOpenPrinter
2521  *
2522  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2523  * called from api_spoolss_rffpcnex
2524 ****************************************************************/
2525
2526 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2527                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2528 {
2529         int snum = -1;
2530         struct spoolss_NotifyOption *option = r->in.notify_options;
2531         struct sockaddr_storage client_ss;
2532
2533         /* store the notify value in the printer struct */
2534
2535         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2536
2537         if (!Printer) {
2538                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2539                         "Invalid handle (%s:%u:%u).\n",
2540                         OUR_HANDLE(r->in.handle)));
2541                 return WERR_BADFID;
2542         }
2543
2544         Printer->notify.flags           = r->in.flags;
2545         Printer->notify.options         = r->in.options;
2546         Printer->notify.printerlocal    = r->in.printer_local;
2547
2548         TALLOC_FREE(Printer->notify.option);
2549         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2550
2551         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2552
2553         /* Connect to the client machine and send a ReplyOpenPrinter */
2554
2555         if ( Printer->printer_type == SPLHND_SERVER)
2556                 snum = -1;
2557         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2558                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2559                 return WERR_BADFID;
2560
2561         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2562                 "client_address is %s\n", p->client_address));
2563
2564         if (!interpret_string_addr(&client_ss, p->client_address,
2565                                    AI_NUMERICHOST)) {
2566                 return WERR_SERVER_UNAVAILABLE;
2567         }
2568
2569         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2570                                         Printer->notify.printerlocal, 1,
2571                                         &Printer->notify.client_hnd, &client_ss))
2572                 return WERR_SERVER_UNAVAILABLE;
2573
2574         Printer->notify.client_connected = true;
2575
2576         return WERR_OK;
2577 }
2578
2579 /*******************************************************************
2580  * fill a notify_info_data with the servername
2581  ********************************************************************/
2582
2583 static void spoolss_notify_server_name(int snum,
2584                                        struct spoolss_Notify *data,
2585                                        print_queue_struct *queue,
2586                                        NT_PRINTER_INFO_LEVEL *printer,
2587                                        TALLOC_CTX *mem_ctx)
2588 {
2589         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2590 }
2591
2592 /*******************************************************************
2593  * fill a notify_info_data with the printername (not including the servername).
2594  ********************************************************************/
2595
2596 static void spoolss_notify_printer_name(int snum,
2597                                         struct spoolss_Notify *data,
2598                                         print_queue_struct *queue,
2599                                         NT_PRINTER_INFO_LEVEL *printer,
2600                                         TALLOC_CTX *mem_ctx)
2601 {
2602         /* the notify name should not contain the \\server\ part */
2603         char *p = strrchr(printer->info_2->printername, '\\');
2604
2605         if (!p) {
2606                 p = printer->info_2->printername;
2607         } else {
2608                 p++;
2609         }
2610
2611         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2612 }
2613
2614 /*******************************************************************
2615  * fill a notify_info_data with the servicename
2616  ********************************************************************/
2617
2618 static void spoolss_notify_share_name(int snum,
2619                                       struct spoolss_Notify *data,
2620                                       print_queue_struct *queue,
2621                                       NT_PRINTER_INFO_LEVEL *printer,
2622                                       TALLOC_CTX *mem_ctx)
2623 {
2624         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2625 }
2626
2627 /*******************************************************************
2628  * fill a notify_info_data with the port name
2629  ********************************************************************/
2630
2631 static void spoolss_notify_port_name(int snum,
2632                                      struct spoolss_Notify *data,
2633                                      print_queue_struct *queue,
2634                                      NT_PRINTER_INFO_LEVEL *printer,
2635                                      TALLOC_CTX *mem_ctx)
2636 {
2637         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2638 }
2639
2640 /*******************************************************************
2641  * fill a notify_info_data with the printername
2642  * but it doesn't exist, have to see what to do
2643  ********************************************************************/
2644
2645 static void spoolss_notify_driver_name(int snum,
2646                                        struct spoolss_Notify *data,
2647                                        print_queue_struct *queue,
2648                                        NT_PRINTER_INFO_LEVEL *printer,
2649                                        TALLOC_CTX *mem_ctx)
2650 {
2651         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2652 }
2653
2654 /*******************************************************************
2655  * fill a notify_info_data with the comment
2656  ********************************************************************/
2657
2658 static void spoolss_notify_comment(int snum,
2659                                    struct spoolss_Notify *data,
2660                                    print_queue_struct *queue,
2661                                    NT_PRINTER_INFO_LEVEL *printer,
2662                                    TALLOC_CTX *mem_ctx)
2663 {
2664         char *p;
2665
2666         if (*printer->info_2->comment == '\0') {
2667                 p = lp_comment(snum);
2668         } else {
2669                 p = printer->info_2->comment;
2670         }
2671
2672         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2673 }
2674
2675 /*******************************************************************
2676  * fill a notify_info_data with the comment
2677  * location = "Room 1, floor 2, building 3"
2678  ********************************************************************/
2679
2680 static void spoolss_notify_location(int snum,
2681                                     struct spoolss_Notify *data,
2682                                     print_queue_struct *queue,
2683                                     NT_PRINTER_INFO_LEVEL *printer,
2684                                     TALLOC_CTX *mem_ctx)
2685 {
2686         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2687 }
2688
2689 /*******************************************************************
2690  * fill a notify_info_data with the device mode
2691  * jfm:xxxx don't to it for know but that's a real problem !!!
2692  ********************************************************************/
2693
2694 static void spoolss_notify_devmode(int snum,
2695                                    struct spoolss_Notify *data,
2696                                    print_queue_struct *queue,
2697                                    NT_PRINTER_INFO_LEVEL *printer,
2698                                    TALLOC_CTX *mem_ctx)
2699 {
2700         /* for a dummy implementation we have to zero the fields */
2701         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2702 }
2703
2704 /*******************************************************************
2705  * fill a notify_info_data with the separator file name
2706  ********************************************************************/
2707
2708 static void spoolss_notify_sepfile(int snum,
2709                                    struct spoolss_Notify *data,
2710                                    print_queue_struct *queue,
2711                                    NT_PRINTER_INFO_LEVEL *printer,
2712                                    TALLOC_CTX *mem_ctx)
2713 {
2714         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2715 }
2716
2717 /*******************************************************************
2718  * fill a notify_info_data with the print processor
2719  * jfm:xxxx return always winprint to indicate we don't do anything to it
2720  ********************************************************************/
2721
2722 static void spoolss_notify_print_processor(int snum,
2723                                            struct spoolss_Notify *data,
2724                                            print_queue_struct *queue,
2725                                            NT_PRINTER_INFO_LEVEL *printer,
2726                                            TALLOC_CTX *mem_ctx)
2727 {
2728         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2729 }
2730
2731 /*******************************************************************
2732  * fill a notify_info_data with the print processor options
2733  * jfm:xxxx send an empty string
2734  ********************************************************************/
2735
2736 static void spoolss_notify_parameters(int snum,
2737                                       struct spoolss_Notify *data,
2738                                       print_queue_struct *queue,
2739                                       NT_PRINTER_INFO_LEVEL *printer,
2740                                       TALLOC_CTX *mem_ctx)
2741 {
2742         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2743 }
2744
2745 /*******************************************************************
2746  * fill a notify_info_data with the data type
2747  * jfm:xxxx always send RAW as data type
2748  ********************************************************************/
2749
2750 static void spoolss_notify_datatype(int snum,
2751                                     struct spoolss_Notify *data,
2752                                     print_queue_struct *queue,
2753                                     NT_PRINTER_INFO_LEVEL *printer,
2754                                     TALLOC_CTX *mem_ctx)
2755 {
2756         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2757 }
2758
2759 /*******************************************************************
2760  * fill a notify_info_data with the security descriptor
2761  * jfm:xxxx send an null pointer to say no security desc
2762  * have to implement security before !
2763  ********************************************************************/
2764
2765 static void spoolss_notify_security_desc(int snum,
2766                                          struct spoolss_Notify *data,
2767                                          print_queue_struct *queue,
2768                                          NT_PRINTER_INFO_LEVEL *printer,
2769                                          TALLOC_CTX *mem_ctx)
2770 {
2771         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2772                                           printer->info_2->secdesc_buf->sd_size,
2773                                           printer->info_2->secdesc_buf->sd);
2774 }
2775
2776 /*******************************************************************
2777  * fill a notify_info_data with the attributes
2778  * jfm:xxxx a samba printer is always shared
2779  ********************************************************************/
2780
2781 static void spoolss_notify_attributes(int snum,
2782                                       struct spoolss_Notify *data,
2783                                       print_queue_struct *queue,
2784                                       NT_PRINTER_INFO_LEVEL *printer,
2785                                       TALLOC_CTX *mem_ctx)
2786 {
2787         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2788 }
2789
2790 /*******************************************************************
2791  * fill a notify_info_data with the priority
2792  ********************************************************************/
2793
2794 static void spoolss_notify_priority(int snum,
2795                                     struct spoolss_Notify *data,
2796                                     print_queue_struct *queue,
2797                                     NT_PRINTER_INFO_LEVEL *printer,
2798                                     TALLOC_CTX *mem_ctx)
2799 {
2800         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2801 }
2802
2803 /*******************************************************************
2804  * fill a notify_info_data with the default priority
2805  ********************************************************************/
2806
2807 static void spoolss_notify_default_priority(int snum,
2808                                             struct spoolss_Notify *data,
2809                                             print_queue_struct *queue,
2810                                             NT_PRINTER_INFO_LEVEL *printer,
2811                                             TALLOC_CTX *mem_ctx)
2812 {
2813         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2814 }
2815
2816 /*******************************************************************
2817  * fill a notify_info_data with the start time
2818  ********************************************************************/
2819
2820 static void spoolss_notify_start_time(int snum,
2821                                       struct spoolss_Notify *data,
2822                                       print_queue_struct *queue,
2823                                       NT_PRINTER_INFO_LEVEL *printer,
2824                                       TALLOC_CTX *mem_ctx)
2825 {
2826         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2827 }
2828
2829 /*******************************************************************
2830  * fill a notify_info_data with the until time
2831  ********************************************************************/
2832
2833 static void spoolss_notify_until_time(int snum,
2834                                       struct spoolss_Notify *data,
2835                                       print_queue_struct *queue,
2836                                       NT_PRINTER_INFO_LEVEL *printer,
2837                                       TALLOC_CTX *mem_ctx)
2838 {
2839         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2840 }
2841
2842 /*******************************************************************
2843  * fill a notify_info_data with the status
2844  ********************************************************************/
2845
2846 static void spoolss_notify_status(int snum,
2847                                   struct spoolss_Notify *data,
2848                                   print_queue_struct *queue,
2849                                   NT_PRINTER_INFO_LEVEL *printer,
2850                                   TALLOC_CTX *mem_ctx)
2851 {
2852         print_status_struct status;
2853
2854         print_queue_length(snum, &status);
2855         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2856 }
2857
2858 /*******************************************************************
2859  * fill a notify_info_data with the number of jobs queued
2860  ********************************************************************/
2861
2862 static void spoolss_notify_cjobs(int snum,
2863                                  struct spoolss_Notify *data,
2864                                  print_queue_struct *queue,
2865                                  NT_PRINTER_INFO_LEVEL *printer,
2866                                  TALLOC_CTX *mem_ctx)
2867 {
2868         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2869 }
2870
2871 /*******************************************************************
2872  * fill a notify_info_data with the average ppm
2873  ********************************************************************/
2874
2875 static void spoolss_notify_average_ppm(int snum,
2876                                        struct spoolss_Notify *data,
2877                                        print_queue_struct *queue,
2878                                        NT_PRINTER_INFO_LEVEL *printer,
2879                                        TALLOC_CTX *mem_ctx)
2880 {
2881         /* always respond 8 pages per minutes */
2882         /* a little hard ! */
2883         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2884 }
2885
2886 /*******************************************************************
2887  * fill a notify_info_data with username
2888  ********************************************************************/
2889
2890 static void spoolss_notify_username(int snum,
2891                                     struct spoolss_Notify *data,
2892                                     print_queue_struct *queue,
2893                                     NT_PRINTER_INFO_LEVEL *printer,
2894                                     TALLOC_CTX *mem_ctx)
2895 {
2896         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2897 }
2898
2899 /*******************************************************************
2900  * fill a notify_info_data with job status
2901  ********************************************************************/
2902
2903 static void spoolss_notify_job_status(int snum,
2904                                       struct spoolss_Notify *data,
2905                                       print_queue_struct *queue,
2906                                       NT_PRINTER_INFO_LEVEL *printer,
2907                                       TALLOC_CTX *mem_ctx)
2908 {
2909         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2910 }
2911
2912 /*******************************************************************
2913  * fill a notify_info_data with job name
2914  ********************************************************************/
2915
2916 static void spoolss_notify_job_name(int snum,
2917                                     struct spoolss_Notify *data,
2918                                     print_queue_struct *queue,
2919                                     NT_PRINTER_INFO_LEVEL *printer,
2920                                     TALLOC_CTX *mem_ctx)
2921 {
2922         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2923 }
2924
2925 /*******************************************************************
2926  * fill a notify_info_data with job status
2927  ********************************************************************/
2928
2929 static void spoolss_notify_job_status_string(int snum,
2930                                              struct spoolss_Notify *data,
2931                                              print_queue_struct *queue,
2932                                              NT_PRINTER_INFO_LEVEL *printer,
2933                                              TALLOC_CTX *mem_ctx)
2934 {
2935         /*
2936          * Now we're returning job status codes we just return a "" here. JRA.
2937          */
2938
2939         const char *p = "";
2940
2941 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2942         p = "unknown";
2943
2944         switch (queue->status) {
2945         case LPQ_QUEUED:
2946                 p = "Queued";
2947                 break;
2948         case LPQ_PAUSED:
2949                 p = "";    /* NT provides the paused string */
2950                 break;
2951         case LPQ_SPOOLING:
2952                 p = "Spooling";
2953                 break;
2954         case LPQ_PRINTING:
2955                 p = "Printing";
2956                 break;
2957         }
2958 #endif /* NO LONGER NEEDED. */
2959
2960         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with job time
2965  ********************************************************************/
2966
2967 static void spoolss_notify_job_time(int snum,
2968                                     struct spoolss_Notify *data,
2969                                     print_queue_struct *queue,
2970                                     NT_PRINTER_INFO_LEVEL *printer,
2971                                     TALLOC_CTX *mem_ctx)
2972 {
2973         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2974 }
2975
2976 /*******************************************************************
2977  * fill a notify_info_data with job size
2978  ********************************************************************/
2979
2980 static void spoolss_notify_job_size(int snum,
2981                                     struct spoolss_Notify *data,
2982                                     print_queue_struct *queue,
2983                                     NT_PRINTER_INFO_LEVEL *printer,
2984                                     TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with page info
2991  ********************************************************************/
2992 static void spoolss_notify_total_pages(int snum,
2993                                 struct spoolss_Notify *data,
2994                                 print_queue_struct *queue,
2995                                 NT_PRINTER_INFO_LEVEL *printer,
2996                                 TALLOC_CTX *mem_ctx)
2997 {
2998         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with pages printed info.
3003  ********************************************************************/
3004 static void spoolss_notify_pages_printed(int snum,
3005                                 struct spoolss_Notify *data,
3006                                 print_queue_struct *queue,
3007                                 NT_PRINTER_INFO_LEVEL *printer,
3008                                 TALLOC_CTX *mem_ctx)
3009 {
3010         /* Add code when back-end tracks this */
3011         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3012 }
3013
3014 /*******************************************************************
3015  Fill a notify_info_data with job position.
3016  ********************************************************************/
3017
3018 static void spoolss_notify_job_position(int snum,
3019                                         struct spoolss_Notify *data,
3020                                         print_queue_struct *queue,
3021                                         NT_PRINTER_INFO_LEVEL *printer,
3022                                         TALLOC_CTX *mem_ctx)
3023 {
3024         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3025 }
3026
3027 /*******************************************************************
3028  Fill a notify_info_data with submitted time.
3029  ********************************************************************/
3030
3031 static void spoolss_notify_submitted_time(int snum,
3032                                           struct spoolss_Notify *data,
3033                                           print_queue_struct *queue,
3034                                           NT_PRINTER_INFO_LEVEL *printer,
3035                                           TALLOC_CTX *mem_ctx)
3036 {
3037         data->data.string.string = NULL;
3038         data->data.string.size = 0;
3039
3040         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3041                                &data->data.string.string,
3042                                &data->data.string.size);
3043
3044 }
3045
3046 struct s_notify_info_data_table
3047 {
3048         enum spoolss_NotifyType type;
3049         uint16_t field;
3050         const char *name;
3051         enum spoolss_NotifyTable variable_type;
3052         void (*fn) (int snum, struct spoolss_Notify *data,
3053                     print_queue_struct *queue,
3054                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3055 };
3056
3057 /* A table describing the various print notification constants and
3058    whether the notification data is a pointer to a variable sized
3059    buffer, a one value uint32_t or a two value uint32_t. */
3060
3061 static const struct s_notify_info_data_table notify_info_data_table[] =
3062 {
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3084 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3085 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3086 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3087 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3088 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3100 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3101 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3102 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3103 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3104 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3105 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3106 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3107 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3108 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3109 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3110 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3111 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3112 };
3113
3114 /*******************************************************************
3115  Return the variable_type of info_data structure.
3116 ********************************************************************/
3117
3118 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3119                                                   uint16_t field)
3120 {
3121         int i=0;
3122
3123         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3124                 if ( (notify_info_data_table[i].type == type) &&
3125                      (notify_info_data_table[i].field == field) ) {
3126                         return notify_info_data_table[i].variable_type;
3127                 }
3128         }
3129
3130         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3131
3132         return 0;
3133 }
3134
3135 /****************************************************************************
3136 ****************************************************************************/
3137
3138 static bool search_notify(enum spoolss_NotifyType type,
3139                           uint16_t field,
3140                           int *value)
3141 {
3142         int i;
3143
3144         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3145                 if (notify_info_data_table[i].type == type &&
3146                     notify_info_data_table[i].field == field &&
3147                     notify_info_data_table[i].fn != NULL) {
3148                         *value = i;
3149                         return true;
3150                 }
3151         }
3152
3153         return false;
3154 }
3155
3156 /****************************************************************************
3157 ****************************************************************************/
3158
3159 void construct_info_data(struct spoolss_Notify *info_data,
3160                          enum spoolss_NotifyType type,
3161                          uint16_t field,
3162                          int id)
3163 {
3164         info_data->type                 = type;
3165         info_data->field.field          = field;
3166         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3167         info_data->job_id               = id;
3168 }
3169
3170 /*******************************************************************
3171  *
3172  * fill a notify_info struct with info asked
3173  *
3174  ********************************************************************/
3175
3176 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3177                                           struct spoolss_NotifyInfo *info,
3178                                           int snum,
3179                                           const struct spoolss_NotifyOptionType *option_type,
3180                                           uint32_t id,
3181                                           TALLOC_CTX *mem_ctx)
3182 {
3183         int field_num,j;
3184         enum spoolss_NotifyType type;
3185         uint16_t field;
3186
3187         struct spoolss_Notify *current_data;
3188         NT_PRINTER_INFO_LEVEL *printer = NULL;
3189         print_queue_struct *queue=NULL;
3190
3191         type = option_type->type;
3192
3193         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3194                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3195                 option_type->count, lp_servicename(snum)));
3196
3197         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3198                 return false;
3199
3200         for(field_num=0; field_num < option_type->count; field_num++) {
3201                 field = option_type->fields[field_num].field;
3202
3203                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3204
3205                 if (!search_notify(type, field, &j) )
3206                         continue;
3207
3208                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3209                                                       struct spoolss_Notify,
3210                                                       info->count + 1);
3211                 if (info->notifies == NULL) {
3212                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3213                         free_a_printer(&printer, 2);
3214                         return false;
3215                 }
3216
3217                 current_data = &info->notifies[info->count];
3218
3219                 construct_info_data(current_data, type, field, id);
3220
3221                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3222                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3223
3224                 notify_info_data_table[j].fn(snum, current_data, queue,
3225                                              printer, mem_ctx);
3226
3227                 info->count++;
3228         }
3229
3230         free_a_printer(&printer, 2);
3231         return true;
3232 }
3233
3234 /*******************************************************************
3235  *
3236  * fill a notify_info struct with info asked
3237  *
3238  ********************************************************************/
3239
3240 static bool construct_notify_jobs_info(print_queue_struct *queue,
3241                                        struct spoolss_NotifyInfo *info,
3242                                        NT_PRINTER_INFO_LEVEL *printer,
3243                                        int snum,
3244                                        const struct spoolss_NotifyOptionType *option_type,
3245                                        uint32_t id,
3246                                        TALLOC_CTX *mem_ctx)
3247 {
3248         int field_num,j;
3249         enum spoolss_NotifyType type;
3250         uint16_t field;
3251         struct spoolss_Notify *current_data;
3252
3253         DEBUG(4,("construct_notify_jobs_info\n"));
3254
3255         type = option_type->type;
3256
3257         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3258                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3259                 option_type->count));
3260
3261         for(field_num=0; field_num<option_type->count; field_num++) {
3262                 field = option_type->fields[field_num].field;
3263
3264                 if (!search_notify(type, field, &j) )
3265                         continue;
3266
3267                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3268                                                       struct spoolss_Notify,
3269                                                       info->count + 1);
3270                 if (info->notifies == NULL) {
3271                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3272                         return false;
3273                 }
3274
3275                 current_data=&(info->notifies[info->count]);
3276
3277                 construct_info_data(current_data, type, field, id);
3278                 notify_info_data_table[j].fn(snum, current_data, queue,
3279                                              printer, mem_ctx);
3280                 info->count++;
3281         }
3282
3283         return true;
3284 }
3285
3286 /*
3287  * JFM: The enumeration is not that simple, it's even non obvious.
3288  *
3289  * let's take an example: I want to monitor the PRINTER SERVER for
3290  * the printer's name and the number of jobs currently queued.
3291  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3292  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3293  *
3294  * I have 3 printers on the back of my server.
3295  *
3296  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3297  * structures.
3298  *   Number     Data                    Id
3299  *      1       printer 1 name          1
3300  *      2       printer 1 cjob          1
3301  *      3       printer 2 name          2
3302  *      4       printer 2 cjob          2
3303  *      5       printer 3 name          3
3304  *      6       printer 3 name          3
3305  *
3306  * that's the print server case, the printer case is even worse.
3307  */
3308
3309 /*******************************************************************
3310  *
3311  * enumerate all printers on the printserver
3312  * fill a notify_info struct with info asked
3313  *
3314  ********************************************************************/
3315
3316 static WERROR printserver_notify_info(pipes_struct *p,
3317                                       struct policy_handle *hnd,
3318                                       struct spoolss_NotifyInfo *info,
3319                                       TALLOC_CTX *mem_ctx)
3320 {
3321         int snum;
3322         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3323         int n_services=lp_numservices();
3324         int i;
3325         struct spoolss_NotifyOption *option;
3326         struct spoolss_NotifyOptionType option_type;
3327
3328         DEBUG(4,("printserver_notify_info\n"));
3329
3330         if (!Printer)
3331                 return WERR_BADFID;
3332
3333         option = Printer->notify.option;
3334
3335         info->version   = 2;
3336         info->notifies  = NULL;
3337         info->count     = 0;
3338
3339         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3340            sending a ffpcn() request first */
3341
3342         if ( !option )
3343                 return WERR_BADFID;
3344
3345         for (i=0; i<option->count; i++) {
3346                 option_type = option->types[i];
3347
3348                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3349                         continue;
3350
3351                 for (snum=0; snum<n_services; snum++)
3352                 {
3353                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3354                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3355                 }
3356         }
3357
3358 #if 0
3359         /*
3360          * Debugging information, don't delete.
3361          */
3362
3363         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3364         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3365         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3366
3367         for (i=0; i<info->count; i++) {
3368                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3369                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3370                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3371         }
3372 #endif
3373
3374         return WERR_OK;
3375 }
3376
3377 /*******************************************************************
3378  *
3379  * fill a notify_info struct with info asked
3380  *
3381  ********************************************************************/
3382
3383 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3384                                   struct spoolss_NotifyInfo *info,
3385                                   TALLOC_CTX *mem_ctx)
3386 {
3387         int snum;
3388         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3389         int i;
3390         uint32_t id;
3391         struct spoolss_NotifyOption *option;
3392         struct spoolss_NotifyOptionType option_type;
3393         int count,j;
3394         print_queue_struct *queue=NULL;
3395         print_status_struct status;
3396
3397         DEBUG(4,("printer_notify_info\n"));
3398
3399         if (!Printer)
3400                 return WERR_BADFID;
3401
3402         option = Printer->notify.option;
3403         id = 0x0;
3404
3405         info->version   = 2;
3406         info->notifies  = NULL;
3407         info->count     = 0;
3408
3409         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3410            sending a ffpcn() request first */
3411
3412         if ( !option )
3413                 return WERR_BADFID;
3414
3415         get_printer_snum(p, hnd, &snum, NULL);
3416
3417         for (i=0; i<option->count; i++) {
3418                 option_type = option->types[i];
3419
3420                 switch (option_type.type) {
3421                 case PRINTER_NOTIFY_TYPE:
3422                         if(construct_notify_printer_info(Printer, info, snum,
3423                                                          &option_type, id,
3424                                                          mem_ctx))
3425                                 id--;
3426                         break;
3427
3428                 case JOB_NOTIFY_TYPE: {
3429                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3430
3431                         count = print_queue_status(snum, &queue, &status);
3432
3433                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3434                                 goto done;
3435
3436                         for (j=0; j<count; j++) {
3437                                 construct_notify_jobs_info(&queue[j], info,
3438                                                            printer, snum,
3439                                                            &option_type,
3440                                                            queue[j].job,
3441                                                            mem_ctx);
3442                         }
3443
3444                         free_a_printer(&printer, 2);
3445
3446                 done:
3447                         SAFE_FREE(queue);
3448                         break;
3449                 }
3450                 }
3451         }
3452
3453         /*
3454          * Debugging information, don't delete.
3455          */
3456         /*
3457         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3458         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3459         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3460
3461         for (i=0; i<info->count; i++) {
3462                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3463                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3464                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3465         }
3466         */
3467         return WERR_OK;
3468 }
3469
3470 /****************************************************************
3471  _spoolss_RouterRefreshPrinterChangeNotify
3472 ****************************************************************/
3473
3474 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3475                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3476 {
3477         struct spoolss_NotifyInfo *info;
3478
3479         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3480         WERROR result = WERR_BADFID;
3481
3482         /* we always have a spoolss_NotifyInfo struct */
3483         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3484         if (!info) {
3485                 result = WERR_NOMEM;
3486                 goto done;
3487         }
3488
3489         *r->out.info = info;
3490
3491         if (!Printer) {
3492                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3493                         "Invalid handle (%s:%u:%u).\n",
3494                         OUR_HANDLE(r->in.handle)));
3495                 goto done;
3496         }
3497
3498         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3499
3500         /*
3501          *      We are now using the change value, and
3502          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3503          *      I don't have a global notification system, I'm sending back all the
3504          *      informations even when _NOTHING_ has changed.
3505          */
3506
3507         /* We need to keep track of the change value to send back in
3508            RRPCN replies otherwise our updates are ignored. */
3509
3510         Printer->notify.fnpcn = true;
3511
3512         if (Printer->notify.client_connected) {
3513                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3514                         "Saving change value in request [%x]\n",
3515                         r->in.change_low));
3516                 Printer->notify.change = r->in.change_low;
3517         }
3518
3519         /* just ignore the spoolss_NotifyOption */
3520
3521         switch (Printer->printer_type) {
3522                 case SPLHND_SERVER:
3523                         result = printserver_notify_info(p, r->in.handle,
3524                                                          info, p->mem_ctx);
3525                         break;
3526
3527                 case SPLHND_PRINTER:
3528                         result = printer_notify_info(p, r->in.handle,
3529                                                      info, p->mem_ctx);
3530                         break;
3531         }
3532
3533         Printer->notify.fnpcn = false;
3534
3535 done:
3536         return result;
3537 }
3538
3539 /********************************************************************
3540  * construct_printer_info_0
3541  * fill a printer_info_0 struct
3542  ********************************************************************/
3543
3544 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3545                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3546                                       struct spoolss_PrinterInfo0 *r,
3547                                       int snum)
3548 {
3549         int count;
3550         counter_printer_0 *session_counter;
3551         time_t setuptime;
3552         print_status_struct status;
3553
3554         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3555         W_ERROR_HAVE_NO_MEMORY(r->printername);
3556
3557         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3558         W_ERROR_HAVE_NO_MEMORY(r->servername);
3559
3560         count = print_queue_length(snum, &status);
3561
3562         /* check if we already have a counter for this printer */
3563         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3564                 if (session_counter->snum == snum)
3565                         break;
3566         }
3567
3568         /* it's the first time, add it to the list */
3569         if (session_counter == NULL) {
3570                 session_counter = SMB_MALLOC_P(counter_printer_0);
3571                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3572                 ZERO_STRUCTP(session_counter);
3573                 session_counter->snum           = snum;
3574                 session_counter->counter        = 0;
3575                 DLIST_ADD(counter_list, session_counter);
3576         }
3577
3578         /* increment it */
3579         session_counter->counter++;
3580
3581         r->cjobs                        = count;
3582         r->total_jobs                   = 0;
3583         r->total_bytes                  = 0;
3584
3585         setuptime = (time_t)ntprinter->info_2->setuptime;
3586
3587         init_systemtime(&r->time, gmtime(&setuptime));
3588
3589         /* JFM:
3590          * the global_counter should be stored in a TDB as it's common to all the clients
3591          * and should be zeroed on samba startup
3592          */
3593         r->global_counter               = session_counter->counter;
3594         r->total_pages                  = 0;
3595         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3596         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3597         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3598         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3599         r->spooling                     = 0;
3600         r->max_spooling                 = 0;
3601         r->session_counter              = session_counter->counter;
3602         r->num_error_out_of_paper       = 0x0;
3603         r->num_error_not_ready          = 0x0;          /* number of print failure */
3604         r->job_error                    = 0x0;
3605         r->number_of_processors         = 0x1;
3606         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3607         r->high_part_total_bytes        = 0x0;
3608         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3609         r->last_error                   = WERR_OK;
3610         r->status                       = nt_printq_status(status.status);
3611         r->enumerate_network_printers   = 0x0;
3612         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3613         r->processor_architecture       = 0x0;
3614         r->processor_level              = 0x6;          /* 6  ???*/
3615         r->ref_ic                       = 0;
3616         r->reserved2                    = 0;
3617         r->reserved3                    = 0;
3618
3619         return WERR_OK;
3620 }
3621
3622 /****************************************************************************
3623  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3624  should be valid upon entry
3625 ****************************************************************************/
3626
3627 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3628                                     struct spoolss_DeviceMode *r,
3629                                     const NT_DEVICEMODE *ntdevmode)
3630 {
3631         if (!r || !ntdevmode) {
3632                 return WERR_INVALID_PARAM;
3633         }
3634
3635         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3636         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3637
3638         r->specversion          = ntdevmode->specversion;
3639         r->driverversion        = ntdevmode->driverversion;
3640         r->size                 = ntdevmode->size;
3641         r->__driverextra_length = ntdevmode->driverextra;
3642         r->fields               = ntdevmode->fields;
3643
3644         r->orientation          = ntdevmode->orientation;
3645         r->papersize            = ntdevmode->papersize;
3646         r->paperlength          = ntdevmode->paperlength;
3647         r->paperwidth           = ntdevmode->paperwidth;
3648         r->scale                = ntdevmode->scale;
3649         r->copies               = ntdevmode->copies;
3650         r->defaultsource        = ntdevmode->defaultsource;
3651         r->printquality         = ntdevmode->printquality;
3652         r->color                = ntdevmode->color;
3653         r->duplex               = ntdevmode->duplex;
3654         r->yresolution          = ntdevmode->yresolution;
3655         r->ttoption             = ntdevmode->ttoption;
3656         r->collate              = ntdevmode->collate;
3657
3658         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3659         W_ERROR_HAVE_NO_MEMORY(r->formname);
3660
3661         r->logpixels            = ntdevmode->logpixels;
3662         r->bitsperpel           = ntdevmode->bitsperpel;
3663         r->pelswidth            = ntdevmode->pelswidth;
3664         r->pelsheight           = ntdevmode->pelsheight;
3665         r->displayflags         = ntdevmode->displayflags;
3666         r->displayfrequency     = ntdevmode->displayfrequency;
3667         r->icmmethod            = ntdevmode->icmmethod;
3668         r->icmintent            = ntdevmode->icmintent;
3669         r->mediatype            = ntdevmode->mediatype;
3670         r->dithertype           = ntdevmode->dithertype;
3671         r->reserved1            = ntdevmode->reserved1;
3672         r->reserved2            = ntdevmode->reserved2;
3673         r->panningwidth         = ntdevmode->panningwidth;
3674         r->panningheight        = ntdevmode->panningheight;
3675
3676         if (ntdevmode->nt_dev_private != NULL) {
3677                 r->driverextra_data = data_blob_talloc(mem_ctx,
3678                         ntdevmode->nt_dev_private,
3679                         ntdevmode->driverextra);
3680                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3681         }
3682
3683         return WERR_OK;
3684 }
3685
3686
3687 /****************************************************************************
3688  Create a spoolss_DeviceMode struct. Returns talloced memory.
3689 ****************************************************************************/
3690
3691 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3692                                               const char *servicename)
3693 {
3694         WERROR result;
3695         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3696         struct spoolss_DeviceMode *devmode = NULL;
3697
3698         DEBUG(7,("construct_dev_mode\n"));
3699
3700         DEBUGADD(8,("getting printer characteristics\n"));
3701
3702         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3703                 return NULL;
3704
3705         if (!printer->info_2->devmode) {
3706                 DEBUG(5, ("BONG! There was no device mode!\n"));
3707                 goto done;
3708         }
3709
3710         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3711         if (!devmode) {
3712                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3713                 goto done;
3714         }
3715
3716         DEBUGADD(8,("loading DEVICEMODE\n"));
3717
3718         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3719         if (!W_ERROR_IS_OK(result)) {
3720                 TALLOC_FREE(devmode);
3721         }
3722
3723 done:
3724         free_a_printer(&printer,2);
3725
3726         return devmode;
3727 }
3728
3729 /********************************************************************
3730  * construct_printer_info1
3731  * fill a spoolss_PrinterInfo1 struct
3732 ********************************************************************/
3733
3734 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3735                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3736                                       uint32_t flags,
3737                                       struct spoolss_PrinterInfo1 *r,
3738                                       int snum)
3739 {
3740         r->flags                = flags;
3741
3742         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3743                                                   ntprinter->info_2->printername,
3744                                                   ntprinter->info_2->drivername,
3745                                                   ntprinter->info_2->location);
3746         W_ERROR_HAVE_NO_MEMORY(r->description);
3747
3748         if (*ntprinter->info_2->comment == '\0') {
3749                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3750         } else {
3751                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3752         }
3753         W_ERROR_HAVE_NO_MEMORY(r->comment);
3754
3755         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3756         W_ERROR_HAVE_NO_MEMORY(r->name);
3757
3758         return WERR_OK;
3759 }
3760
3761 /********************************************************************
3762  * construct_printer_info2
3763  * fill a spoolss_PrinterInfo2 struct
3764 ********************************************************************/
3765
3766 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3767                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3768                                       struct spoolss_PrinterInfo2 *r,
3769                                       int snum)
3770 {
3771         int count;
3772
3773         print_status_struct status;
3774
3775         count = print_queue_length(snum, &status);
3776
3777         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3778         W_ERROR_HAVE_NO_MEMORY(r->servername);
3779         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3780         W_ERROR_HAVE_NO_MEMORY(r->printername);
3781         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3782         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3783         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3784         W_ERROR_HAVE_NO_MEMORY(r->portname);
3785         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3786         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3787
3788         if (*ntprinter->info_2->comment == '\0') {
3789                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3790         } else {
3791                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3792         }
3793         W_ERROR_HAVE_NO_MEMORY(r->comment);
3794
3795         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3796         W_ERROR_HAVE_NO_MEMORY(r->location);
3797         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3798         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3799         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3800         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3801         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3802         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3803         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3804         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3805
3806         r->attributes           = ntprinter->info_2->attributes;
3807
3808         r->priority             = ntprinter->info_2->priority;
3809         r->defaultpriority      = ntprinter->info_2->default_priority;
3810         r->starttime            = ntprinter->info_2->starttime;
3811         r->untiltime            = ntprinter->info_2->untiltime;
3812         r->status               = nt_printq_status(status.status);
3813         r->cjobs                = count;
3814         r->averageppm           = ntprinter->info_2->averageppm;
3815
3816         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3817         if (!r->devmode) {
3818                 DEBUG(8,("Returning NULL Devicemode!\n"));
3819         }
3820
3821         r->secdesc              = NULL;
3822
3823         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3824                 /* don't use talloc_steal() here unless you do a deep steal of all
3825                    the SEC_DESC members */
3826
3827                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3828         }
3829
3830         return WERR_OK;
3831 }
3832
3833 /********************************************************************
3834  * construct_printer_info3
3835  * fill a spoolss_PrinterInfo3 struct
3836  ********************************************************************/
3837
3838 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3839                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3840                                       struct spoolss_PrinterInfo3 *r,
3841                                       int snum)
3842 {
3843         /* These are the components of the SD we are returning. */
3844
3845         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3846                 /* don't use talloc_steal() here unless you do a deep steal of all
3847                    the SEC_DESC members */
3848
3849                 r->secdesc = dup_sec_desc(mem_ctx,
3850                                           ntprinter->info_2->secdesc_buf->sd);
3851                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3852         }
3853
3854         return WERR_OK;
3855 }
3856
3857 /********************************************************************
3858  * construct_printer_info4
3859  * fill a spoolss_PrinterInfo4 struct
3860  ********************************************************************/
3861
3862 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3863                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3864                                       struct spoolss_PrinterInfo4 *r,
3865                                       int snum)
3866 {
3867         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3868         W_ERROR_HAVE_NO_MEMORY(r->printername);
3869         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3870         W_ERROR_HAVE_NO_MEMORY(r->servername);
3871
3872         r->attributes   = ntprinter->info_2->attributes;
3873
3874         return WERR_OK;
3875 }
3876
3877 /********************************************************************
3878  * construct_printer_info5
3879  * fill a spoolss_PrinterInfo5 struct
3880  ********************************************************************/
3881
3882 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3883                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3884                                       struct spoolss_PrinterInfo5 *r,
3885                                       int snum)
3886 {
3887         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3888         W_ERROR_HAVE_NO_MEMORY(r->printername);
3889         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3890         W_ERROR_HAVE_NO_MEMORY(r->portname);
3891
3892         r->attributes   = ntprinter->info_2->attributes;
3893
3894         /* these two are not used by NT+ according to MSDN */
3895
3896         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3897         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3898
3899         return WERR_OK;
3900 }
3901
3902 /********************************************************************
3903  * construct_printer_info_6
3904  * fill a spoolss_PrinterInfo6 struct
3905  ********************************************************************/
3906
3907 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3908                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3909                                       struct spoolss_PrinterInfo6 *r,
3910                                       int snum)
3911 {
3912         int count;
3913         print_status_struct status;
3914
3915         count = print_queue_length(snum, &status);
3916
3917         r->status = nt_printq_status(status.status);
3918
3919         return WERR_OK;
3920 }
3921
3922 /********************************************************************
3923  * construct_printer_info7
3924  * fill a spoolss_PrinterInfo7 struct
3925  ********************************************************************/
3926
3927 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3928                                       Printer_entry *print_hnd,
3929                                       struct spoolss_PrinterInfo7 *r,
3930                                       int snum)
3931 {
3932         struct GUID guid;
3933
3934         if (is_printer_published(print_hnd, snum, &guid)) {
3935                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3936                 r->action = DSPRINT_PUBLISH;
3937         } else {
3938                 r->guid = talloc_strdup(mem_ctx, "");
3939                 r->action = DSPRINT_UNPUBLISH;
3940         }
3941         W_ERROR_HAVE_NO_MEMORY(r->guid);
3942
3943         return WERR_OK;
3944 }
3945
3946 /********************************************************************
3947  * construct_printer_info8
3948  * fill a spoolss_PrinterInfo8 struct
3949  ********************************************************************/
3950
3951 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3952                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3953                                       struct spoolss_DeviceModeInfo *r,
3954                                       int snum)
3955 {
3956         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3957         if (!r->devmode) {
3958                 DEBUG(8,("Returning NULL Devicemode!\n"));
3959         }
3960
3961         return WERR_OK;
3962 }
3963
3964
3965 /********************************************************************
3966 ********************************************************************/
3967
3968 static bool snum_is_shared_printer(int snum)
3969 {
3970         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3971 }
3972
3973 /********************************************************************
3974  Spoolss_enumprinters.
3975 ********************************************************************/
3976
3977 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3978                                            uint32_t level,
3979                                            uint32_t flags,
3980                                            union spoolss_PrinterInfo **info_p,
3981                                            uint32_t *count_p)
3982 {
3983         int snum;
3984         int n_services = lp_numservices();
3985         union spoolss_PrinterInfo *info = NULL;
3986         uint32_t count = 0;
3987         WERROR result = WERR_OK;
3988
3989         *count_p = 0;
3990         *info_p = NULL;
3991
3992         for (snum = 0; snum < n_services; snum++) {
3993
3994                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3995
3996                 if (!snum_is_shared_printer(snum)) {
3997                         continue;
3998                 }
3999
4000                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4001                         lp_servicename(snum), snum));
4002
4003                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4004                                             union spoolss_PrinterInfo,
4005                                             count + 1);
4006                 if (!info) {
4007                         result = WERR_NOMEM;
4008                         goto out;
4009                 }
4010
4011                 result = get_a_printer(NULL, &ntprinter, 2,
4012                                        lp_const_servicename(snum));
4013                 if (!W_ERROR_IS_OK(result)) {
4014                         goto out;
4015                 }
4016
4017                 switch (level) {
4018                 case 0:
4019                         result = construct_printer_info0(info, ntprinter,
4020                                                          &info[count].info0, snum);
4021                         break;
4022                 case 1:
4023                         result = construct_printer_info1(info, ntprinter, flags,
4024                                                          &info[count].info1, snum);
4025                         break;
4026                 case 2:
4027                         result = construct_printer_info2(info, ntprinter,
4028                                                          &info[count].info2, snum);
4029                         break;
4030                 case 4:
4031                         result = construct_printer_info4(info, ntprinter,
4032                                                          &info[count].info4, snum);
4033                         break;
4034                 case 5:
4035                         result = construct_printer_info5(info, ntprinter,
4036                                                          &info[count].info5, snum);
4037                         break;
4038
4039                 default:
4040                         result = WERR_UNKNOWN_LEVEL;
4041                         free_a_printer(&ntprinter, 2);
4042                         goto out;
4043                 }
4044
4045                 free_a_printer(&ntprinter, 2);
4046                 if (!W_ERROR_IS_OK(result)) {
4047                         goto out;
4048                 }
4049
4050                 count++;
4051         }
4052
4053         *count_p = count;
4054         *info_p = info;
4055
4056  out:
4057         if (!W_ERROR_IS_OK(result)) {
4058                 TALLOC_FREE(info);
4059                 return result;
4060         }
4061
4062         *info_p = info;
4063
4064         return WERR_OK;
4065 }
4066
4067 /********************************************************************
4068  * handle enumeration of printers at level 0
4069  ********************************************************************/
4070
4071 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4072                                   uint32_t flags,
4073                                   const char *servername,
4074                                   union spoolss_PrinterInfo **info,
4075                                   uint32_t *count)
4076 {
4077         DEBUG(4,("enum_all_printers_info_0\n"));
4078
4079         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4080 }
4081
4082
4083 /********************************************************************
4084 ********************************************************************/
4085
4086 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4087                                        uint32_t flags,
4088                                        union spoolss_PrinterInfo **info,
4089                                        uint32_t *count)
4090 {
4091         DEBUG(4,("enum_all_printers_info_1\n"));
4092
4093         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4094 }
4095
4096 /********************************************************************
4097  enum_all_printers_info_1_local.
4098 *********************************************************************/
4099
4100 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4101                                              union spoolss_PrinterInfo **info,
4102                                              uint32_t *count)
4103 {
4104         DEBUG(4,("enum_all_printers_info_1_local\n"));
4105
4106         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4107 }
4108
4109 /********************************************************************
4110  enum_all_printers_info_1_name.
4111 *********************************************************************/
4112
4113 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4114                                             const char *name,
4115                                             union spoolss_PrinterInfo **info,
4116                                             uint32_t *count)
4117 {
4118         const char *s = name;
4119
4120         DEBUG(4,("enum_all_printers_info_1_name\n"));
4121
4122         if ((name[0] == '\\') && (name[1] == '\\')) {
4123                 s = name + 2;
4124         }
4125
4126         if (!is_myname_or_ipaddr(s)) {
4127                 return WERR_INVALID_NAME;
4128         }
4129
4130         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4131 }
4132
4133 /********************************************************************
4134  enum_all_printers_info_1_network.
4135 *********************************************************************/
4136
4137 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4138                                                const char *name,
4139                                                union spoolss_PrinterInfo **info,
4140                                                uint32_t *count)
4141 {
4142         const char *s = name;
4143
4144         DEBUG(4,("enum_all_printers_info_1_network\n"));
4145
4146         /* If we respond to a enum_printers level 1 on our name with flags
4147            set to PRINTER_ENUM_REMOTE with a list of printers then these
4148            printers incorrectly appear in the APW browse list.
4149            Specifically the printers for the server appear at the workgroup
4150            level where all the other servers in the domain are
4151            listed. Windows responds to this call with a
4152            WERR_CAN_NOT_COMPLETE so we should do the same. */
4153
4154         if (name[0] == '\\' && name[1] == '\\') {
4155                  s = name + 2;
4156         }
4157
4158         if (is_myname_or_ipaddr(s)) {
4159                  return WERR_CAN_NOT_COMPLETE;
4160         }
4161
4162         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4163 }
4164
4165 /********************************************************************
4166  * api_spoolss_enumprinters
4167  *
4168  * called from api_spoolss_enumprinters (see this to understand)
4169  ********************************************************************/
4170
4171 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4172                                        union spoolss_PrinterInfo **info,
4173                                        uint32_t *count)
4174 {
4175         DEBUG(4,("enum_all_printers_info_2\n"));
4176
4177         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4178 }
4179
4180 /********************************************************************
4181  * handle enumeration of printers at level 1
4182  ********************************************************************/
4183
4184 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4185                                   uint32_t flags,
4186                                   const char *name,
4187                                   union spoolss_PrinterInfo **info,
4188                                   uint32_t *count)
4189 {
4190         /* Not all the flags are equals */
4191
4192         if (flags & PRINTER_ENUM_LOCAL) {
4193                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4194         }
4195
4196         if (flags & PRINTER_ENUM_NAME) {
4197                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4198         }
4199
4200         if (flags & PRINTER_ENUM_NETWORK) {
4201                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4202         }
4203
4204         return WERR_OK; /* NT4sp5 does that */
4205 }
4206
4207 /********************************************************************
4208  * handle enumeration of printers at level 2
4209  ********************************************************************/
4210
4211 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4212                                   uint32_t flags,
4213                                   const char *servername,
4214                                   union spoolss_PrinterInfo **info,
4215                                   uint32_t *count)
4216 {
4217         if (flags & PRINTER_ENUM_LOCAL) {
4218                 return enum_all_printers_info_2(mem_ctx, info, count);
4219         }
4220
4221         if (flags & PRINTER_ENUM_NAME) {
4222                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4223                         return WERR_INVALID_NAME;
4224                 }
4225
4226                 return enum_all_printers_info_2(mem_ctx, info, count);
4227         }
4228
4229         if (flags & PRINTER_ENUM_REMOTE) {
4230                 return WERR_UNKNOWN_LEVEL;
4231         }
4232
4233         return WERR_OK;
4234 }
4235
4236 /********************************************************************
4237  * handle enumeration of printers at level 4
4238  ********************************************************************/
4239
4240 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4241                                   uint32_t flags,
4242                                   const char *servername,
4243                                   union spoolss_PrinterInfo **info,
4244                                   uint32_t *count)
4245 {
4246         DEBUG(4,("enum_all_printers_info_4\n"));
4247
4248         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4249 }
4250
4251
4252 /********************************************************************
4253  * handle enumeration of printers at level 5
4254  ********************************************************************/
4255
4256 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4257                                   uint32_t flags,
4258                                   const char *servername,
4259                                   union spoolss_PrinterInfo **info,
4260                                   uint32_t *count)
4261 {
4262         DEBUG(4,("enum_all_printers_info_5\n"));
4263
4264         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4265 }
4266
4267 /****************************************************************
4268  _spoolss_EnumPrinters
4269 ****************************************************************/
4270
4271 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4272                              struct spoolss_EnumPrinters *r)
4273 {
4274         const char *name = NULL;
4275         WERROR result;
4276
4277         /* that's an [in out] buffer */
4278
4279         if (!r->in.buffer && (r->in.offered != 0)) {
4280                 return WERR_INVALID_PARAM;
4281         }
4282
4283         DEBUG(4,("_spoolss_EnumPrinters\n"));
4284
4285         *r->out.needed = 0;
4286         *r->out.count = 0;
4287         *r->out.info = NULL;
4288
4289         /*
4290          * Level 1:
4291          *          flags==PRINTER_ENUM_NAME
4292          *           if name=="" then enumerates all printers
4293          *           if name!="" then enumerate the printer
4294          *          flags==PRINTER_ENUM_REMOTE
4295          *          name is NULL, enumerate printers
4296          * Level 2: name!="" enumerates printers, name can't be NULL
4297          * Level 3: doesn't exist
4298          * Level 4: does a local registry lookup
4299          * Level 5: same as Level 2
4300          */
4301
4302         if (r->in.server) {
4303                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4304                 W_ERROR_HAVE_NO_MEMORY(name);
4305         }
4306
4307         switch (r->in.level) {
4308         case 0:
4309                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4310                                              r->out.info, r->out.count);
4311                 break;
4312         case 1:
4313                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4314                                              r->out.info, r->out.count);
4315                 break;
4316         case 2:
4317                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4318                                              r->out.info, r->out.count);
4319                 break;
4320         case 4:
4321                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4322                                              r->out.info, r->out.count);
4323                 break;
4324         case 5:
4325                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4326                                              r->out.info, r->out.count);
4327                 break;
4328         default:
4329                 return WERR_UNKNOWN_LEVEL;
4330         }
4331
4332         if (!W_ERROR_IS_OK(result)) {
4333                 return result;
4334         }
4335
4336         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4337                                                      spoolss_EnumPrinters, NULL,
4338                                                      *r->out.info, r->in.level,
4339                                                      *r->out.count);
4340         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4341         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4342
4343         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4344 }
4345
4346 /****************************************************************
4347  _spoolss_GetPrinter
4348 ****************************************************************/
4349
4350 WERROR _spoolss_GetPrinter(pipes_struct *p,
4351                            struct spoolss_GetPrinter *r)
4352 {
4353         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4354         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4355         WERROR result = WERR_OK;
4356
4357         int snum;
4358
4359         /* that's an [in out] buffer */
4360
4361         if (!r->in.buffer && (r->in.offered != 0)) {
4362                 return WERR_INVALID_PARAM;
4363         }
4364
4365         *r->out.needed = 0;
4366
4367         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4368                 return WERR_BADFID;
4369         }
4370
4371         result = get_a_printer(Printer, &ntprinter, 2,
4372                                lp_const_servicename(snum));
4373         if (!W_ERROR_IS_OK(result)) {
4374                 return result;
4375         }
4376
4377         switch (r->in.level) {
4378         case 0:
4379                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4380                                                  &r->out.info->info0, snum);
4381                 break;
4382         case 1:
4383                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4384                                                  PRINTER_ENUM_ICON8,
4385                                                  &r->out.info->info1, snum);
4386                 break;
4387         case 2:
4388                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4389                                                  &r->out.info->info2, snum);
4390                 break;
4391         case 3:
4392                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4393                                                  &r->out.info->info3, snum);
4394                 break;
4395         case 4:
4396                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4397                                                  &r->out.info->info4, snum);
4398                 break;
4399         case 5:
4400                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4401                                                  &r->out.info->info5, snum);
4402                 break;
4403         case 6:
4404                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4405                                                  &r->out.info->info6, snum);
4406                 break;
4407         case 7:
4408                 result = construct_printer_info7(p->mem_ctx, Printer,
4409                                                  &r->out.info->info7, snum);
4410                 break;
4411         case 8:
4412                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4413                                                  &r->out.info->info8, snum);
4414                 break;
4415         default:
4416                 result = WERR_UNKNOWN_LEVEL;
4417                 break;
4418         }
4419
4420         free_a_printer(&ntprinter, 2);
4421
4422         if (!W_ERROR_IS_OK(result)) {
4423                 TALLOC_FREE(r->out.info);
4424                 return result;
4425         }
4426
4427         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4428                                                r->out.info, r->in.level);
4429         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4430
4431         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4432 }
4433
4434 /********************************************************************
4435  ********************************************************************/
4436
4437 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4438                                                   const char **string_array,
4439                                                   const char *cservername)
4440 {
4441         int i, num_strings = 0;
4442         const char **array = NULL;
4443
4444         if (!string_array) {
4445                 return NULL;
4446         }
4447
4448         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4449
4450                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4451                                                   cservername, string_array[i]);
4452                 if (!str) {
4453                         TALLOC_FREE(array);
4454                         return NULL;
4455                 }
4456
4457
4458                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4459                         TALLOC_FREE(array);
4460                         return NULL;
4461                 }
4462         }
4463
4464         if (i > 0) {
4465                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4466                              &array, &num_strings);
4467         }
4468
4469         return array;
4470 }
4471
4472 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4473         do { \
4474                 if (in && strlen(in)) { \
4475                         out = talloc_strdup(mem_ctx, in); \
4476                         W_ERROR_HAVE_NO_MEMORY(out); \
4477                 } else { \
4478                         out = NULL; \
4479                 } \
4480         } while (0);
4481
4482 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4483         do { \
4484                 if (in && strlen(in)) { \
4485                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4486                 } else { \
4487                         out = talloc_strdup(mem_ctx, ""); \
4488                 } \
4489                 W_ERROR_HAVE_NO_MEMORY(out); \
4490         } while (0);
4491
4492 /********************************************************************
4493  * fill a spoolss_DriverInfo1 struct
4494  ********************************************************************/
4495
4496 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4497                                         struct spoolss_DriverInfo1 *r,
4498                                         const struct spoolss_DriverInfo8 *driver,
4499                                         const char *servername)
4500 {
4501         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4502         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4503
4504         return WERR_OK;
4505 }
4506
4507 /********************************************************************
4508  * fill a spoolss_DriverInfo2 struct
4509  ********************************************************************/
4510
4511 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4512                                         struct spoolss_DriverInfo2 *r,
4513                                         const struct spoolss_DriverInfo8 *driver,
4514                                         const char *servername)
4515
4516 {
4517         const char *cservername = canon_servername(servername);
4518
4519         r->version              = driver->version;
4520
4521         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4522         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4523         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4524         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4525
4526         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4527                                driver->driver_path,
4528                                r->driver_path);
4529
4530         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4531                                driver->data_file,
4532                                r->data_file);
4533
4534         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4535                                driver->config_file,
4536                                r->config_file);
4537
4538         return WERR_OK;
4539 }
4540
4541 /********************************************************************
4542  * fill a spoolss_DriverInfo3 struct
4543  ********************************************************************/
4544
4545 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4546                                         struct spoolss_DriverInfo3 *r,
4547                                         const struct spoolss_DriverInfo8 *driver,
4548                                         const char *servername)
4549 {
4550         const char *cservername = canon_servername(servername);
4551
4552         r->version              = driver->version;
4553
4554         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4555         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4556         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4557         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4558
4559         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4560                                driver->driver_path,
4561                                r->driver_path);
4562
4563         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4564                                driver->data_file,
4565                                r->data_file);
4566
4567         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4568                                driver->config_file,
4569                                r->config_file);
4570
4571         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4572                                driver->help_file,
4573                                r->help_file);
4574
4575         FILL_DRIVER_STRING(mem_ctx,
4576                            driver->monitor_name,
4577                            r->monitor_name);
4578
4579         FILL_DRIVER_STRING(mem_ctx,
4580                            driver->default_datatype,
4581                            r->default_datatype);
4582
4583         r->dependent_files = string_array_from_driver_info(mem_ctx,
4584                                                            driver->dependent_files,
4585                                                            cservername);
4586         return WERR_OK;
4587 }
4588
4589 /********************************************************************
4590  * fill a spoolss_DriverInfo4 struct
4591  ********************************************************************/
4592
4593 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4594                                         struct spoolss_DriverInfo4 *r,
4595                                         const struct spoolss_DriverInfo8 *driver,
4596                                         const char *servername)
4597 {
4598         const char *cservername = canon_servername(servername);
4599
4600         r->version              = driver->version;
4601
4602         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4603         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4604         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4605         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4606
4607         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4608                                driver->driver_path,
4609                                r->driver_path);
4610
4611         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4612                                driver->data_file,
4613                                r->data_file);
4614
4615         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4616                                driver->config_file,
4617                                r->config_file);
4618
4619         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4620                                driver->help_file,
4621                                r->help_file);
4622
4623         r->dependent_files = string_array_from_driver_info(mem_ctx,
4624                                                            driver->dependent_files,
4625                                                            cservername);
4626
4627         FILL_DRIVER_STRING(mem_ctx,
4628                            driver->monitor_name,
4629                            r->monitor_name);
4630
4631         FILL_DRIVER_STRING(mem_ctx,
4632                            driver->default_datatype,
4633                            r->default_datatype);
4634
4635         r->previous_names = string_array_from_driver_info(mem_ctx,
4636                                                           driver->previous_names,
4637                                                           cservername);
4638
4639         return WERR_OK;
4640 }
4641
4642 /********************************************************************
4643  * fill a spoolss_DriverInfo5 struct
4644  ********************************************************************/
4645
4646 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4647                                         struct spoolss_DriverInfo5 *r,
4648                                         const struct spoolss_DriverInfo8 *driver,
4649                                         const char *servername)
4650 {
4651         const char *cservername = canon_servername(servername);
4652
4653         r->version              = driver->version;
4654
4655         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4656         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4657         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4658         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4659
4660         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4661                                driver->driver_path,
4662                                r->driver_path);
4663
4664         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4665                                driver->data_file,
4666                                r->data_file);
4667
4668         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4669                                driver->config_file,
4670                                r->config_file);
4671
4672         r->driver_attributes    = 0;
4673         r->config_version       = 0;
4674         r->driver_version       = 0;
4675
4676         return WERR_OK;
4677 }
4678 /********************************************************************
4679  * fill a spoolss_DriverInfo6 struct
4680  ********************************************************************/
4681
4682 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4683                                         struct spoolss_DriverInfo6 *r,
4684                                         const struct spoolss_DriverInfo8 *driver,
4685                                         const char *servername)
4686 {
4687         const char *cservername = canon_servername(servername);
4688
4689         r->version              = driver->version;
4690
4691         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4692         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4693         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4694         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4695
4696         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4697                                driver->driver_path,
4698                                r->driver_path);
4699
4700         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4701                                driver->data_file,
4702                                r->data_file);
4703
4704         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4705                                driver->config_file,
4706                                r->config_file);
4707
4708         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4709                                driver->help_file,
4710                                r->help_file);
4711
4712         FILL_DRIVER_STRING(mem_ctx,
4713                            driver->monitor_name,
4714                            r->monitor_name);
4715
4716         FILL_DRIVER_STRING(mem_ctx,
4717                            driver->default_datatype,
4718                            r->default_datatype);
4719
4720         r->dependent_files = string_array_from_driver_info(mem_ctx,
4721                                                            driver->dependent_files,
4722                                                            cservername);
4723         r->previous_names = string_array_from_driver_info(mem_ctx,
4724                                                           driver->previous_names,
4725                                                           cservername);
4726
4727         r->driver_date          = driver->driver_date;
4728         r->driver_version       = driver->driver_version;
4729
4730         FILL_DRIVER_STRING(mem_ctx,
4731                            driver->manufacturer_name,
4732                            r->manufacturer_name);
4733         FILL_DRIVER_STRING(mem_ctx,
4734                            driver->manufacturer_url,
4735                            r->manufacturer_url);
4736         FILL_DRIVER_STRING(mem_ctx,
4737                            driver->hardware_id,
4738                            r->hardware_id);
4739         FILL_DRIVER_STRING(mem_ctx,
4740                            driver->provider,
4741                            r->provider);
4742
4743         return WERR_OK;
4744 }
4745
4746 /********************************************************************
4747  * fill a spoolss_DriverInfo8 struct
4748  ********************************************************************/
4749
4750 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4751                                         struct spoolss_DriverInfo8 *r,
4752                                         const struct spoolss_DriverInfo8 *driver,
4753                                         const char *servername)
4754 {
4755         const char *cservername = canon_servername(servername);
4756
4757         r->version              = driver->version;
4758
4759         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4760         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4761         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4762         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4763
4764         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4765                                driver->driver_path,
4766                                r->driver_path);
4767
4768         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4769                                driver->data_file,
4770                                r->data_file);
4771
4772         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4773                                driver->config_file,
4774                                r->config_file);
4775
4776         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4777                                driver->help_file,
4778                                r->help_file);
4779
4780         FILL_DRIVER_STRING(mem_ctx,
4781                            driver->monitor_name,
4782                            r->monitor_name);
4783
4784         FILL_DRIVER_STRING(mem_ctx,
4785                            driver->default_datatype,
4786                            r->default_datatype);
4787
4788         r->dependent_files = string_array_from_driver_info(mem_ctx,
4789                                                            driver->dependent_files,
4790                                                            cservername);
4791         r->previous_names = string_array_from_driver_info(mem_ctx,
4792                                                           driver->previous_names,
4793                                                           cservername);
4794
4795         r->driver_date          = driver->driver_date;
4796         r->driver_version       = driver->driver_version;
4797
4798         FILL_DRIVER_STRING(mem_ctx,
4799                            driver->manufacturer_name,
4800                            r->manufacturer_name);
4801         FILL_DRIVER_STRING(mem_ctx,
4802                            driver->manufacturer_url,
4803                            r->manufacturer_url);
4804         FILL_DRIVER_STRING(mem_ctx,
4805                            driver->hardware_id,
4806                            r->hardware_id);
4807         FILL_DRIVER_STRING(mem_ctx,
4808                            driver->provider,
4809                            r->provider);
4810
4811         FILL_DRIVER_STRING(mem_ctx,
4812                            driver->print_processor,
4813                            r->print_processor);
4814         FILL_DRIVER_STRING(mem_ctx,
4815                            driver->vendor_setup,
4816                            r->vendor_setup);
4817
4818         r->color_profiles = string_array_from_driver_info(mem_ctx,
4819                                                           driver->color_profiles,
4820                                                           cservername);
4821
4822         FILL_DRIVER_STRING(mem_ctx,
4823                            driver->inf_path,
4824                            r->inf_path);
4825
4826         r->printer_driver_attributes    = driver->printer_driver_attributes;
4827
4828         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4829                                                                     driver->core_driver_dependencies,
4830                                                                     cservername);
4831
4832         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4833         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4834
4835         return WERR_OK;
4836 }
4837
4838 #if 0 /* disabled until marshalling issues are resolved - gd */
4839 /********************************************************************
4840  ********************************************************************/
4841
4842 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4843                                           struct spoolss_DriverFileInfo *r,
4844                                           const char *cservername,
4845                                           const char *file_name,
4846                                           enum spoolss_DriverFileType file_type,
4847                                           uint32_t file_version)
4848 {
4849         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4850                                           cservername, file_name);
4851         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4852         r->file_type    = file_type;
4853         r->file_version = file_version;
4854
4855         return WERR_OK;
4856 }
4857
4858 /********************************************************************
4859  ********************************************************************/
4860
4861 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4862                                                  const struct spoolss_DriverInfo8 *driver,
4863                                                  const char *cservername,
4864                                                  struct spoolss_DriverFileInfo **info_p,
4865                                                  uint32_t *count_p)
4866 {
4867         struct spoolss_DriverFileInfo *info = NULL;
4868         uint32_t count = 0;
4869         WERROR result;
4870         uint32_t i;
4871
4872         *info_p = NULL;
4873         *count_p = 0;
4874
4875         if (strlen(driver->driver_path)) {
4876                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4877                                             struct spoolss_DriverFileInfo,
4878                                             count + 1);
4879                 W_ERROR_HAVE_NO_MEMORY(info);
4880                 result = fill_spoolss_DriverFileInfo(info,
4881                                                      &info[count],
4882                                                      cservername,
4883                                                      driver->driver_path,
4884                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4885                                                      0);
4886                 W_ERROR_NOT_OK_RETURN(result);
4887                 count++;
4888         }
4889
4890         if (strlen(driver->config_file)) {
4891                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4892                                             struct spoolss_DriverFileInfo,
4893                                             count + 1);
4894                 W_ERROR_HAVE_NO_MEMORY(info);
4895                 result = fill_spoolss_DriverFileInfo(info,
4896                                                      &info[count],
4897                                                      cservername,
4898                                                      driver->config_file,
4899                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4900                                                      0);
4901                 W_ERROR_NOT_OK_RETURN(result);
4902                 count++;
4903         }
4904
4905         if (strlen(driver->data_file)) {
4906                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4907                                             struct spoolss_DriverFileInfo,
4908                                             count + 1);
4909                 W_ERROR_HAVE_NO_MEMORY(info);
4910                 result = fill_spoolss_DriverFileInfo(info,
4911                                                      &info[count],
4912                                                      cservername,
4913                                                      driver->data_file,
4914                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4915                                                      0);
4916                 W_ERROR_NOT_OK_RETURN(result);
4917                 count++;
4918         }
4919
4920         if (strlen(driver->help_file)) {
4921                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4922                                             struct spoolss_DriverFileInfo,
4923                                             count + 1);
4924                 W_ERROR_HAVE_NO_MEMORY(info);
4925                 result = fill_spoolss_DriverFileInfo(info,
4926                                                      &info[count],
4927                                                      cservername,
4928                                                      driver->help_file,
4929                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4930                                                      0);
4931                 W_ERROR_NOT_OK_RETURN(result);
4932                 count++;
4933         }
4934
4935         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4936                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4937                                             struct spoolss_DriverFileInfo,
4938                                             count + 1);
4939                 W_ERROR_HAVE_NO_MEMORY(info);
4940                 result = fill_spoolss_DriverFileInfo(info,
4941                                                      &info[count],
4942                                                      cservername,
4943                                                      driver->dependent_files[i],
4944                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4945                                                      0);
4946                 W_ERROR_NOT_OK_RETURN(result);
4947                 count++;
4948         }
4949
4950         *info_p = info;
4951         *count_p = count;
4952
4953         return WERR_OK;
4954 }
4955
4956 /********************************************************************
4957  * fill a spoolss_DriverInfo101 struct
4958  ********************************************************************/
4959
4960 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4961                                           struct spoolss_DriverInfo101 *r,
4962                                           const struct spoolss_DriverInfo8 *driver,
4963                                           const char *servername)
4964 {
4965         const char *cservername = canon_servername(servername);
4966         WERROR result;
4967
4968         r->version              = driver->version;
4969
4970         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4971         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4972         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4973         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4974
4975         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4976                                                     cservername,
4977                                                     &r->file_info,
4978                                                     &r->file_count);
4979         if (!W_ERROR_IS_OK(result)) {
4980                 return result;
4981         }
4982
4983         FILL_DRIVER_STRING(mem_ctx,
4984                            driver->monitor_name,
4985                            r->monitor_name);
4986
4987         FILL_DRIVER_STRING(mem_ctx,
4988                            driver->default_datatype,
4989                            r->default_datatype);
4990
4991         r->previous_names = string_array_from_driver_info(mem_ctx,
4992                                                           driver->previous_names,
4993                                                           cservername);
4994         r->driver_date          = driver->driver_date;
4995         r->driver_version       = driver->driver_version;
4996
4997         FILL_DRIVER_STRING(mem_ctx,
4998                            driver->manufacturer_name,
4999                            r->manufacturer_name);
5000         FILL_DRIVER_STRING(mem_ctx,
5001                            driver->manufacturer_url,
5002                            r->manufacturer_url);
5003         FILL_DRIVER_STRING(mem_ctx,
5004                            driver->hardware_id,
5005                            r->hardware_id);
5006         FILL_DRIVER_STRING(mem_ctx,
5007                            driver->provider,
5008                            r->provider);
5009
5010         return WERR_OK;
5011 }
5012 #endif
5013 /********************************************************************
5014  ********************************************************************/
5015
5016 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5017                                                   uint32_t level,
5018                                                   union spoolss_DriverInfo *r,
5019                                                   int snum,
5020                                                   const char *servername,
5021                                                   const char *architecture,
5022                                                   uint32_t version)
5023 {
5024         NT_PRINTER_INFO_LEVEL *printer = NULL;
5025         struct spoolss_DriverInfo8 *driver;
5026         WERROR result;
5027
5028         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5029
5030         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5031                 win_errstr(result)));
5032
5033         if (!W_ERROR_IS_OK(result)) {
5034                 return WERR_INVALID_PRINTER_NAME;
5035         }
5036
5037         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5038                                       architecture, version);
5039
5040         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5041                 win_errstr(result)));
5042
5043         if (!W_ERROR_IS_OK(result)) {
5044                 /*
5045                  * Is this a W2k client ?
5046                  */
5047
5048                 if (version < 3) {
5049                         free_a_printer(&printer, 2);
5050                         return WERR_UNKNOWN_PRINTER_DRIVER;
5051                 }
5052
5053                 /* Yes - try again with a WinNT driver. */
5054                 version = 2;
5055                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5056                                               architecture, version);
5057                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5058                         win_errstr(result)));
5059                 if (!W_ERROR_IS_OK(result)) {
5060                         free_a_printer(&printer, 2);
5061                         return WERR_UNKNOWN_PRINTER_DRIVER;
5062                 }
5063         }
5064
5065         switch (level) {
5066         case 1:
5067                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5068                 break;
5069         case 2:
5070                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5071                 break;
5072         case 3:
5073                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5074                 break;
5075         case 4:
5076                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5077                 break;
5078         case 5:
5079                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5080                 break;
5081         case 6:
5082                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5083                 break;
5084         case 8:
5085                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5086                 break;
5087 #if 0 /* disabled until marshalling issues are resolved - gd */
5088         case 101:
5089                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5090                 break;
5091 #endif
5092         default:
5093                 result = WERR_UNKNOWN_LEVEL;
5094                 break;
5095         }
5096
5097         free_a_printer(&printer, 2);
5098         free_a_printer_driver(driver);
5099
5100         return result;
5101 }
5102
5103 /****************************************************************
5104  _spoolss_GetPrinterDriver2
5105 ****************************************************************/
5106
5107 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5108                                   struct spoolss_GetPrinterDriver2 *r)
5109 {
5110         Printer_entry *printer;
5111         WERROR result;
5112
5113         const char *servername;
5114         int snum;
5115
5116         /* that's an [in out] buffer */
5117
5118         if (!r->in.buffer && (r->in.offered != 0)) {
5119                 return WERR_INVALID_PARAM;
5120         }
5121
5122         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5123
5124         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5125                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5126                 return WERR_INVALID_PRINTER_NAME;
5127         }
5128
5129         *r->out.needed = 0;
5130         *r->out.server_major_version = 0;
5131         *r->out.server_minor_version = 0;
5132
5133         servername = get_server_name(printer);
5134
5135         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5136                 return WERR_BADFID;
5137         }
5138
5139         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5140                                                      r->out.info, snum,
5141                                                      servername,
5142                                                      r->in.architecture,
5143                                                      r->in.client_major_version);
5144         if (!W_ERROR_IS_OK(result)) {
5145                 TALLOC_FREE(r->out.info);
5146                 return result;
5147         }
5148
5149         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5150                                                r->out.info, r->in.level);
5151         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5152
5153         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5154 }
5155
5156
5157 /****************************************************************
5158  _spoolss_StartPagePrinter
5159 ****************************************************************/
5160
5161 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5162                                  struct spoolss_StartPagePrinter *r)
5163 {
5164         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5165
5166         if (!Printer) {
5167                 DEBUG(3,("_spoolss_StartPagePrinter: "
5168                         "Error in startpageprinter printer handle\n"));
5169                 return WERR_BADFID;
5170         }
5171
5172         Printer->page_started = true;
5173         return WERR_OK;
5174 }
5175
5176 /****************************************************************
5177  _spoolss_EndPagePrinter
5178 ****************************************************************/
5179
5180 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5181                                struct spoolss_EndPagePrinter *r)
5182 {
5183         int snum;
5184
5185         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5186
5187         if (!Printer) {
5188                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5189                         OUR_HANDLE(r->in.handle)));
5190                 return WERR_BADFID;
5191         }
5192
5193         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5194                 return WERR_BADFID;
5195
5196         Printer->page_started = false;
5197         print_job_endpage(snum, Printer->jobid);
5198
5199         return WERR_OK;
5200 }
5201
5202 /****************************************************************
5203  _spoolss_StartDocPrinter
5204 ****************************************************************/
5205
5206 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5207                                 struct spoolss_StartDocPrinter *r)
5208 {
5209         struct spoolss_DocumentInfo1 *info_1;
5210         int snum;
5211         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5212
5213         if (!Printer) {
5214                 DEBUG(2,("_spoolss_StartDocPrinter: "
5215                         "Invalid handle (%s:%u:%u)\n",
5216                         OUR_HANDLE(r->in.handle)));
5217                 return WERR_BADFID;
5218         }
5219
5220         if (r->in.level != 1) {
5221                 return WERR_UNKNOWN_LEVEL;
5222         }
5223
5224         info_1 = r->in.info.info1;
5225
5226         /*
5227          * a nice thing with NT is it doesn't listen to what you tell it.
5228          * when asked to send _only_ RAW datas, it tries to send datas
5229          * in EMF format.
5230          *
5231          * So I add checks like in NT Server ...
5232          */
5233
5234         if (info_1->datatype) {
5235                 if (strcmp(info_1->datatype, "RAW") != 0) {
5236                         *r->out.job_id = 0;
5237                         return WERR_INVALID_DATATYPE;
5238                 }
5239         }
5240
5241         /* get the share number of the printer */
5242         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5243                 return WERR_BADFID;
5244         }
5245
5246         Printer->jobid = print_job_start(p->server_info, snum,
5247                                          info_1->document_name,
5248                                          Printer->nt_devmode);
5249
5250         /* An error occured in print_job_start() so return an appropriate
5251            NT error code. */
5252
5253         if (Printer->jobid == -1) {
5254                 return map_werror_from_unix(errno);
5255         }
5256
5257         Printer->document_started = true;
5258         *r->out.job_id = Printer->jobid;
5259
5260         return WERR_OK;
5261 }
5262
5263 /****************************************************************
5264  _spoolss_EndDocPrinter
5265 ****************************************************************/
5266
5267 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5268                               struct spoolss_EndDocPrinter *r)
5269 {
5270         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5271         int snum;
5272
5273         if (!Printer) {
5274                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5275                         OUR_HANDLE(r->in.handle)));
5276                 return WERR_BADFID;
5277         }
5278
5279         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5280                 return WERR_BADFID;
5281         }
5282
5283         Printer->document_started = false;
5284         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5285         /* error codes unhandled so far ... */
5286
5287         return WERR_OK;
5288 }
5289
5290 /****************************************************************
5291  _spoolss_WritePrinter
5292 ****************************************************************/
5293
5294 WERROR _spoolss_WritePrinter(pipes_struct *p,
5295                              struct spoolss_WritePrinter *r)
5296 {
5297         ssize_t buffer_written;
5298         int snum;
5299         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5300
5301         if (!Printer) {
5302                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5303                         OUR_HANDLE(r->in.handle)));
5304                 *r->out.num_written = r->in._data_size;
5305                 return WERR_BADFID;
5306         }
5307
5308         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5309                 return WERR_BADFID;
5310
5311         buffer_written = print_job_write(snum, Printer->jobid,
5312                                                    (const char *)r->in.data.data,
5313                                                    (SMB_OFF_T)-1,
5314                                                    (size_t)r->in._data_size);
5315         if (buffer_written == (ssize_t)-1) {
5316                 *r->out.num_written = 0;
5317                 if (errno == ENOSPC)
5318                         return WERR_NO_SPOOL_SPACE;
5319                 else
5320                         return WERR_ACCESS_DENIED;
5321         }
5322
5323         *r->out.num_written = r->in._data_size;
5324
5325         return WERR_OK;
5326 }
5327
5328 /********************************************************************
5329  * api_spoolss_getprinter
5330  * called from the spoolss dispatcher
5331  *
5332  ********************************************************************/
5333
5334 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5335                               pipes_struct *p)
5336 {
5337         int snum;
5338         WERROR errcode = WERR_BADFUNC;
5339         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5340
5341         if (!Printer) {
5342                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5343                         OUR_HANDLE(handle)));
5344                 return WERR_BADFID;
5345         }
5346
5347         if (!get_printer_snum(p, handle, &snum, NULL))
5348                 return WERR_BADFID;
5349
5350         switch (command) {
5351         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5352                 errcode = print_queue_pause(p->server_info, snum);
5353                 break;
5354         case SPOOLSS_PRINTER_CONTROL_RESUME:
5355         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5356                 errcode = print_queue_resume(p->server_info, snum);
5357                 break;
5358         case SPOOLSS_PRINTER_CONTROL_PURGE:
5359                 errcode = print_queue_purge(p->server_info, snum);
5360                 break;
5361         default:
5362                 return WERR_UNKNOWN_LEVEL;
5363         }
5364
5365         return errcode;
5366 }
5367
5368
5369 /****************************************************************
5370  _spoolss_AbortPrinter
5371  * From MSDN: "Deletes printer's spool file if printer is configured
5372  * for spooling"
5373 ****************************************************************/
5374
5375 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5376                              struct spoolss_AbortPrinter *r)
5377 {
5378         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5379         int             snum;
5380         WERROR          errcode = WERR_OK;
5381
5382         if (!Printer) {
5383                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5384                         OUR_HANDLE(r->in.handle)));
5385                 return WERR_BADFID;
5386         }
5387
5388         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5389                 return WERR_BADFID;
5390
5391         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5392
5393         return errcode;
5394 }
5395
5396 /********************************************************************
5397  * called by spoolss_api_setprinter
5398  * when updating a printer description
5399  ********************************************************************/
5400
5401 static WERROR update_printer_sec(struct policy_handle *handle,
5402                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5403 {
5404         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5405         WERROR result;
5406         int snum;
5407
5408         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5409
5410         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5411                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5412                          OUR_HANDLE(handle)));
5413
5414                 result = WERR_BADFID;
5415                 goto done;
5416         }
5417
5418         if (!secdesc_ctr) {
5419                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5420                 result = WERR_INVALID_PARAM;
5421                 goto done;
5422         }
5423
5424         /* Check the user has permissions to change the security
5425            descriptor.  By experimentation with two NT machines, the user
5426            requires Full Access to the printer to change security
5427            information. */
5428
5429         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5430                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5431                 result = WERR_ACCESS_DENIED;
5432                 goto done;
5433         }
5434
5435         /* NT seems to like setting the security descriptor even though
5436            nothing may have actually changed. */
5437
5438         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5439                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5440                 result = WERR_BADFID;
5441                 goto done;
5442         }
5443
5444         if (DEBUGLEVEL >= 10) {
5445                 SEC_ACL *the_acl;
5446                 int i;
5447
5448                 the_acl = old_secdesc_ctr->sd->dacl;
5449                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5450                            PRINTERNAME(snum), the_acl->num_aces));
5451
5452                 for (i = 0; i < the_acl->num_aces; i++) {
5453                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5454                                            &the_acl->aces[i].trustee),
5455                                   the_acl->aces[i].access_mask));
5456                 }
5457
5458                 the_acl = secdesc_ctr->sd->dacl;
5459
5460                 if (the_acl) {
5461                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5462                                    PRINTERNAME(snum), the_acl->num_aces));
5463
5464                         for (i = 0; i < the_acl->num_aces; i++) {
5465                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5466                                                    &the_acl->aces[i].trustee),
5467                                            the_acl->aces[i].access_mask));
5468                         }
5469                 } else {
5470                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5471                 }
5472         }
5473
5474         new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5475         if (!new_secdesc_ctr) {
5476                 result = WERR_NOMEM;
5477                 goto done;
5478         }
5479
5480         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5481                 result = WERR_OK;
5482                 goto done;
5483         }
5484
5485         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5486
5487  done:
5488
5489         return result;
5490 }
5491
5492 /********************************************************************
5493  Canonicalize printer info from a client
5494
5495  ATTN: It does not matter what we set the servername to hear
5496  since we do the necessary work in get_a_printer() to set it to
5497  the correct value based on what the client sent in the
5498  _spoolss_open_printer_ex().
5499  ********************************************************************/
5500
5501 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5502 {
5503         fstring printername;
5504         const char *p;
5505
5506         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5507                 "portname=%s drivername=%s comment=%s location=%s\n",
5508                 info->servername, info->printername, info->sharename,
5509                 info->portname, info->drivername, info->comment, info->location));
5510
5511         /* we force some elements to "correct" values */
5512         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5513         fstrcpy(info->sharename, lp_servicename(snum));
5514
5515         /* check to see if we allow printername != sharename */
5516
5517         if ( lp_force_printername(snum) ) {
5518                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5519                         global_myname(), info->sharename );
5520         } else {
5521
5522                 /* make sure printername is in \\server\printername format */
5523
5524                 fstrcpy( printername, info->printername );
5525                 p = printername;
5526                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5527                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5528                                 p++;
5529                 }
5530
5531                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5532                          global_myname(), p );
5533         }
5534
5535         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5536         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5537
5538
5539
5540         return true;
5541 }
5542
5543 /****************************************************************************
5544 ****************************************************************************/
5545
5546 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5547 {
5548         char *cmd = lp_addport_cmd();
5549         char *command = NULL;
5550         int ret;
5551         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5552         bool is_print_op = false;
5553
5554         if ( !*cmd ) {
5555                 return WERR_ACCESS_DENIED;
5556         }
5557
5558         command = talloc_asprintf(ctx,
5559                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5560         if (!command) {
5561                 return WERR_NOMEM;
5562         }
5563
5564         if ( token )
5565                 is_print_op = user_has_privileges( token, &se_printop );
5566
5567         DEBUG(10,("Running [%s]\n", command));
5568
5569         /********* BEGIN SePrintOperatorPrivilege **********/
5570
5571         if ( is_print_op )
5572                 become_root();
5573
5574         ret = smbrun(command, NULL);
5575
5576         if ( is_print_op )
5577                 unbecome_root();
5578
5579         /********* END SePrintOperatorPrivilege **********/
5580
5581         DEBUGADD(10,("returned [%d]\n", ret));
5582
5583         TALLOC_FREE(command);
5584
5585         if ( ret != 0 ) {
5586                 return WERR_ACCESS_DENIED;
5587         }
5588
5589         return WERR_OK;
5590 }
5591
5592 /****************************************************************************
5593 ****************************************************************************/
5594
5595 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5596 {
5597         char *cmd = lp_addprinter_cmd();
5598         char **qlines;
5599         char *command = NULL;
5600         int numlines;
5601         int ret;
5602         int fd;
5603         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5604         bool is_print_op = false;
5605         char *remote_machine = talloc_strdup(ctx, "%m");
5606
5607         if (!remote_machine) {
5608                 return false;
5609         }
5610         remote_machine = talloc_sub_basic(ctx,
5611                                 current_user_info.smb_name,
5612                                 current_user_info.domain,
5613                                 remote_machine);
5614         if (!remote_machine) {
5615                 return false;
5616         }
5617
5618         command = talloc_asprintf(ctx,
5619                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5620                         cmd, printer->info_2->printername, printer->info_2->sharename,
5621                         printer->info_2->portname, printer->info_2->drivername,
5622                         printer->info_2->location, printer->info_2->comment, remote_machine);
5623         if (!command) {
5624                 return false;
5625         }
5626
5627         if ( token )
5628                 is_print_op = user_has_privileges( token, &se_printop );
5629
5630         DEBUG(10,("Running [%s]\n", command));
5631
5632         /********* BEGIN SePrintOperatorPrivilege **********/
5633
5634         if ( is_print_op )
5635                 become_root();
5636
5637         if ( (ret = smbrun(command, &fd)) == 0 ) {
5638                 /* Tell everyone we updated smb.conf. */
5639                 message_send_all(smbd_messaging_context(),
5640                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5641         }
5642
5643         if ( is_print_op )
5644                 unbecome_root();
5645
5646         /********* END SePrintOperatorPrivilege **********/
5647
5648         DEBUGADD(10,("returned [%d]\n", ret));
5649
5650         TALLOC_FREE(command);
5651         TALLOC_FREE(remote_machine);
5652
5653         if ( ret != 0 ) {
5654                 if (fd != -1)
5655                         close(fd);
5656                 return false;
5657         }
5658
5659         /* reload our services immediately */
5660         become_root();
5661         reload_services(false);
5662         unbecome_root();
5663
5664         numlines = 0;
5665         /* Get lines and convert them back to dos-codepage */
5666         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5667         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5668         close(fd);
5669
5670         /* Set the portname to what the script says the portname should be. */
5671         /* but don't require anything to be return from the script exit a good error code */
5672
5673         if (numlines) {
5674                 /* Set the portname to what the script says the portname should be. */
5675                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5676                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5677         }
5678
5679         TALLOC_FREE(qlines);
5680         return true;
5681 }
5682
5683
5684 /********************************************************************
5685  * Called by spoolss_api_setprinter
5686  * when updating a printer description.
5687  ********************************************************************/
5688
5689 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5690                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5691                              struct spoolss_DeviceMode *devmode)
5692 {
5693         int snum;
5694         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5695         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5696         WERROR result;
5697         DATA_BLOB buffer;
5698         fstring asc_buffer;
5699
5700         DEBUG(8,("update_printer\n"));
5701
5702         result = WERR_OK;
5703
5704         if (!Printer) {
5705                 result = WERR_BADFID;
5706                 goto done;
5707         }
5708
5709         if (!get_printer_snum(p, handle, &snum, NULL)) {
5710                 result = WERR_BADFID;
5711                 goto done;
5712         }
5713
5714         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5715             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5716                 result = WERR_BADFID;
5717                 goto done;
5718         }
5719
5720         DEBUGADD(8,("Converting info_2 struct\n"));
5721
5722         /*
5723          * convert_printer_info converts the incoming
5724          * info from the client and overwrites the info
5725          * just read from the tdb in the pointer 'printer'.
5726          */
5727
5728         if (!convert_printer_info(info_ctr, printer)) {
5729                 result =  WERR_NOMEM;
5730                 goto done;
5731         }
5732
5733         if (devmode) {
5734                 /* we have a valid devmode
5735                    convert it and link it*/
5736
5737                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5738                 if (!convert_devicemode(printer->info_2->printername, devmode,
5739                                         &printer->info_2->devmode)) {
5740                         result =  WERR_NOMEM;
5741                         goto done;
5742                 }
5743         }
5744
5745         /* Do sanity check on the requested changes for Samba */
5746
5747         if (!check_printer_ok(printer->info_2, snum)) {
5748                 result = WERR_INVALID_PARAM;
5749                 goto done;
5750         }
5751
5752         /* FIXME!!! If the driver has changed we really should verify that
5753            it is installed before doing much else   --jerry */
5754
5755         /* Check calling user has permission to update printer description */
5756
5757         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5758                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5759                 result = WERR_ACCESS_DENIED;
5760                 goto done;
5761         }
5762
5763         /* Call addprinter hook */
5764         /* Check changes to see if this is really needed */
5765
5766         if ( *lp_addprinter_cmd()
5767                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5768                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5769                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5770                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5771         {
5772                 /* add_printer_hook() will call reload_services() */
5773
5774                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5775                                        printer) ) {
5776                         result = WERR_ACCESS_DENIED;
5777                         goto done;
5778                 }
5779         }
5780
5781         /*
5782          * When a *new* driver is bound to a printer, the drivername is used to
5783          * lookup previously saved driver initialization info, which is then
5784          * bound to the printer, simulating what happens in the Windows arch.
5785          */
5786         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5787         {
5788                 if (!set_driver_init(printer, 2))
5789                 {
5790                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5791                                 printer->info_2->drivername));
5792                 }
5793
5794                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5795                         printer->info_2->drivername));
5796
5797                 notify_printer_driver(snum, printer->info_2->drivername);
5798         }
5799
5800         /*
5801          * flag which changes actually occured.  This is a small subset of
5802          * all the possible changes.  We also have to update things in the
5803          * DsSpooler key.
5804          */
5805
5806         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5807                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->comment);
5808                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5809                         REG_SZ, buffer.data, buffer.length);
5810
5811                 notify_printer_comment(snum, printer->info_2->comment);
5812         }
5813
5814         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5815                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->sharename);
5816                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5817                         REG_SZ, buffer.data, buffer.length);
5818
5819                 notify_printer_sharename(snum, printer->info_2->sharename);
5820         }
5821
5822         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5823                 char *pname;
5824
5825                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5826                         pname++;
5827                 else
5828                         pname = printer->info_2->printername;
5829
5830
5831                 push_reg_sz(talloc_tos(), NULL, &buffer, pname);
5832                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5833                         REG_SZ, buffer.data, buffer.length);
5834
5835                 notify_printer_printername( snum, pname );
5836         }
5837
5838         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5839                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->portname);
5840                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5841                         REG_SZ, buffer.data, buffer.length);
5842
5843                 notify_printer_port(snum, printer->info_2->portname);
5844         }
5845
5846         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5847                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->location);
5848                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5849                         REG_SZ, buffer.data, buffer.length);
5850
5851                 notify_printer_location(snum, printer->info_2->location);
5852         }
5853
5854         /* here we need to update some more DsSpooler keys */
5855         /* uNCName, serverName, shortServerName */
5856
5857         push_reg_sz(talloc_tos(), NULL, &buffer, global_myname());
5858         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5859                 REG_SZ, buffer.data, buffer.length);
5860         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5861                 REG_SZ, buffer.data, buffer.length);
5862
5863         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5864                  global_myname(), printer->info_2->sharename );
5865         push_reg_sz(talloc_tos(), NULL, &buffer, asc_buffer);
5866         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5867                 REG_SZ, buffer.data, buffer.length);
5868
5869         /* Update printer info */
5870         result = mod_a_printer(printer, 2);
5871
5872 done:
5873         free_a_printer(&printer, 2);
5874         free_a_printer(&old_printer, 2);
5875
5876
5877         return result;
5878 }
5879
5880 /****************************************************************************
5881 ****************************************************************************/
5882 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5883                                            struct policy_handle *handle,
5884                                            struct spoolss_SetPrinterInfo7 *info7)
5885 {
5886 #ifdef HAVE_ADS
5887         int snum;
5888         Printer_entry *Printer;
5889
5890         if ( lp_security() != SEC_ADS ) {
5891                 return WERR_UNKNOWN_LEVEL;
5892         }
5893
5894         Printer = find_printer_index_by_hnd(p, handle);
5895
5896         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5897
5898         if (!Printer)
5899                 return WERR_BADFID;
5900
5901         if (!get_printer_snum(p, handle, &snum, NULL))
5902                 return WERR_BADFID;
5903
5904         nt_printer_publish(Printer, snum, info7->action);
5905
5906         return WERR_OK;
5907 #else
5908         return WERR_UNKNOWN_LEVEL;
5909 #endif
5910 }
5911
5912 /********************************************************************
5913  ********************************************************************/
5914
5915 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5916                                      struct spoolss_DeviceMode *devmode)
5917 {
5918         int snum;
5919         NT_PRINTER_INFO_LEVEL *printer = NULL;
5920         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5921         WERROR result;
5922
5923         DEBUG(8,("update_printer_devmode\n"));
5924
5925         result = WERR_OK;
5926
5927         if (!Printer) {
5928                 result = WERR_BADFID;
5929                 goto done;
5930         }
5931
5932         if (!get_printer_snum(p, handle, &snum, NULL)) {
5933                 result = WERR_BADFID;
5934                 goto done;
5935         }
5936
5937         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5938                 result = WERR_BADFID;
5939                 goto done;
5940         }
5941
5942         if (devmode) {
5943                 /* we have a valid devmode
5944                    convert it and link it*/
5945
5946                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5947                 if (!convert_devicemode(printer->info_2->printername, devmode,
5948                                         &printer->info_2->devmode)) {
5949                         result =  WERR_NOMEM;
5950                         goto done;
5951                 }
5952         }
5953
5954         /* Check calling user has permission to update printer description */
5955
5956         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5957                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5958                 result = WERR_ACCESS_DENIED;
5959                 goto done;
5960         }
5961
5962
5963         /* Update printer info */
5964         result = mod_a_printer(printer, 2);
5965
5966 done:
5967         free_a_printer(&printer, 2);
5968
5969         return result;
5970 }
5971
5972
5973 /****************************************************************
5974  _spoolss_SetPrinter
5975 ****************************************************************/
5976
5977 WERROR _spoolss_SetPrinter(pipes_struct *p,
5978                            struct spoolss_SetPrinter *r)
5979 {
5980         WERROR result;
5981
5982         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5983
5984         if (!Printer) {
5985                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5986                         OUR_HANDLE(r->in.handle)));
5987                 return WERR_BADFID;
5988         }
5989
5990         /* check the level */
5991         switch (r->in.info_ctr->level) {
5992                 case 0:
5993                         return control_printer(r->in.handle, r->in.command, p);
5994                 case 2:
5995                         result = update_printer(p, r->in.handle,
5996                                                 r->in.info_ctr,
5997                                                 r->in.devmode_ctr->devmode);
5998                         if (!W_ERROR_IS_OK(result))
5999                                 return result;
6000                         if (r->in.secdesc_ctr->sd)
6001                                 result = update_printer_sec(r->in.handle, p,
6002                                                             r->in.secdesc_ctr);
6003                         return result;
6004                 case 3:
6005                         return update_printer_sec(r->in.handle, p,
6006                                                   r->in.secdesc_ctr);
6007                 case 7:
6008                         return publish_or_unpublish_printer(p, r->in.handle,
6009                                                             r->in.info_ctr->info.info7);
6010                 case 8:
6011                         return update_printer_devmode(p, r->in.handle,
6012                                                       r->in.devmode_ctr->devmode);
6013                 default:
6014                         return WERR_UNKNOWN_LEVEL;
6015         }
6016 }
6017
6018 /****************************************************************
6019  _spoolss_FindClosePrinterNotify
6020 ****************************************************************/
6021
6022 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6023                                        struct spoolss_FindClosePrinterNotify *r)
6024 {
6025         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6026
6027         if (!Printer) {
6028                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6029                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6030                 return WERR_BADFID;
6031         }
6032
6033         if (Printer->notify.client_connected == true) {
6034                 int snum = -1;
6035
6036                 if ( Printer->printer_type == SPLHND_SERVER)
6037                         snum = -1;
6038                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6039                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6040                         return WERR_BADFID;
6041
6042                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6043         }
6044
6045         Printer->notify.flags=0;
6046         Printer->notify.options=0;
6047         Printer->notify.localmachine[0]='\0';
6048         Printer->notify.printerlocal=0;
6049         TALLOC_FREE(Printer->notify.option);
6050         Printer->notify.client_connected = false;
6051
6052         return WERR_OK;
6053 }
6054
6055 /****************************************************************
6056  _spoolss_AddJob
6057 ****************************************************************/
6058
6059 WERROR _spoolss_AddJob(pipes_struct *p,
6060                        struct spoolss_AddJob *r)
6061 {
6062         if (!r->in.buffer && (r->in.offered != 0)) {
6063                 return WERR_INVALID_PARAM;
6064         }
6065
6066         /* this is what a NT server returns for AddJob. AddJob must fail on
6067          * non-local printers */
6068
6069         if (r->in.level != 1) {
6070                 return WERR_UNKNOWN_LEVEL;
6071         }
6072
6073         return WERR_INVALID_PARAM;
6074 }
6075
6076 /****************************************************************************
6077 fill_job_info1
6078 ****************************************************************************/
6079
6080 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6081                              struct spoolss_JobInfo1 *r,
6082                              const print_queue_struct *queue,
6083                              int position, int snum,
6084                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6085 {
6086         struct tm *t;
6087
6088         t = gmtime(&queue->time);
6089
6090         r->job_id               = queue->job;
6091
6092         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6093         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6094         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6095         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6096         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6097         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6098         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6099         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6100         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6101         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6102         r->text_status          = talloc_strdup(mem_ctx, "");
6103         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6104
6105         r->status               = nt_printj_status(queue->status);
6106         r->priority             = queue->priority;
6107         r->position             = position;
6108         r->total_pages          = queue->page_count;
6109         r->pages_printed        = 0; /* ??? */
6110
6111         init_systemtime(&r->submitted, t);
6112
6113         return WERR_OK;
6114 }
6115
6116 /****************************************************************************
6117 fill_job_info2
6118 ****************************************************************************/
6119
6120 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6121                              struct spoolss_JobInfo2 *r,
6122                              const print_queue_struct *queue,
6123                              int position, int snum,
6124                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6125                              struct spoolss_DeviceMode *devmode)
6126 {
6127         struct tm *t;
6128
6129         t = gmtime(&queue->time);
6130
6131         r->job_id               = queue->job;
6132
6133         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6134         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6135         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6136         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6137         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6138         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6139         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6140         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6141         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6142         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6143         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6144         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6145         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6146         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6147         r->parameters           = talloc_strdup(mem_ctx, "");
6148         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6149         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6150         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6151
6152         r->devmode              = devmode;
6153
6154         r->text_status          = talloc_strdup(mem_ctx, "");
6155         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6156
6157         r->secdesc              = NULL;
6158
6159         r->status               = nt_printj_status(queue->status);
6160         r->priority             = queue->priority;
6161         r->position             = position;
6162         r->start_time           = 0;
6163         r->until_time           = 0;
6164         r->total_pages          = queue->page_count;
6165         r->size                 = queue->size;
6166         init_systemtime(&r->submitted, t);
6167         r->time                 = 0;
6168         r->pages_printed        = 0; /* ??? */
6169
6170         return WERR_OK;
6171 }
6172
6173 /****************************************************************************
6174 fill_job_info3
6175 ****************************************************************************/
6176
6177 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6178                              struct spoolss_JobInfo3 *r,
6179                              const print_queue_struct *queue,
6180                              const print_queue_struct *next_queue,
6181                              int position, int snum,
6182                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6183 {
6184         r->job_id               = queue->job;
6185         r->next_job_id          = 0;
6186         if (next_queue) {
6187                 r->next_job_id  = next_queue->job;
6188         }
6189         r->reserved             = 0;
6190
6191         return WERR_OK;
6192 }
6193
6194 /****************************************************************************
6195  Enumjobs at level 1.
6196 ****************************************************************************/
6197
6198 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6199                               const print_queue_struct *queue,
6200                               uint32_t num_queues, int snum,
6201                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6202                               union spoolss_JobInfo **info_p,
6203                               uint32_t *count)
6204 {
6205         union spoolss_JobInfo *info;
6206         int i;
6207         WERROR result = WERR_OK;
6208
6209         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6210         W_ERROR_HAVE_NO_MEMORY(info);
6211
6212         *count = num_queues;
6213
6214         for (i=0; i<*count; i++) {
6215                 result = fill_job_info1(info,
6216                                         &info[i].info1,
6217                                         &queue[i],
6218                                         i,
6219                                         snum,
6220                                         ntprinter);
6221                 if (!W_ERROR_IS_OK(result)) {
6222                         goto out;
6223                 }
6224         }
6225
6226  out:
6227         if (!W_ERROR_IS_OK(result)) {
6228                 TALLOC_FREE(info);
6229                 *count = 0;
6230                 return result;
6231         }
6232
6233         *info_p = info;
6234
6235         return WERR_OK;
6236 }
6237
6238 /****************************************************************************
6239  Enumjobs at level 2.
6240 ****************************************************************************/
6241
6242 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6243                               const print_queue_struct *queue,
6244                               uint32_t num_queues, int snum,
6245                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6246                               union spoolss_JobInfo **info_p,
6247                               uint32_t *count)
6248 {
6249         union spoolss_JobInfo *info;
6250         int i;
6251         WERROR result = WERR_OK;
6252
6253         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6254         W_ERROR_HAVE_NO_MEMORY(info);
6255
6256         *count = num_queues;
6257
6258         for (i=0; i<*count; i++) {
6259
6260                 struct spoolss_DeviceMode *devmode;
6261
6262                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6263                 if (!devmode) {
6264                         result = WERR_NOMEM;
6265                         goto out;
6266                 }
6267
6268                 result = fill_job_info2(info,
6269                                         &info[i].info2,
6270                                         &queue[i],
6271                                         i,
6272                                         snum,
6273                                         ntprinter,
6274                                         devmode);
6275                 if (!W_ERROR_IS_OK(result)) {
6276                         goto out;
6277                 }
6278         }
6279
6280  out:
6281         if (!W_ERROR_IS_OK(result)) {
6282                 TALLOC_FREE(info);
6283                 *count = 0;
6284                 return result;
6285         }
6286
6287         *info_p = info;
6288
6289         return WERR_OK;
6290 }
6291
6292 /****************************************************************************
6293  Enumjobs at level 3.
6294 ****************************************************************************/
6295
6296 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6297                               const print_queue_struct *queue,
6298                               uint32_t num_queues, int snum,
6299                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6300                               union spoolss_JobInfo **info_p,
6301                               uint32_t *count)
6302 {
6303         union spoolss_JobInfo *info;
6304         int i;
6305         WERROR result = WERR_OK;
6306
6307         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6308         W_ERROR_HAVE_NO_MEMORY(info);
6309
6310         *count = num_queues;
6311
6312         for (i=0; i<*count; i++) {
6313                 const print_queue_struct *next_queue = NULL;
6314
6315                 if (i+1 < *count) {
6316                         next_queue = &queue[i+1];
6317                 }
6318
6319                 result = fill_job_info3(info,
6320                                         &info[i].info3,
6321                                         &queue[i],
6322                                         next_queue,
6323                                         i,
6324                                         snum,
6325                                         ntprinter);
6326                 if (!W_ERROR_IS_OK(result)) {
6327                         goto out;
6328                 }
6329         }
6330
6331  out:
6332         if (!W_ERROR_IS_OK(result)) {
6333                 TALLOC_FREE(info);
6334                 *count = 0;
6335                 return result;
6336         }
6337
6338         *info_p = info;
6339
6340         return WERR_OK;
6341 }
6342
6343 /****************************************************************
6344  _spoolss_EnumJobs
6345 ****************************************************************/
6346
6347 WERROR _spoolss_EnumJobs(pipes_struct *p,
6348                          struct spoolss_EnumJobs *r)
6349 {
6350         WERROR result;
6351         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6352         int snum;
6353         print_status_struct prt_status;
6354         print_queue_struct *queue = NULL;
6355         uint32_t count;
6356
6357         /* that's an [in out] buffer */
6358
6359         if (!r->in.buffer && (r->in.offered != 0)) {
6360                 return WERR_INVALID_PARAM;
6361         }
6362
6363         DEBUG(4,("_spoolss_EnumJobs\n"));
6364
6365         *r->out.needed = 0;
6366         *r->out.count = 0;
6367         *r->out.info = NULL;
6368
6369         /* lookup the printer snum and tdb entry */
6370
6371         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6372                 return WERR_BADFID;
6373         }
6374
6375         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6376         if (!W_ERROR_IS_OK(result)) {
6377                 return result;
6378         }
6379
6380         count = print_queue_status(snum, &queue, &prt_status);
6381         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6382                 count, prt_status.status, prt_status.message));
6383
6384         if (count == 0) {
6385                 SAFE_FREE(queue);
6386                 free_a_printer(&ntprinter, 2);
6387                 return WERR_OK;
6388         }
6389
6390         switch (r->in.level) {
6391         case 1:
6392                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6393                                          ntprinter, r->out.info, r->out.count);
6394                 break;
6395         case 2:
6396                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6397                                          ntprinter, r->out.info, r->out.count);
6398                 break;
6399         case 3:
6400                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6401                                          ntprinter, r->out.info, r->out.count);
6402                 break;
6403         default:
6404                 result = WERR_UNKNOWN_LEVEL;
6405                 break;
6406         }
6407
6408         SAFE_FREE(queue);
6409         free_a_printer(&ntprinter, 2);
6410
6411         if (!W_ERROR_IS_OK(result)) {
6412                 return result;
6413         }
6414
6415         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6416                                                      spoolss_EnumJobs, NULL,
6417                                                      *r->out.info, r->in.level,
6418                                                      *r->out.count);
6419         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6420         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6421
6422         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6423 }
6424
6425 /****************************************************************
6426  _spoolss_ScheduleJob
6427 ****************************************************************/
6428
6429 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6430                             struct spoolss_ScheduleJob *r)
6431 {
6432         return WERR_OK;
6433 }
6434
6435 /****************************************************************
6436 ****************************************************************/
6437
6438 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6439                                const char *printer_name,
6440                                uint32_t job_id,
6441                                struct spoolss_SetJobInfo1 *r)
6442 {
6443         char *old_doc_name;
6444
6445         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6446                 return WERR_BADFID;
6447         }
6448
6449         if (strequal(old_doc_name, r->document_name)) {
6450                 return WERR_OK;
6451         }
6452
6453         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6454                 return WERR_BADFID;
6455         }
6456
6457         return WERR_OK;
6458 }
6459
6460 /****************************************************************
6461  _spoolss_SetJob
6462 ****************************************************************/
6463
6464 WERROR _spoolss_SetJob(pipes_struct *p,
6465                        struct spoolss_SetJob *r)
6466 {
6467         int snum;
6468         WERROR errcode = WERR_BADFUNC;
6469
6470         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6471                 return WERR_BADFID;
6472         }
6473
6474         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6475                 return WERR_INVALID_PRINTER_NAME;
6476         }
6477
6478         switch (r->in.command) {
6479         case SPOOLSS_JOB_CONTROL_CANCEL:
6480         case SPOOLSS_JOB_CONTROL_DELETE:
6481                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6482                         errcode = WERR_OK;
6483                 }
6484                 break;
6485         case SPOOLSS_JOB_CONTROL_PAUSE:
6486                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6487                         errcode = WERR_OK;
6488                 }
6489                 break;
6490         case SPOOLSS_JOB_CONTROL_RESTART:
6491         case SPOOLSS_JOB_CONTROL_RESUME:
6492                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6493                         errcode = WERR_OK;
6494                 }
6495                 break;
6496         case 0:
6497                 errcode = WERR_OK;
6498                 break;
6499         default:
6500                 return WERR_UNKNOWN_LEVEL;
6501         }
6502
6503         if (!W_ERROR_IS_OK(errcode)) {
6504                 return errcode;
6505         }
6506
6507         if (r->in.ctr == NULL) {
6508                 return errcode;
6509         }
6510
6511         switch (r->in.ctr->level) {
6512         case 1:
6513                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6514                                            r->in.job_id,
6515                                            r->in.ctr->info.info1);
6516                 break;
6517         case 2:
6518         case 3:
6519         case 4:
6520         default:
6521                 return WERR_UNKNOWN_LEVEL;
6522         }
6523
6524         return errcode;
6525 }
6526
6527 /****************************************************************************
6528  Enumerates all printer drivers by level and architecture.
6529 ****************************************************************************/
6530
6531 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6532                                                        const char *servername,
6533                                                        const char *architecture,
6534                                                        uint32_t level,
6535                                                        union spoolss_DriverInfo **info_p,
6536                                                        uint32_t *count_p)
6537 {
6538         int i;
6539         int ndrivers;
6540         uint32_t version;
6541         fstring *list = NULL;
6542         struct spoolss_DriverInfo8 *driver;
6543         union spoolss_DriverInfo *info = NULL;
6544         uint32_t count = 0;
6545         WERROR result = WERR_OK;
6546
6547         *count_p = 0;
6548         *info_p = NULL;
6549
6550         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6551                 list = NULL;
6552                 ndrivers = get_ntdrivers(&list, architecture, version);
6553                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6554                         ndrivers, architecture, version));
6555
6556                 if (ndrivers == -1) {
6557                         result = WERR_NOMEM;
6558                         goto out;
6559                 }
6560
6561                 if (ndrivers != 0) {
6562                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6563                                                     union spoolss_DriverInfo,
6564                                                     count + ndrivers);
6565                         if (!info) {
6566                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6567                                         "failed to enlarge driver info buffer!\n"));
6568                                 result = WERR_NOMEM;
6569                                 goto out;
6570                         }
6571                 }
6572
6573                 for (i=0; i<ndrivers; i++) {
6574                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6575                         ZERO_STRUCT(driver);
6576                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6577                                                       architecture, version);
6578                         if (!W_ERROR_IS_OK(result)) {
6579                                 goto out;
6580                         }
6581
6582                         switch (level) {
6583                         case 1:
6584                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6585                                                                    driver, servername);
6586                                 break;
6587                         case 2:
6588                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6589                                                                    driver, servername);
6590                                 break;
6591                         case 3:
6592                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6593                                                                    driver, servername);
6594                                 break;
6595                         case 4:
6596                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6597                                                                    driver, servername);
6598                                 break;
6599                         case 5:
6600                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6601                                                                    driver, servername);
6602                                 break;
6603                         case 6:
6604                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6605                                                                    driver, servername);
6606                                 break;
6607                         case 8:
6608                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6609                                                                    driver, servername);
6610                                 break;
6611                         default:
6612                                 result = WERR_UNKNOWN_LEVEL;
6613                                 break;
6614                         }
6615
6616                         free_a_printer_driver(driver);
6617
6618                         if (!W_ERROR_IS_OK(result)) {
6619                                 goto out;
6620                         }
6621                 }
6622
6623                 count += ndrivers;
6624                 SAFE_FREE(list);
6625         }
6626
6627  out:
6628         SAFE_FREE(list);
6629
6630         if (!W_ERROR_IS_OK(result)) {
6631                 TALLOC_FREE(info);
6632                 return result;
6633         }
6634
6635         *info_p = info;
6636         *count_p = count;
6637
6638         return WERR_OK;
6639 }
6640
6641 /****************************************************************************
6642  Enumerates all printer drivers by level.
6643 ****************************************************************************/
6644
6645 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6646                                        const char *servername,
6647                                        const char *architecture,
6648                                        uint32_t level,
6649                                        union spoolss_DriverInfo **info_p,
6650                                        uint32_t *count_p)
6651 {
6652         uint32_t a,i;
6653         WERROR result = WERR_OK;
6654
6655         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6656
6657                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6658
6659                         union spoolss_DriverInfo *info = NULL;
6660                         uint32_t count = 0;
6661
6662                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6663                                                                           servername,
6664                                                                           archi_table[a].long_archi,
6665                                                                           level,
6666                                                                           &info,
6667                                                                           &count);
6668                         if (!W_ERROR_IS_OK(result)) {
6669                                 continue;
6670                         }
6671
6672                         for (i=0; i < count; i++) {
6673                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6674                                              info[i], info_p, count_p);
6675                         }
6676                 }
6677
6678                 return result;
6679         }
6680
6681         return enumprinterdrivers_level_by_architecture(mem_ctx,
6682                                                         servername,
6683                                                         architecture,
6684                                                         level,
6685                                                         info_p,
6686                                                         count_p);
6687 }
6688
6689 /****************************************************************
6690  _spoolss_EnumPrinterDrivers
6691 ****************************************************************/
6692
6693 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6694                                    struct spoolss_EnumPrinterDrivers *r)
6695 {
6696         const char *cservername;
6697         WERROR result;
6698
6699         /* that's an [in out] buffer */
6700
6701         if (!r->in.buffer && (r->in.offered != 0)) {
6702                 return WERR_INVALID_PARAM;
6703         }
6704
6705         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6706
6707         *r->out.needed = 0;
6708         *r->out.count = 0;
6709         *r->out.info = NULL;
6710
6711         cservername = canon_servername(r->in.server);
6712
6713         if (!is_myname_or_ipaddr(cservername)) {
6714                 return WERR_UNKNOWN_PRINTER_DRIVER;
6715         }
6716
6717         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6718                                           r->in.environment,
6719                                           r->in.level,
6720                                           r->out.info,
6721                                           r->out.count);
6722         if (!W_ERROR_IS_OK(result)) {
6723                 return result;
6724         }
6725
6726         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6727                                                      spoolss_EnumPrinterDrivers, NULL,
6728                                                      *r->out.info, r->in.level,
6729                                                      *r->out.count);
6730         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6731         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6732
6733         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6734 }
6735
6736 /****************************************************************************
6737 ****************************************************************************/
6738
6739 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6740                                struct spoolss_FormInfo1 *r,
6741                                const nt_forms_struct *form)
6742 {
6743         r->form_name    = talloc_strdup(mem_ctx, form->name);
6744         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6745
6746         r->flags        = form->flag;
6747         r->size.width   = form->width;
6748         r->size.height  = form->length;
6749         r->area.left    = form->left;
6750         r->area.top     = form->top;
6751         r->area.right   = form->right;
6752         r->area.bottom  = form->bottom;
6753
6754         return WERR_OK;
6755 }
6756
6757 /****************************************************************
6758  spoolss_enumforms_level1
6759 ****************************************************************/
6760
6761 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6762                                        const nt_forms_struct *builtin_forms,
6763                                        uint32_t num_builtin_forms,
6764                                        const nt_forms_struct *user_forms,
6765                                        uint32_t num_user_forms,
6766                                        union spoolss_FormInfo **info_p,
6767                                        uint32_t *count)
6768 {
6769         union spoolss_FormInfo *info;
6770         WERROR result = WERR_OK;
6771         int i;
6772
6773         *count = num_builtin_forms + num_user_forms;
6774
6775         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6776         W_ERROR_HAVE_NO_MEMORY(info);
6777
6778         /* construct the list of form structures */
6779         for (i=0; i<num_builtin_forms; i++) {
6780                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6781                 result = fill_form_info_1(info, &info[i].info1,
6782                                           &builtin_forms[i]);
6783                 if (!W_ERROR_IS_OK(result)) {
6784                         goto out;
6785                 }
6786         }
6787
6788         for (i=0; i<num_user_forms; i++) {
6789                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6790                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6791                                           &user_forms[i]);
6792                 if (!W_ERROR_IS_OK(result)) {
6793                         goto out;
6794                 }
6795         }
6796
6797  out:
6798         if (!W_ERROR_IS_OK(result)) {
6799                 TALLOC_FREE(info);
6800                 *count = 0;
6801                 return result;
6802         }
6803
6804         *info_p = info;
6805
6806         return WERR_OK;
6807 }
6808
6809 /****************************************************************
6810  _spoolss_EnumForms
6811 ****************************************************************/
6812
6813 WERROR _spoolss_EnumForms(pipes_struct *p,
6814                           struct spoolss_EnumForms *r)
6815 {
6816         WERROR result;
6817         nt_forms_struct *user_forms = NULL;
6818         nt_forms_struct *builtin_forms = NULL;
6819         uint32_t num_user_forms;
6820         uint32_t num_builtin_forms;
6821
6822         *r->out.count = 0;
6823         *r->out.needed = 0;
6824         *r->out.info = NULL;
6825
6826         /* that's an [in out] buffer */
6827
6828         if (!r->in.buffer && (r->in.offered != 0) ) {
6829                 return WERR_INVALID_PARAM;
6830         }
6831
6832         DEBUG(4,("_spoolss_EnumForms\n"));
6833         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6834         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6835
6836         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6837         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6838         num_user_forms = get_ntforms(&user_forms);
6839         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6840
6841         if (num_user_forms + num_builtin_forms == 0) {
6842                 SAFE_FREE(builtin_forms);
6843                 SAFE_FREE(user_forms);
6844                 return WERR_NO_MORE_ITEMS;
6845         }
6846
6847         switch (r->in.level) {
6848         case 1:
6849                 result = spoolss_enumforms_level1(p->mem_ctx,
6850                                                   builtin_forms,
6851                                                   num_builtin_forms,
6852                                                   user_forms,
6853                                                   num_user_forms,
6854                                                   r->out.info,
6855                                                   r->out.count);
6856                 break;
6857         default:
6858                 result = WERR_UNKNOWN_LEVEL;
6859                 break;
6860         }
6861
6862         SAFE_FREE(user_forms);
6863         SAFE_FREE(builtin_forms);
6864
6865         if (!W_ERROR_IS_OK(result)) {
6866                 return result;
6867         }
6868
6869         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6870                                                      spoolss_EnumForms, NULL,
6871                                                      *r->out.info, r->in.level,
6872                                                      *r->out.count);
6873         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6874         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6875
6876         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6877 }
6878
6879 /****************************************************************
6880 ****************************************************************/
6881
6882 static WERROR find_form_byname(const char *name,
6883                                nt_forms_struct *form)
6884 {
6885         nt_forms_struct *list = NULL;
6886         int num_forms = 0, i = 0;
6887
6888         if (get_a_builtin_ntform_by_string(name, form)) {
6889                 return WERR_OK;
6890         }
6891
6892         num_forms = get_ntforms(&list);
6893         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6894
6895         if (num_forms == 0) {
6896                 return WERR_BADFID;
6897         }
6898
6899         /* Check if the requested name is in the list of form structures */
6900         for (i = 0; i < num_forms; i++) {
6901
6902                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6903
6904                 if (strequal(name, list[i].name)) {
6905                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6906                         *form = list[i];
6907                         SAFE_FREE(list);
6908                         return WERR_OK;
6909                 }
6910         }
6911
6912         SAFE_FREE(list);
6913
6914         return WERR_BADFID;
6915 }
6916
6917 /****************************************************************
6918  _spoolss_GetForm
6919 ****************************************************************/
6920
6921 WERROR _spoolss_GetForm(pipes_struct *p,
6922                         struct spoolss_GetForm *r)
6923 {
6924         WERROR result;
6925         nt_forms_struct form;
6926
6927         /* that's an [in out] buffer */
6928
6929         if (!r->in.buffer && (r->in.offered != 0)) {
6930                 return WERR_INVALID_PARAM;
6931         }
6932
6933         DEBUG(4,("_spoolss_GetForm\n"));
6934         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6935         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6936
6937         result = find_form_byname(r->in.form_name, &form);
6938         if (!W_ERROR_IS_OK(result)) {
6939                 TALLOC_FREE(r->out.info);
6940                 return result;
6941         }
6942
6943         switch (r->in.level) {
6944         case 1:
6945                 result = fill_form_info_1(p->mem_ctx,
6946                                           &r->out.info->info1,
6947                                           &form);
6948                 break;
6949
6950         default:
6951                 result = WERR_UNKNOWN_LEVEL;
6952                 break;
6953         }
6954
6955         if (!W_ERROR_IS_OK(result)) {
6956                 TALLOC_FREE(r->out.info);
6957                 return result;
6958         }
6959
6960         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6961                                                r->out.info, r->in.level);
6962         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6963
6964         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6965 }
6966
6967 /****************************************************************************
6968 ****************************************************************************/
6969
6970 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6971                           struct spoolss_PortInfo1 *r,
6972                           const char *name)
6973 {
6974         r->port_name = talloc_strdup(mem_ctx, name);
6975         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6976
6977         return WERR_OK;
6978 }
6979
6980 /****************************************************************************
6981  TODO: This probably needs distinguish between TCP/IP and Local ports
6982  somehow.
6983 ****************************************************************************/
6984
6985 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6986                           struct spoolss_PortInfo2 *r,
6987                           const char *name)
6988 {
6989         r->port_name = talloc_strdup(mem_ctx, name);
6990         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6991
6992         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6993         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6994
6995         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6996         W_ERROR_HAVE_NO_MEMORY(r->description);
6997
6998         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6999         r->reserved = 0;
7000
7001         return WERR_OK;
7002 }
7003
7004
7005 /****************************************************************************
7006  wrapper around the enumer ports command
7007 ****************************************************************************/
7008
7009 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7010 {
7011         char *cmd = lp_enumports_cmd();
7012         char **qlines = NULL;
7013         char *command = NULL;
7014         int numlines;
7015         int ret;
7016         int fd;
7017
7018         *count = 0;
7019         *lines = NULL;
7020
7021         /* if no hook then just fill in the default port */
7022
7023         if ( !*cmd ) {
7024                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7025                         return WERR_NOMEM;
7026                 }
7027                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7028                         TALLOC_FREE(qlines);
7029                         return WERR_NOMEM;
7030                 }
7031                 qlines[1] = NULL;
7032                 numlines = 1;
7033         }
7034         else {
7035                 /* we have a valid enumport command */
7036
7037                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7038                 if (!command) {
7039                         return WERR_NOMEM;
7040                 }
7041
7042                 DEBUG(10,("Running [%s]\n", command));
7043                 ret = smbrun(command, &fd);
7044                 DEBUG(10,("Returned [%d]\n", ret));
7045                 TALLOC_FREE(command);
7046                 if (ret != 0) {
7047                         if (fd != -1) {
7048                                 close(fd);
7049                         }
7050                         return WERR_ACCESS_DENIED;
7051                 }
7052
7053                 numlines = 0;
7054                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7055                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7056                 close(fd);
7057         }
7058
7059         *count = numlines;
7060         *lines = qlines;
7061
7062         return WERR_OK;
7063 }
7064
7065 /****************************************************************************
7066  enumports level 1.
7067 ****************************************************************************/
7068
7069 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7070                                 union spoolss_PortInfo **info_p,
7071                                 uint32_t *count)
7072 {
7073         union spoolss_PortInfo *info = NULL;
7074         int i=0;
7075         WERROR result = WERR_OK;
7076         char **qlines = NULL;
7077         int numlines = 0;
7078
7079         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7080         if (!W_ERROR_IS_OK(result)) {
7081                 goto out;
7082         }
7083
7084         if (numlines) {
7085                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7086                 if (!info) {
7087                         DEBUG(10,("Returning WERR_NOMEM\n"));
7088                         result = WERR_NOMEM;
7089                         goto out;
7090                 }
7091
7092                 for (i=0; i<numlines; i++) {
7093                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7094                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7095                         if (!W_ERROR_IS_OK(result)) {
7096                                 goto out;
7097                         }
7098                 }
7099         }
7100         TALLOC_FREE(qlines);
7101
7102 out:
7103         if (!W_ERROR_IS_OK(result)) {
7104                 TALLOC_FREE(info);
7105                 TALLOC_FREE(qlines);
7106                 *count = 0;
7107                 *info_p = NULL;
7108                 return result;
7109         }
7110
7111         *info_p = info;
7112         *count = numlines;
7113
7114         return WERR_OK;
7115 }
7116
7117 /****************************************************************************
7118  enumports level 2.
7119 ****************************************************************************/
7120
7121 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7122                                 union spoolss_PortInfo **info_p,
7123                                 uint32_t *count)
7124 {
7125         union spoolss_PortInfo *info = NULL;
7126         int i=0;
7127         WERROR result = WERR_OK;
7128         char **qlines = NULL;
7129         int numlines = 0;
7130
7131         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7132         if (!W_ERROR_IS_OK(result)) {
7133                 goto out;
7134         }
7135
7136         if (numlines) {
7137                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7138                 if (!info) {
7139                         DEBUG(10,("Returning WERR_NOMEM\n"));
7140                         result = WERR_NOMEM;
7141                         goto out;
7142                 }
7143
7144                 for (i=0; i<numlines; i++) {
7145                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7146                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7147                         if (!W_ERROR_IS_OK(result)) {
7148                                 goto out;
7149                         }
7150                 }
7151         }
7152         TALLOC_FREE(qlines);
7153
7154 out:
7155         if (!W_ERROR_IS_OK(result)) {
7156                 TALLOC_FREE(info);
7157                 TALLOC_FREE(qlines);
7158                 *count = 0;
7159                 *info_p = NULL;
7160                 return result;
7161         }
7162
7163         *info_p = info;
7164         *count = numlines;
7165
7166         return WERR_OK;
7167 }
7168
7169 /****************************************************************
7170  _spoolss_EnumPorts
7171 ****************************************************************/
7172
7173 WERROR _spoolss_EnumPorts(pipes_struct *p,
7174                           struct spoolss_EnumPorts *r)
7175 {
7176         WERROR result;
7177
7178         /* that's an [in out] buffer */
7179
7180         if (!r->in.buffer && (r->in.offered != 0)) {
7181                 return WERR_INVALID_PARAM;
7182         }
7183
7184         DEBUG(4,("_spoolss_EnumPorts\n"));
7185
7186         *r->out.count = 0;
7187         *r->out.needed = 0;
7188         *r->out.info = NULL;
7189
7190         switch (r->in.level) {
7191         case 1:
7192                 result = enumports_level_1(p->mem_ctx, r->out.info,
7193                                            r->out.count);
7194                 break;
7195         case 2:
7196                 result = enumports_level_2(p->mem_ctx, r->out.info,
7197                                            r->out.count);
7198                 break;
7199         default:
7200                 return WERR_UNKNOWN_LEVEL;
7201         }
7202
7203         if (!W_ERROR_IS_OK(result)) {
7204                 return result;
7205         }
7206
7207         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7208                                                      spoolss_EnumPorts, NULL,
7209                                                      *r->out.info, r->in.level,
7210                                                      *r->out.count);
7211         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7212         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7213
7214         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7215 }
7216
7217 /****************************************************************************
7218 ****************************************************************************/
7219
7220 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7221                                            const char *server,
7222                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7223                                            struct spoolss_DeviceMode *devmode,
7224                                            struct security_descriptor *sec_desc,
7225                                            struct spoolss_UserLevelCtr *user_ctr,
7226                                            struct policy_handle *handle)
7227 {
7228         NT_PRINTER_INFO_LEVEL *printer = NULL;
7229         fstring name;
7230         int     snum;
7231         WERROR err = WERR_OK;
7232
7233         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7234                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7235                 return WERR_NOMEM;
7236         }
7237
7238         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7239         if (!convert_printer_info(info_ctr, printer)) {
7240                 free_a_printer(&printer, 2);
7241                 return WERR_NOMEM;
7242         }
7243
7244         /* samba does not have a concept of local, non-shared printers yet, so
7245          * make sure we always setup sharename - gd */
7246         if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7247                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7248                         "no sharename has been set, setting printername %s as sharename\n",
7249                         printer->info_2->printername));
7250                 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7251         }
7252
7253         /* check to see if the printer already exists */
7254
7255         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7256                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7257                         printer->info_2->sharename));
7258                 free_a_printer(&printer, 2);
7259                 return WERR_PRINTER_ALREADY_EXISTS;
7260         }
7261
7262         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7263                 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7264                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7265                                 printer->info_2->printername));
7266                         free_a_printer(&printer, 2);
7267                         return WERR_PRINTER_ALREADY_EXISTS;
7268                 }
7269         }
7270
7271         /* validate printer info struct */
7272         if (!info_ctr->info.info2->printername ||
7273             strlen(info_ctr->info.info2->printername) == 0) {
7274                 free_a_printer(&printer,2);
7275                 return WERR_INVALID_PRINTER_NAME;
7276         }
7277         if (!info_ctr->info.info2->portname ||
7278             strlen(info_ctr->info.info2->portname) == 0) {
7279                 free_a_printer(&printer,2);
7280                 return WERR_UNKNOWN_PORT;
7281         }
7282         if (!info_ctr->info.info2->drivername ||
7283             strlen(info_ctr->info.info2->drivername) == 0) {
7284                 free_a_printer(&printer,2);
7285                 return WERR_UNKNOWN_PRINTER_DRIVER;
7286         }
7287         if (!info_ctr->info.info2->printprocessor ||
7288             strlen(info_ctr->info.info2->printprocessor) == 0) {
7289                 free_a_printer(&printer,2);
7290                 return WERR_UNKNOWN_PRINTPROCESSOR;
7291         }
7292
7293         /* FIXME!!!  smbd should check to see if the driver is installed before
7294            trying to add a printer like this  --jerry */
7295
7296         if (*lp_addprinter_cmd() ) {
7297                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7298                                        printer) ) {
7299                         free_a_printer(&printer,2);
7300                         return WERR_ACCESS_DENIED;
7301                 }
7302         } else {
7303                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7304                         "smb.conf parameter \"addprinter command\" is defined. This"
7305                         "parameter must exist for this call to succeed\n",
7306                         printer->info_2->sharename ));
7307         }
7308
7309         /* use our primary netbios name since get_a_printer() will convert
7310            it to what the client expects on a case by case basis */
7311
7312         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7313              printer->info_2->sharename);
7314
7315
7316         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7317                 free_a_printer(&printer,2);
7318                 return WERR_ACCESS_DENIED;
7319         }
7320
7321         /* you must be a printer admin to add a new printer */
7322         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7323                 free_a_printer(&printer,2);
7324                 return WERR_ACCESS_DENIED;
7325         }
7326
7327         /*
7328          * Do sanity check on the requested changes for Samba.
7329          */
7330
7331         if (!check_printer_ok(printer->info_2, snum)) {
7332                 free_a_printer(&printer,2);
7333                 return WERR_INVALID_PARAM;
7334         }
7335
7336         /*
7337          * When a printer is created, the drivername bound to the printer is used
7338          * to lookup previously saved driver initialization info, which is then
7339          * bound to the new printer, simulating what happens in the Windows arch.
7340          */
7341
7342         if (!devmode)
7343         {
7344                 set_driver_init(printer, 2);
7345         }
7346         else
7347         {
7348                 /* A valid devmode was included, convert and link it
7349                 */
7350                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7351
7352                 if (!convert_devicemode(printer->info_2->printername, devmode,
7353                                         &printer->info_2->devmode)) {
7354                         return  WERR_NOMEM;
7355                 }
7356         }
7357
7358         /* write the ASCII on disk */
7359         err = mod_a_printer(printer, 2);
7360         if (!W_ERROR_IS_OK(err)) {
7361                 free_a_printer(&printer,2);
7362                 return err;
7363         }
7364
7365         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7366                 /* Handle open failed - remove addition. */
7367                 del_a_printer(printer->info_2->sharename);
7368                 free_a_printer(&printer,2);
7369                 ZERO_STRUCTP(handle);
7370                 return WERR_ACCESS_DENIED;
7371         }
7372
7373         update_c_setprinter(false);
7374         free_a_printer(&printer,2);
7375
7376         return WERR_OK;
7377 }
7378
7379 /****************************************************************
7380  _spoolss_AddPrinterEx
7381 ****************************************************************/
7382
7383 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7384                              struct spoolss_AddPrinterEx *r)
7385 {
7386         switch (r->in.info_ctr->level) {
7387         case 1:
7388                 /* we don't handle yet */
7389                 /* but I know what to do ... */
7390                 return WERR_UNKNOWN_LEVEL;
7391         case 2:
7392                 return spoolss_addprinterex_level_2(p, r->in.server,
7393                                                     r->in.info_ctr,
7394                                                     r->in.devmode_ctr->devmode,
7395                                                     r->in.secdesc_ctr->sd,
7396                                                     r->in.userlevel_ctr,
7397                                                     r->out.handle);
7398         default:
7399                 return WERR_UNKNOWN_LEVEL;
7400         }
7401 }
7402
7403 /****************************************************************
7404  _spoolss_AddPrinter
7405 ****************************************************************/
7406
7407 WERROR _spoolss_AddPrinter(pipes_struct *p,
7408                            struct spoolss_AddPrinter *r)
7409 {
7410         struct spoolss_AddPrinterEx a;
7411         struct spoolss_UserLevelCtr userlevel_ctr;
7412
7413         ZERO_STRUCT(userlevel_ctr);
7414
7415         userlevel_ctr.level = 1;
7416
7417         a.in.server             = r->in.server;
7418         a.in.info_ctr           = r->in.info_ctr;
7419         a.in.devmode_ctr        = r->in.devmode_ctr;
7420         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7421         a.in.userlevel_ctr      = &userlevel_ctr;
7422         a.out.handle            = r->out.handle;
7423
7424         return _spoolss_AddPrinterEx(p, &a);
7425 }
7426
7427 /****************************************************************
7428  _spoolss_AddPrinterDriverEx
7429 ****************************************************************/
7430
7431 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7432                                    struct spoolss_AddPrinterDriverEx *r)
7433 {
7434         WERROR err = WERR_OK;
7435         char *driver_name = NULL;
7436         uint32_t version;
7437         const char *fn;
7438
7439         switch (p->hdr_req.opnum) {
7440                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7441                         fn = "_spoolss_AddPrinterDriver";
7442                         break;
7443                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7444                         fn = "_spoolss_AddPrinterDriverEx";
7445                         break;
7446                 default:
7447                         return WERR_INVALID_PARAM;
7448         }
7449
7450         /*
7451          * we only support the semantics of AddPrinterDriver()
7452          * i.e. only copy files that are newer than existing ones
7453          */
7454
7455         if (r->in.flags == 0) {
7456                 return WERR_INVALID_PARAM;
7457         }
7458
7459         if (r->in.flags != APD_COPY_NEW_FILES) {
7460                 return WERR_ACCESS_DENIED;
7461         }
7462
7463         /* FIXME */
7464         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7465                 /* Clever hack from Martin Zielinski <mz@seh.de>
7466                  * to allow downgrade from level 8 (Vista).
7467                  */
7468                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7469                         r->in.info_ctr->level));
7470                 return WERR_UNKNOWN_LEVEL;
7471         }
7472
7473         DEBUG(5,("Cleaning driver's information\n"));
7474         err = clean_up_driver_struct(p, r->in.info_ctr);
7475         if (!W_ERROR_IS_OK(err))
7476                 goto done;
7477
7478         DEBUG(5,("Moving driver to final destination\n"));
7479         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7480                                                               &err)) ) {
7481                 goto done;
7482         }
7483
7484         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7485                 err = WERR_ACCESS_DENIED;
7486                 goto done;
7487         }
7488
7489         /*
7490          * I think this is where he DrvUpgradePrinter() hook would be
7491          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7492          * server.  Right now, we just need to send ourselves a message
7493          * to update each printer bound to this driver.   --jerry
7494          */
7495
7496         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7497                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7498                         fn, driver_name));
7499         }
7500
7501         /*
7502          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7503          * decide if the driver init data should be deleted. The rules are:
7504          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7505          *  2) delete init data only if there is no 2k/Xp driver
7506          *  3) always delete init data
7507          * The generalized rule is always use init data from the highest order driver.
7508          * It is necessary to follow the driver install by an initialization step to
7509          * finish off this process.
7510         */
7511
7512         switch (version) {
7513                 /*
7514                  * 9x printer driver - never delete init data
7515                 */
7516                 case 0:
7517                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7518                                 fn, driver_name));
7519                         break;
7520
7521                 /*
7522                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7523                  * there is no 2k/Xp driver init data for this driver name.
7524                 */
7525                 case 2:
7526                 {
7527                         struct spoolss_DriverInfo8 *driver1;
7528
7529                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
7530                                 /*
7531                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7532                                 */
7533                                 if (!del_driver_init(driver_name))
7534                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7535                                                 fn, driver_name));
7536                         } else {
7537                                 /*
7538                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7539                                 */
7540                                 free_a_printer_driver(driver1);
7541                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7542                                         fn, driver_name));
7543                         }
7544                 }
7545                 break;
7546
7547                 /*
7548                  * 2k or Xp printer driver - always delete init data
7549                 */
7550                 case 3:
7551                         if (!del_driver_init(driver_name))
7552                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7553                                         fn, driver_name));
7554                         break;
7555
7556                 default:
7557                         DEBUG(0,("%s: invalid level=%d\n", fn,
7558                                 r->in.info_ctr->level));
7559                         break;
7560         }
7561
7562
7563 done:
7564         return err;
7565 }
7566
7567 /****************************************************************
7568  _spoolss_AddPrinterDriver
7569 ****************************************************************/
7570
7571 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7572                                  struct spoolss_AddPrinterDriver *r)
7573 {
7574         struct spoolss_AddPrinterDriverEx a;
7575
7576         switch (r->in.info_ctr->level) {
7577         case 2:
7578         case 3:
7579         case 4:
7580         case 5:
7581                 break;
7582         default:
7583                 return WERR_UNKNOWN_LEVEL;
7584         }
7585
7586         a.in.servername         = r->in.servername;
7587         a.in.info_ctr           = r->in.info_ctr;
7588         a.in.flags              = APD_COPY_NEW_FILES;
7589
7590         return _spoolss_AddPrinterDriverEx(p, &a);
7591 }
7592
7593 /****************************************************************************
7594 ****************************************************************************/
7595
7596 struct _spoolss_paths {
7597         int type;
7598         const char *share;
7599         const char *dir;
7600 };
7601
7602 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7603
7604 static const struct _spoolss_paths spoolss_paths[]= {
7605         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7606         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7607 };
7608
7609 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7610                                           const char *servername,
7611                                           const char *environment,
7612                                           int component,
7613                                           char **path)
7614 {
7615         const char *pservername = NULL;
7616         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7617         const char *short_archi;
7618
7619         *path = NULL;
7620
7621         /* environment may be empty */
7622         if (environment && strlen(environment)) {
7623                 long_archi = environment;
7624         }
7625
7626         /* servername may be empty */
7627         if (servername && strlen(servername)) {
7628                 pservername = canon_servername(servername);
7629
7630                 if (!is_myname_or_ipaddr(pservername)) {
7631                         return WERR_INVALID_PARAM;
7632                 }
7633         }
7634
7635         if (!(short_archi = get_short_archi(long_archi))) {
7636                 return WERR_INVALID_ENVIRONMENT;
7637         }
7638
7639         switch (component) {
7640         case SPOOLSS_PRTPROCS_PATH:
7641         case SPOOLSS_DRIVER_PATH:
7642                 if (pservername) {
7643                         *path = talloc_asprintf(mem_ctx,
7644                                         "\\\\%s\\%s\\%s",
7645                                         pservername,
7646                                         spoolss_paths[component].share,
7647                                         short_archi);
7648                 } else {
7649                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7650                                         SPOOLSS_DEFAULT_SERVER_PATH,
7651                                         spoolss_paths[component].dir,
7652                                         short_archi);
7653                 }
7654                 break;
7655         default:
7656                 return WERR_INVALID_PARAM;
7657         }
7658
7659         if (!*path) {
7660                 return WERR_NOMEM;
7661         }
7662
7663         return WERR_OK;
7664 }
7665
7666 /****************************************************************************
7667 ****************************************************************************/
7668
7669 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7670                                           const char *servername,
7671                                           const char *environment,
7672                                           struct spoolss_DriverDirectoryInfo1 *r)
7673 {
7674         WERROR werr;
7675         char *path = NULL;
7676
7677         werr = compose_spoolss_server_path(mem_ctx,
7678                                            servername,
7679                                            environment,
7680                                            SPOOLSS_DRIVER_PATH,
7681                                            &path);
7682         if (!W_ERROR_IS_OK(werr)) {
7683                 return werr;
7684         }
7685
7686         DEBUG(4,("printer driver directory: [%s]\n", path));
7687
7688         r->directory_name = path;
7689
7690         return WERR_OK;
7691 }
7692
7693 /****************************************************************
7694  _spoolss_GetPrinterDriverDirectory
7695 ****************************************************************/
7696
7697 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7698                                           struct spoolss_GetPrinterDriverDirectory *r)
7699 {
7700         WERROR werror;
7701
7702         /* that's an [in out] buffer */
7703
7704         if (!r->in.buffer && (r->in.offered != 0)) {
7705                 return WERR_INVALID_PARAM;
7706         }
7707
7708         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7709                 r->in.level));
7710
7711         *r->out.needed = 0;
7712
7713         /* r->in.level is ignored */
7714
7715         werror = getprinterdriverdir_level_1(p->mem_ctx,
7716                                              r->in.server,
7717                                              r->in.environment,
7718                                              &r->out.info->info1);
7719         if (!W_ERROR_IS_OK(werror)) {
7720                 TALLOC_FREE(r->out.info);
7721                 return werror;
7722         }
7723
7724         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7725                                                r->out.info, r->in.level);
7726         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7727
7728         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7729 }
7730
7731 /****************************************************************
7732  _spoolss_EnumPrinterData
7733 ****************************************************************/
7734
7735 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7736                                 struct spoolss_EnumPrinterData *r)
7737 {
7738         WERROR result;
7739         struct spoolss_EnumPrinterDataEx r2;
7740         uint32_t count;
7741         struct spoolss_PrinterEnumValues *info, *val = NULL;
7742         uint32_t needed;
7743
7744         r2.in.handle    = r->in.handle;
7745         r2.in.key_name  = "PrinterDriverData";
7746         r2.in.offered   = 0;
7747         r2.out.count    = &count;
7748         r2.out.info     = &info;
7749         r2.out.needed   = &needed;
7750
7751         result = _spoolss_EnumPrinterDataEx(p, &r2);
7752         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7753                 r2.in.offered = needed;
7754                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7755         }
7756         if (!W_ERROR_IS_OK(result)) {
7757                 return result;
7758         }
7759
7760         /*
7761          * The NT machine wants to know the biggest size of value and data
7762          *
7763          * cf: MSDN EnumPrinterData remark section
7764          */
7765
7766         if (!r->in.value_offered && !r->in.data_offered) {
7767                 uint32_t biggest_valuesize = 0;
7768                 uint32_t biggest_datasize = 0;
7769                 int i, name_length;
7770
7771                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7772
7773                 for (i=0; i<count; i++) {
7774
7775                         name_length = strlen(info[i].value_name);
7776                         if (strlen(info[i].value_name) > biggest_valuesize) {
7777                                 biggest_valuesize = name_length;
7778                         }
7779
7780                         if (info[i].data_length > biggest_datasize) {
7781                                 biggest_datasize = info[i].data_length;
7782                         }
7783
7784                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7785                                 biggest_datasize));
7786                 }
7787
7788                 /* the value is an UNICODE string but real_value_size is the length
7789                    in bytes including the trailing 0 */
7790
7791                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7792                 *r->out.data_needed  = biggest_datasize;
7793
7794                 DEBUG(6,("final values: [%d], [%d]\n",
7795                         *r->out.value_needed, *r->out.data_needed));
7796
7797                 return WERR_OK;
7798         }
7799
7800         if (r->in.enum_index < count) {
7801                 val = &info[r->in.enum_index];
7802         }
7803
7804         if (val == NULL) {
7805                 /* out_value should default to "" or else NT4 has
7806                    problems unmarshalling the response */
7807
7808                 if (r->in.value_offered) {
7809                         *r->out.value_needed = 1;
7810                         r->out.value_name = talloc_strdup(r, "");
7811                         if (!r->out.value_name) {
7812                                 return WERR_NOMEM;
7813                         }
7814                 } else {
7815                         r->out.value_name = NULL;
7816                         *r->out.value_needed = 0;
7817                 }
7818
7819                 /* the data is counted in bytes */
7820
7821                 *r->out.data_needed = r->in.data_offered;
7822
7823                 result = WERR_NO_MORE_ITEMS;
7824         } else {
7825                 /*
7826                  * the value is:
7827                  * - counted in bytes in the request
7828                  * - counted in UNICODE chars in the max reply
7829                  * - counted in bytes in the real size
7830                  *
7831                  * take a pause *before* coding not *during* coding
7832                  */
7833
7834                 /* name */
7835                 if (r->in.value_offered) {
7836                         r->out.value_name = talloc_strdup(r, val->value_name);
7837                         if (!r->out.value_name) {
7838                                 return WERR_NOMEM;
7839                         }
7840                         *r->out.value_needed = val->value_name_len;
7841                 } else {
7842                         r->out.value_name = NULL;
7843                         *r->out.value_needed = 0;
7844                 }
7845
7846                 /* type */
7847
7848                 *r->out.type = val->type;
7849
7850                 /* data - counted in bytes */
7851
7852                 /*
7853                  * See the section "Dynamically Typed Query Parameters"
7854                  * in MS-RPRN.
7855                  */
7856
7857                 if (r->out.data && val->data && val->data->data &&
7858                                 val->data_length && r->in.data_offered) {
7859                         memcpy(r->out.data, val->data->data,
7860                                 MIN(val->data_length,r->in.data_offered));
7861                 }
7862
7863                 *r->out.data_needed = val->data_length;
7864
7865                 result = WERR_OK;
7866         }
7867
7868         return result;
7869 }
7870
7871 /****************************************************************
7872  _spoolss_SetPrinterData
7873 ****************************************************************/
7874
7875 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7876                                struct spoolss_SetPrinterData *r)
7877 {
7878         struct spoolss_SetPrinterDataEx r2;
7879
7880         r2.in.handle            = r->in.handle;
7881         r2.in.key_name          = "PrinterDriverData";
7882         r2.in.value_name        = r->in.value_name;
7883         r2.in.type              = r->in.type;
7884         r2.in.data              = r->in.data;
7885         r2.in.offered           = r->in.offered;
7886
7887         return _spoolss_SetPrinterDataEx(p, &r2);
7888 }
7889
7890 /****************************************************************
7891  _spoolss_ResetPrinter
7892 ****************************************************************/
7893
7894 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7895                              struct spoolss_ResetPrinter *r)
7896 {
7897         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7898         int             snum;
7899
7900         DEBUG(5,("_spoolss_ResetPrinter\n"));
7901
7902         /*
7903          * All we do is to check to see if the handle and queue is valid.
7904          * This call really doesn't mean anything to us because we only
7905          * support RAW printing.   --jerry
7906          */
7907
7908         if (!Printer) {
7909                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7910                         OUR_HANDLE(r->in.handle)));
7911                 return WERR_BADFID;
7912         }
7913
7914         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7915                 return WERR_BADFID;
7916
7917
7918         /* blindly return success */
7919         return WERR_OK;
7920 }
7921
7922 /****************************************************************
7923  _spoolss_DeletePrinterData
7924 ****************************************************************/
7925
7926 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7927                                   struct spoolss_DeletePrinterData *r)
7928 {
7929         struct spoolss_DeletePrinterDataEx r2;
7930
7931         r2.in.handle            = r->in.handle;
7932         r2.in.key_name          = "PrinterDriverData";
7933         r2.in.value_name        = r->in.value_name;
7934
7935         return _spoolss_DeletePrinterDataEx(p, &r2);
7936 }
7937
7938 /****************************************************************
7939  _spoolss_AddForm
7940 ****************************************************************/
7941
7942 WERROR _spoolss_AddForm(pipes_struct *p,
7943                         struct spoolss_AddForm *r)
7944 {
7945         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7946         nt_forms_struct tmpForm;
7947         int snum = -1;
7948         WERROR status = WERR_OK;
7949         NT_PRINTER_INFO_LEVEL *printer = NULL;
7950         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7951
7952         int count=0;
7953         nt_forms_struct *list=NULL;
7954         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7955         int i;
7956
7957         DEBUG(5,("_spoolss_AddForm\n"));
7958
7959         if (!Printer) {
7960                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7961                         OUR_HANDLE(r->in.handle)));
7962                 return WERR_BADFID;
7963         }
7964
7965
7966         /* forms can be added on printer or on the print server handle */
7967
7968         if ( Printer->printer_type == SPLHND_PRINTER )
7969         {
7970                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7971                         return WERR_BADFID;
7972
7973                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7974                 if (!W_ERROR_IS_OK(status))
7975                         goto done;
7976         }
7977
7978         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7979            and not a printer admin, then fail */
7980
7981         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7982              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7983              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7984                                           NULL, NULL,
7985                                           p->server_info->ptok,
7986                                           lp_printer_admin(snum))) {
7987                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7988                 status = WERR_ACCESS_DENIED;
7989                 goto done;
7990         }
7991
7992         switch (form->flags) {
7993         case SPOOLSS_FORM_USER:
7994         case SPOOLSS_FORM_BUILTIN:
7995         case SPOOLSS_FORM_PRINTER:
7996                 break;
7997         default:
7998                 status = WERR_INVALID_PARAM;
7999                 goto done;
8000         }
8001
8002         /* can't add if builtin */
8003
8004         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8005                 status = WERR_FILE_EXISTS;
8006                 goto done;
8007         }
8008
8009         count = get_ntforms(&list);
8010
8011         for (i=0; i < count; i++) {
8012                 if (strequal(form->form_name, list[i].name)) {
8013                         status = WERR_FILE_EXISTS;
8014                         goto done;
8015                 }
8016         }
8017
8018         if(!add_a_form(&list, form, &count)) {
8019                 status =  WERR_NOMEM;
8020                 goto done;
8021         }
8022
8023         become_root();
8024         write_ntforms(&list, count);
8025         unbecome_root();
8026
8027         /*
8028          * ChangeID must always be set if this is a printer
8029          */
8030
8031         if ( Printer->printer_type == SPLHND_PRINTER )
8032                 status = mod_a_printer(printer, 2);
8033
8034 done:
8035         if ( printer )
8036                 free_a_printer(&printer, 2);
8037         SAFE_FREE(list);
8038
8039         return status;
8040 }
8041
8042 /****************************************************************
8043  _spoolss_DeleteForm
8044 ****************************************************************/
8045
8046 WERROR _spoolss_DeleteForm(pipes_struct *p,
8047                            struct spoolss_DeleteForm *r)
8048 {
8049         const char *form_name = r->in.form_name;
8050         nt_forms_struct tmpForm;
8051         int count=0;
8052         nt_forms_struct *list=NULL;
8053         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8054         int snum = -1;
8055         WERROR status = WERR_OK;
8056         NT_PRINTER_INFO_LEVEL *printer = NULL;
8057         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8058         bool ret = false;
8059
8060         DEBUG(5,("_spoolss_DeleteForm\n"));
8061
8062         if (!Printer) {
8063                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8064                         OUR_HANDLE(r->in.handle)));
8065                 return WERR_BADFID;
8066         }
8067
8068         /* forms can be deleted on printer of on the print server handle */
8069
8070         if ( Printer->printer_type == SPLHND_PRINTER )
8071         {
8072                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8073                         return WERR_BADFID;
8074
8075                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8076                 if (!W_ERROR_IS_OK(status))
8077                         goto done;
8078         }
8079
8080         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8081              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8082              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8083                                           NULL, NULL,
8084                                           p->server_info->ptok,
8085                                           lp_printer_admin(snum))) {
8086                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8087                 return WERR_ACCESS_DENIED;
8088         }
8089
8090
8091         /* can't delete if builtin */
8092
8093         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8094                 status = WERR_INVALID_PARAM;
8095                 goto done;
8096         }
8097
8098         count = get_ntforms(&list);
8099
8100         become_root();
8101         ret = delete_a_form(&list, form_name, &count, &status);
8102         unbecome_root();
8103         if (ret == false) {
8104                 goto done;
8105         }
8106
8107         /*
8108          * ChangeID must always be set if this is a printer
8109          */
8110
8111         if ( Printer->printer_type == SPLHND_PRINTER )
8112                 status = mod_a_printer(printer, 2);
8113
8114 done:
8115         if ( printer )
8116                 free_a_printer(&printer, 2);
8117         SAFE_FREE(list);
8118
8119         return status;
8120 }
8121
8122 /****************************************************************
8123  _spoolss_SetForm
8124 ****************************************************************/
8125
8126 WERROR _spoolss_SetForm(pipes_struct *p,
8127                         struct spoolss_SetForm *r)
8128 {
8129         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8130         nt_forms_struct tmpForm;
8131         int snum = -1;
8132         WERROR status = WERR_OK;
8133         NT_PRINTER_INFO_LEVEL *printer = NULL;
8134         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8135
8136         int count=0;
8137         nt_forms_struct *list=NULL;
8138         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8139
8140         DEBUG(5,("_spoolss_SetForm\n"));
8141
8142         if (!Printer) {
8143                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8144                         OUR_HANDLE(r->in.handle)));
8145                 return WERR_BADFID;
8146         }
8147
8148         /* forms can be modified on printer of on the print server handle */
8149
8150         if ( Printer->printer_type == SPLHND_PRINTER )
8151         {
8152                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8153                         return WERR_BADFID;
8154
8155                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8156                 if (!W_ERROR_IS_OK(status))
8157                         goto done;
8158         }
8159
8160         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8161            and not a printer admin, then fail */
8162
8163         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8164              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8165              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8166                                           NULL, NULL,
8167                                           p->server_info->ptok,
8168                                           lp_printer_admin(snum))) {
8169                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8170                 status = WERR_ACCESS_DENIED;
8171                 goto done;
8172         }
8173
8174         /* can't set if builtin */
8175         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8176                 status = WERR_INVALID_PARAM;
8177                 goto done;
8178         }
8179
8180         count = get_ntforms(&list);
8181         update_a_form(&list, form, count);
8182         become_root();
8183         write_ntforms(&list, count);
8184         unbecome_root();
8185
8186         /*
8187          * ChangeID must always be set if this is a printer
8188          */
8189
8190         if ( Printer->printer_type == SPLHND_PRINTER )
8191                 status = mod_a_printer(printer, 2);
8192
8193
8194 done:
8195         if ( printer )
8196                 free_a_printer(&printer, 2);
8197         SAFE_FREE(list);
8198
8199         return status;
8200 }
8201
8202 /****************************************************************************
8203  fill_print_processor1
8204 ****************************************************************************/
8205
8206 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8207                                     struct spoolss_PrintProcessorInfo1 *r,
8208                                     const char *print_processor_name)
8209 {
8210         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8211         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8212
8213         return WERR_OK;
8214 }
8215
8216 /****************************************************************************
8217  enumprintprocessors level 1.
8218 ****************************************************************************/
8219
8220 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8221                                           union spoolss_PrintProcessorInfo **info_p,
8222                                           uint32_t *count)
8223 {
8224         union spoolss_PrintProcessorInfo *info;
8225         WERROR result;
8226
8227         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8228         W_ERROR_HAVE_NO_MEMORY(info);
8229
8230         *count = 1;
8231
8232         result = fill_print_processor1(info, &info[0].info1, "winprint");
8233         if (!W_ERROR_IS_OK(result)) {
8234                 goto out;
8235         }
8236
8237  out:
8238         if (!W_ERROR_IS_OK(result)) {
8239                 TALLOC_FREE(info);
8240                 *count = 0;
8241                 return result;
8242         }
8243
8244         *info_p = info;
8245
8246         return WERR_OK;
8247 }
8248
8249 /****************************************************************
8250  _spoolss_EnumPrintProcessors
8251 ****************************************************************/
8252
8253 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8254                                     struct spoolss_EnumPrintProcessors *r)
8255 {
8256         WERROR result;
8257
8258         /* that's an [in out] buffer */
8259
8260         if (!r->in.buffer && (r->in.offered != 0)) {
8261                 return WERR_INVALID_PARAM;
8262         }
8263
8264         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8265
8266         /*
8267          * Enumerate the print processors ...
8268          *
8269          * Just reply with "winprint", to keep NT happy
8270          * and I can use my nice printer checker.
8271          */
8272
8273         *r->out.count = 0;
8274         *r->out.needed = 0;
8275         *r->out.info = NULL;
8276
8277         switch (r->in.level) {
8278         case 1:
8279                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8280                                                      r->out.count);
8281                 break;
8282         default:
8283                 return WERR_UNKNOWN_LEVEL;
8284         }
8285
8286         if (!W_ERROR_IS_OK(result)) {
8287                 return result;
8288         }
8289
8290         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8291                                                      spoolss_EnumPrintProcessors, NULL,
8292                                                      *r->out.info, r->in.level,
8293                                                      *r->out.count);
8294         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8295         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8296
8297         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8298 }
8299
8300 /****************************************************************************
8301  fill_printprocdatatype1
8302 ****************************************************************************/
8303
8304 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8305                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8306                                       const char *name_array)
8307 {
8308         r->name_array = talloc_strdup(mem_ctx, name_array);
8309         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8310
8311         return WERR_OK;
8312 }
8313
8314 /****************************************************************************
8315  enumprintprocdatatypes level 1.
8316 ****************************************************************************/
8317
8318 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8319                                              union spoolss_PrintProcDataTypesInfo **info_p,
8320                                              uint32_t *count)
8321 {
8322         WERROR result;
8323         union spoolss_PrintProcDataTypesInfo *info;
8324
8325         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8326         W_ERROR_HAVE_NO_MEMORY(info);
8327
8328         *count = 1;
8329
8330         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8331         if (!W_ERROR_IS_OK(result)) {
8332                 goto out;
8333         }
8334
8335  out:
8336         if (!W_ERROR_IS_OK(result)) {
8337                 TALLOC_FREE(info);
8338                 *count = 0;
8339                 return result;
8340         }
8341
8342         *info_p = info;
8343
8344         return WERR_OK;
8345 }
8346
8347 /****************************************************************
8348  _spoolss_EnumPrintProcDataTypes
8349 ****************************************************************/
8350
8351 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8352                                        struct spoolss_EnumPrintProcDataTypes *r)
8353 {
8354         WERROR result;
8355
8356         /* that's an [in out] buffer */
8357
8358         if (!r->in.buffer && (r->in.offered != 0)) {
8359                 return WERR_INVALID_PARAM;
8360         }
8361
8362         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8363
8364         *r->out.count = 0;
8365         *r->out.needed = 0;
8366         *r->out.info = NULL;
8367
8368         switch (r->in.level) {
8369         case 1:
8370                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8371                                                         r->out.count);
8372                 break;
8373         default:
8374                 return WERR_UNKNOWN_LEVEL;
8375         }
8376
8377         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8378                                                      spoolss_EnumPrintProcDataTypes, NULL,
8379                                                      *r->out.info, r->in.level,
8380                                                      *r->out.count);
8381         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8382         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8383
8384         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8385 }
8386
8387 /****************************************************************************
8388  fill_monitor_1
8389 ****************************************************************************/
8390
8391 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8392                              struct spoolss_MonitorInfo1 *r,
8393                              const char *monitor_name)
8394 {
8395         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8396         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8397
8398         return WERR_OK;
8399 }
8400
8401 /****************************************************************************
8402  fill_monitor_2
8403 ****************************************************************************/
8404
8405 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8406                              struct spoolss_MonitorInfo2 *r,
8407                              const char *monitor_name,
8408                              const char *environment,
8409                              const char *dll_name)
8410 {
8411         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8412         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8413         r->environment                  = talloc_strdup(mem_ctx, environment);
8414         W_ERROR_HAVE_NO_MEMORY(r->environment);
8415         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8416         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8417
8418         return WERR_OK;
8419 }
8420
8421 /****************************************************************************
8422  enumprintmonitors level 1.
8423 ****************************************************************************/
8424
8425 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8426                                         union spoolss_MonitorInfo **info_p,
8427                                         uint32_t *count)
8428 {
8429         union spoolss_MonitorInfo *info;
8430         WERROR result = WERR_OK;
8431
8432         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8433         W_ERROR_HAVE_NO_MEMORY(info);
8434
8435         *count = 2;
8436
8437         result = fill_monitor_1(info, &info[0].info1,
8438                                 SPL_LOCAL_PORT);
8439         if (!W_ERROR_IS_OK(result)) {
8440                 goto out;
8441         }
8442
8443         result = fill_monitor_1(info, &info[1].info1,
8444                                 SPL_TCPIP_PORT);
8445         if (!W_ERROR_IS_OK(result)) {
8446                 goto out;
8447         }
8448
8449 out:
8450         if (!W_ERROR_IS_OK(result)) {
8451                 TALLOC_FREE(info);
8452                 *count = 0;
8453                 return result;
8454         }
8455
8456         *info_p = info;
8457
8458         return WERR_OK;
8459 }
8460
8461 /****************************************************************************
8462  enumprintmonitors level 2.
8463 ****************************************************************************/
8464
8465 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8466                                         union spoolss_MonitorInfo **info_p,
8467                                         uint32_t *count)
8468 {
8469         union spoolss_MonitorInfo *info;
8470         WERROR result = WERR_OK;
8471
8472         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8473         W_ERROR_HAVE_NO_MEMORY(info);
8474
8475         *count = 2;
8476
8477         result = fill_monitor_2(info, &info[0].info2,
8478                                 SPL_LOCAL_PORT,
8479                                 "Windows NT X86", /* FIXME */
8480                                 "localmon.dll");
8481         if (!W_ERROR_IS_OK(result)) {
8482                 goto out;
8483         }
8484
8485         result = fill_monitor_2(info, &info[1].info2,
8486                                 SPL_TCPIP_PORT,
8487                                 "Windows NT X86", /* FIXME */
8488                                 "tcpmon.dll");
8489         if (!W_ERROR_IS_OK(result)) {
8490                 goto out;
8491         }
8492
8493 out:
8494         if (!W_ERROR_IS_OK(result)) {
8495                 TALLOC_FREE(info);
8496                 *count = 0;
8497                 return result;
8498         }
8499
8500         *info_p = info;
8501
8502         return WERR_OK;
8503 }
8504
8505 /****************************************************************
8506  _spoolss_EnumMonitors
8507 ****************************************************************/
8508
8509 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8510                              struct spoolss_EnumMonitors *r)
8511 {
8512         WERROR result;
8513
8514         /* that's an [in out] buffer */
8515
8516         if (!r->in.buffer && (r->in.offered != 0)) {
8517                 return WERR_INVALID_PARAM;
8518         }
8519
8520         DEBUG(5,("_spoolss_EnumMonitors\n"));
8521
8522         /*
8523          * Enumerate the print monitors ...
8524          *
8525          * Just reply with "Local Port", to keep NT happy
8526          * and I can use my nice printer checker.
8527          */
8528
8529         *r->out.count = 0;
8530         *r->out.needed = 0;
8531         *r->out.info = NULL;
8532
8533         switch (r->in.level) {
8534         case 1:
8535                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8536                                                    r->out.count);
8537                 break;
8538         case 2:
8539                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8540                                                    r->out.count);
8541                 break;
8542         default:
8543                 return WERR_UNKNOWN_LEVEL;
8544         }
8545
8546         if (!W_ERROR_IS_OK(result)) {
8547                 return result;
8548         }
8549
8550         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8551                                                      spoolss_EnumMonitors, NULL,
8552                                                      *r->out.info, r->in.level,
8553                                                      *r->out.count);
8554         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8555         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8556
8557         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8558 }
8559
8560 /****************************************************************************
8561 ****************************************************************************/
8562
8563 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8564                              const print_queue_struct *queue,
8565                              int count, int snum,
8566                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8567                              uint32_t jobid,
8568                              struct spoolss_JobInfo1 *r)
8569 {
8570         int i = 0;
8571         bool found = false;
8572
8573         for (i=0; i<count; i++) {
8574                 if (queue[i].job == (int)jobid) {
8575                         found = true;
8576                         break;
8577                 }
8578         }
8579
8580         if (found == false) {
8581                 /* NT treats not found as bad param... yet another bad choice */
8582                 return WERR_INVALID_PARAM;
8583         }
8584
8585         return fill_job_info1(mem_ctx,
8586                               r,
8587                               &queue[i],
8588                               i,
8589                               snum,
8590                               ntprinter);
8591 }
8592
8593 /****************************************************************************
8594 ****************************************************************************/
8595
8596 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8597                              const print_queue_struct *queue,
8598                              int count, int snum,
8599                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8600                              uint32_t jobid,
8601                              struct spoolss_JobInfo2 *r)
8602 {
8603         int i = 0;
8604         bool found = false;
8605         struct spoolss_DeviceMode *devmode;
8606         NT_DEVICEMODE *nt_devmode;
8607         WERROR result;
8608
8609         for (i=0; i<count; i++) {
8610                 if (queue[i].job == (int)jobid) {
8611                         found = true;
8612                         break;
8613                 }
8614         }
8615
8616         if (found == false) {
8617                 /* NT treats not found as bad param... yet another bad
8618                    choice */
8619                 return WERR_INVALID_PARAM;
8620         }
8621
8622         /*
8623          * if the print job does not have a DEVMODE associated with it,
8624          * just use the one for the printer. A NULL devicemode is not
8625          *  a failure condition
8626          */
8627
8628         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8629         if (nt_devmode) {
8630                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8631                 W_ERROR_HAVE_NO_MEMORY(devmode);
8632                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8633                 if (!W_ERROR_IS_OK(result)) {
8634                         return result;
8635                 }
8636         } else {
8637                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8638                 W_ERROR_HAVE_NO_MEMORY(devmode);
8639         }
8640
8641         return fill_job_info2(mem_ctx,
8642                               r,
8643                               &queue[i],
8644                               i,
8645                               snum,
8646                               ntprinter,
8647                               devmode);
8648 }
8649
8650 /****************************************************************
8651  _spoolss_GetJob
8652 ****************************************************************/
8653
8654 WERROR _spoolss_GetJob(pipes_struct *p,
8655                        struct spoolss_GetJob *r)
8656 {
8657         WERROR result = WERR_OK;
8658         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8659         int snum;
8660         int count;
8661         print_queue_struct      *queue = NULL;
8662         print_status_struct prt_status;
8663
8664         /* that's an [in out] buffer */
8665
8666         if (!r->in.buffer && (r->in.offered != 0)) {
8667                 return WERR_INVALID_PARAM;
8668         }
8669
8670         DEBUG(5,("_spoolss_GetJob\n"));
8671
8672         *r->out.needed = 0;
8673
8674         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8675                 return WERR_BADFID;
8676         }
8677
8678         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8679         if (!W_ERROR_IS_OK(result)) {
8680                 return result;
8681         }
8682
8683         count = print_queue_status(snum, &queue, &prt_status);
8684
8685         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8686                      count, prt_status.status, prt_status.message));
8687
8688         switch (r->in.level) {
8689         case 1:
8690                 result = getjob_level_1(p->mem_ctx,
8691                                         queue, count, snum, ntprinter,
8692                                         r->in.job_id, &r->out.info->info1);
8693                 break;
8694         case 2:
8695                 result = getjob_level_2(p->mem_ctx,
8696                                         queue, count, snum, ntprinter,
8697                                         r->in.job_id, &r->out.info->info2);
8698                 break;
8699         default:
8700                 result = WERR_UNKNOWN_LEVEL;
8701                 break;
8702         }
8703
8704         SAFE_FREE(queue);
8705         free_a_printer(&ntprinter, 2);
8706
8707         if (!W_ERROR_IS_OK(result)) {
8708                 TALLOC_FREE(r->out.info);
8709                 return result;
8710         }
8711
8712         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8713                                                r->out.info, r->in.level);
8714         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8715
8716         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8717 }
8718
8719 /****************************************************************
8720  _spoolss_GetPrinterDataEx
8721 ****************************************************************/
8722
8723 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8724                                  struct spoolss_GetPrinterDataEx *r)
8725 {
8726
8727         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8728         struct regval_blob              *val = NULL;
8729         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8730         int                     snum = 0;
8731         WERROR result = WERR_OK;
8732         DATA_BLOB blob;
8733
8734         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8735
8736         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8737                 r->in.key_name, r->in.value_name));
8738
8739         /* in case of problem, return some default values */
8740
8741         *r->out.needed  = 0;
8742         *r->out.type    = REG_NONE;
8743
8744         if (!Printer) {
8745                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8746                         OUR_HANDLE(r->in.handle)));
8747                 result = WERR_BADFID;
8748                 goto done;
8749         }
8750
8751         /* Is the handle to a printer or to the server? */
8752
8753         if (Printer->printer_type == SPLHND_SERVER) {
8754
8755                 union spoolss_PrinterData data;
8756
8757                 result = getprinterdata_printer_server(p->mem_ctx,
8758                                                        r->in.value_name,
8759                                                        r->out.type,
8760                                                        &data);
8761                 if (!W_ERROR_IS_OK(result)) {
8762                         goto done;
8763                 }
8764
8765                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8766                                                   *r->out.type, &data);
8767                 if (!W_ERROR_IS_OK(result)) {
8768                         goto done;
8769                 }
8770
8771                 *r->out.needed = blob.length;
8772
8773                 if (r->in.offered >= *r->out.needed) {
8774                         memcpy(r->out.data, blob.data, blob.length);
8775                 }
8776
8777                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8778         }
8779
8780         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8781                 result = WERR_BADFID;
8782                 goto done;
8783         }
8784
8785         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8786         if (!W_ERROR_IS_OK(result)) {
8787                 goto done;
8788         }
8789
8790         /* check to see if the keyname is valid */
8791         if (!strlen(r->in.key_name)) {
8792                 result = WERR_INVALID_PARAM;
8793                 goto done;
8794         }
8795
8796         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8797
8798         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8799             strequal(r->in.value_name, "ChangeId")) {
8800                 *r->out.type = REG_DWORD;
8801                 *r->out.needed = 4;
8802                 if (r->in.offered >= *r->out.needed) {
8803                         SIVAL(r->out.data, 0, printer->info_2->changeid);
8804                         result = WERR_OK;
8805                 }
8806                 goto done;
8807         }
8808
8809         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8810                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8811                         "Invalid keyname [%s]\n", r->in.key_name ));
8812                 result = WERR_BADFILE;
8813                 goto done;
8814         }
8815
8816         val = get_printer_data(printer->info_2,
8817                                r->in.key_name, r->in.value_name);
8818         if (!val) {
8819                 result = WERR_BADFILE;
8820                 goto done;
8821         }
8822
8823         *r->out.needed = regval_size(val);
8824         *r->out.type = regval_type(val);
8825
8826         if (r->in.offered >= *r->out.needed) {
8827                 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8828         }
8829  done:
8830         if (printer) {
8831                 free_a_printer(&printer, 2);
8832         }
8833
8834         if (!W_ERROR_IS_OK(result)) {
8835                 return result;
8836         }
8837
8838         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8839         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8840
8841         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8842 }
8843
8844 /****************************************************************
8845  _spoolss_SetPrinterDataEx
8846 ****************************************************************/
8847
8848 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8849                                  struct spoolss_SetPrinterDataEx *r)
8850 {
8851         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8852         int                     snum = 0;
8853         WERROR                  result = WERR_OK;
8854         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8855         char                    *oid_string;
8856
8857         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8858
8859         /* From MSDN documentation of SetPrinterDataEx: pass request to
8860            SetPrinterData if key is "PrinterDriverData" */
8861
8862         if (!Printer) {
8863                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8864                         OUR_HANDLE(r->in.handle)));
8865                 return WERR_BADFID;
8866         }
8867
8868         if (Printer->printer_type == SPLHND_SERVER) {
8869                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8870                         "Not implemented for server handles yet\n"));
8871                 return WERR_INVALID_PARAM;
8872         }
8873
8874         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8875                 return WERR_BADFID;
8876         }
8877
8878         /*
8879          * Access check : NT returns "access denied" if you make a
8880          * SetPrinterData call without the necessary privildge.
8881          * we were originally returning OK if nothing changed
8882          * which made Win2k issue **a lot** of SetPrinterData
8883          * when connecting to a printer  --jerry
8884          */
8885
8886         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8887                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8888                         "change denied by handle access permissions\n"));
8889                 return WERR_ACCESS_DENIED;
8890         }
8891
8892         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8893         if (!W_ERROR_IS_OK(result)) {
8894                 return result;
8895         }
8896
8897         /* check for OID in valuename */
8898
8899         oid_string = strchr(r->in.value_name, ',');
8900         if (oid_string) {
8901                 *oid_string = '\0';
8902                 oid_string++;
8903         }
8904
8905         /*
8906          * When client side code sets a magic printer data key, detect it and save
8907          * the current printer data and the magic key's data (its the DEVMODE) for
8908          * future printer/driver initializations.
8909          */
8910         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8911                 /* Set devmode and printer initialization info */
8912                 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
8913
8914                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8915
8916                 goto done;
8917         }
8918
8919         /* save the registry data */
8920
8921         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8922                                     r->in.type, r->in.data, r->in.offered);
8923
8924         if (W_ERROR_IS_OK(result)) {
8925                 /* save the OID if one was specified */
8926                 if (oid_string) {
8927                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8928                                 r->in.key_name, SPOOL_OID_KEY);
8929                         if (!str) {
8930                                 result = WERR_NOMEM;
8931                                 goto done;
8932                         }
8933
8934                         /*
8935                          * I'm not checking the status here on purpose.  Don't know
8936                          * if this is right, but I'm returning the status from the
8937                          * previous set_printer_dataex() call.  I have no idea if
8938                          * this is right.    --jerry
8939                          */
8940
8941                         set_printer_dataex(printer, str, r->in.value_name,
8942                                            REG_SZ, (uint8_t *)oid_string,
8943                                            strlen(oid_string)+1);
8944                 }
8945
8946                 result = mod_a_printer(printer, 2);
8947         }
8948
8949  done:
8950         free_a_printer(&printer, 2);
8951
8952         return result;
8953 }
8954
8955 /****************************************************************
8956  _spoolss_DeletePrinterDataEx
8957 ****************************************************************/
8958
8959 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8960                                     struct spoolss_DeletePrinterDataEx *r)
8961 {
8962         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8963         int             snum=0;
8964         WERROR          status = WERR_OK;
8965         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8966
8967         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8968
8969         if (!Printer) {
8970                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8971                         "Invalid handle (%s:%u:%u).\n",
8972                         OUR_HANDLE(r->in.handle)));
8973                 return WERR_BADFID;
8974         }
8975
8976         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8977                 return WERR_BADFID;
8978
8979         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8980                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8981                         "printer properties change denied by handle\n"));
8982                 return WERR_ACCESS_DENIED;
8983         }
8984
8985         if (!r->in.value_name || !r->in.key_name) {
8986                 return WERR_NOMEM;
8987         }
8988
8989         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8990         if (!W_ERROR_IS_OK(status))
8991                 return status;
8992
8993         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8994
8995         if ( W_ERROR_IS_OK(status) )
8996                 mod_a_printer( printer, 2 );
8997
8998         free_a_printer(&printer, 2);
8999
9000         return status;
9001 }
9002
9003 /****************************************************************
9004  _spoolss_EnumPrinterKey
9005 ****************************************************************/
9006
9007 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9008                                struct spoolss_EnumPrinterKey *r)
9009 {
9010         fstring         *keynames = NULL;
9011         int             num_keys;
9012         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9013         NT_PRINTER_DATA *data;
9014         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9015         int             snum = 0;
9016         WERROR          result = WERR_BADFILE;
9017         int i;
9018         const char **array = NULL;
9019         DATA_BLOB blob;
9020
9021         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9022
9023         if (!Printer) {
9024                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9025                         OUR_HANDLE(r->in.handle)));
9026                 return WERR_BADFID;
9027         }
9028
9029         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9030                 return WERR_BADFID;
9031         }
9032
9033         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9034         if (!W_ERROR_IS_OK(result)) {
9035                 return result;
9036         }
9037
9038         /* get the list of subkey names */
9039
9040         data = printer->info_2->data;
9041
9042         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9043         if (num_keys == -1) {
9044                 result = WERR_BADFILE;
9045                 goto done;
9046         }
9047
9048         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9049         if (!array) {
9050                 result = WERR_NOMEM;
9051                 goto done;
9052         }
9053
9054         if (!num_keys) {
9055                 array[0] = talloc_strdup(array, "");
9056                 if (!array[0]) {
9057                         result = WERR_NOMEM;
9058                         goto done;
9059                 }
9060         }
9061
9062         for (i=0; i < num_keys; i++) {
9063
9064                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9065                         keynames[i]));
9066
9067                 array[i] = talloc_strdup(array, keynames[i]);
9068                 if (!array[i]) {
9069                         result = WERR_NOMEM;
9070                         goto done;
9071                 }
9072         }
9073
9074         if (!push_reg_multi_sz(p->mem_ctx, NULL, &blob, array)) {
9075                 result = WERR_NOMEM;
9076                 goto done;
9077         }
9078
9079         *r->out._ndr_size = r->in.offered / 2;
9080         *r->out.needed = blob.length;
9081
9082         if (r->in.offered < *r->out.needed) {
9083                 result = WERR_MORE_DATA;
9084         } else {
9085                 result = WERR_OK;
9086                 r->out.key_buffer->string_array = array;
9087         }
9088
9089  done:
9090         if (!W_ERROR_IS_OK(result)) {
9091                 TALLOC_FREE(array);
9092                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9093                         *r->out.needed = 0;
9094                 }
9095         }
9096
9097         free_a_printer(&printer, 2);
9098         SAFE_FREE(keynames);
9099
9100         return result;
9101 }
9102
9103 /****************************************************************
9104  _spoolss_DeletePrinterKey
9105 ****************************************************************/
9106
9107 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9108                                  struct spoolss_DeletePrinterKey *r)
9109 {
9110         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9111         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9112         int                     snum=0;
9113         WERROR                  status;
9114
9115         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9116
9117         if (!Printer) {
9118                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9119                         OUR_HANDLE(r->in.handle)));
9120                 return WERR_BADFID;
9121         }
9122
9123         /* if keyname == NULL, return error */
9124
9125         if ( !r->in.key_name )
9126                 return WERR_INVALID_PARAM;
9127
9128         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9129                 return WERR_BADFID;
9130
9131         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9132                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9133                         "printer properties change denied by handle\n"));
9134                 return WERR_ACCESS_DENIED;
9135         }
9136
9137         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9138         if (!W_ERROR_IS_OK(status))
9139                 return status;
9140
9141         /* delete the key and all subneys */
9142
9143         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9144
9145         if ( W_ERROR_IS_OK(status) )
9146                 status = mod_a_printer(printer, 2);
9147
9148         free_a_printer( &printer, 2 );
9149
9150         return status;
9151 }
9152
9153 /****************************************************************
9154 ****************************************************************/
9155
9156 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9157                                                    struct regval_blob *v,
9158                                                    struct spoolss_PrinterEnumValues *r)
9159 {
9160         r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9161         W_ERROR_HAVE_NO_MEMORY(r->data);
9162
9163         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9164         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9165
9166         r->value_name_len = strlen_m_term(regval_name(v)) * 2;
9167
9168         r->type         = regval_type(v);
9169         r->data_length  = regval_size(v);
9170
9171         if (r->data_length) {
9172                 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9173         }
9174
9175         return WERR_OK;
9176 }
9177
9178 /****************************************************************
9179  _spoolss_EnumPrinterDataEx
9180 ****************************************************************/
9181
9182 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9183                                   struct spoolss_EnumPrinterDataEx *r)
9184 {
9185         uint32_t        count = 0;
9186         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9187         struct spoolss_PrinterEnumValues *info = NULL;
9188         NT_PRINTER_DATA         *p_data;
9189         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9190         int             snum;
9191         WERROR          result;
9192         int             key_index;
9193         int             i;
9194
9195         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9196
9197         *r->out.count = 0;
9198         *r->out.needed = 0;
9199         *r->out.info = NULL;
9200
9201         if (!Printer) {
9202                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9203                         OUR_HANDLE(r->in.handle)));
9204                 return WERR_BADFID;
9205         }
9206
9207         /*
9208          * first check for a keyname of NULL or "".  Win2k seems to send
9209          * this a lot and we should send back WERR_INVALID_PARAM
9210          * no need to spend time looking up the printer in this case.
9211          * --jerry
9212          */
9213
9214         if (!strlen(r->in.key_name)) {
9215                 result = WERR_INVALID_PARAM;
9216                 goto done;
9217         }
9218
9219         /* get the printer off of disk */
9220
9221         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9222                 return WERR_BADFID;
9223         }
9224
9225         ZERO_STRUCT(printer);
9226         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9227         if (!W_ERROR_IS_OK(result)) {
9228                 return result;
9229         }
9230
9231         /* now look for a match on the key name */
9232
9233         p_data = printer->info_2->data;
9234
9235         key_index = lookup_printerkey(p_data, r->in.key_name);
9236         if (key_index == -1) {
9237                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9238                         r->in.key_name));
9239                 result = WERR_INVALID_PARAM;
9240                 goto done;
9241         }
9242
9243         /* allocate the memory for the array of pointers -- if necessary */
9244
9245         count = regval_ctr_numvals(p_data->keys[key_index].values);
9246         if (!count) {
9247                 result = WERR_OK; /* ??? */
9248                 goto done;
9249         }
9250
9251         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9252                                  struct spoolss_PrinterEnumValues,
9253                                  count);
9254         if (!info) {
9255                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9256                 result = WERR_NOMEM;
9257                 goto done;
9258         }
9259
9260         /*
9261          * loop through all params and build the array to pass
9262          * back to the  client
9263          */
9264
9265         for (i=0; i < count; i++) {
9266
9267                 struct regval_blob      *val;
9268
9269                 /* lookup the registry value */
9270
9271                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9272
9273                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9274
9275                 /* copy the data */
9276
9277                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9278                 if (!W_ERROR_IS_OK(result)) {
9279                         goto done;
9280                 }
9281         }
9282
9283 #if 0 /* FIXME - gd */
9284         /* housekeeping information in the reply */
9285
9286         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9287          * the hand marshalled container size is a multiple
9288          * of 4 bytes for RPC alignment.
9289          */
9290
9291         if (needed % 4) {
9292                 needed += 4-(needed % 4);
9293         }
9294 #endif
9295         *r->out.count   = count;
9296         *r->out.info    = info;
9297
9298  done:
9299
9300         if (printer) {
9301                 free_a_printer(&printer, 2);
9302         }
9303
9304         if (!W_ERROR_IS_OK(result)) {
9305                 return result;
9306         }
9307
9308         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9309                                                spoolss_EnumPrinterDataEx, NULL,
9310                                                *r->out.info,
9311                                                *r->out.count);
9312         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9313         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9314
9315         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9316 }
9317
9318 /****************************************************************************
9319 ****************************************************************************/
9320
9321 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9322                                                  const char *servername,
9323                                                  const char *environment,
9324                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9325 {
9326         WERROR werr;
9327         char *path = NULL;
9328
9329         werr = compose_spoolss_server_path(mem_ctx,
9330                                            servername,
9331                                            environment,
9332                                            SPOOLSS_PRTPROCS_PATH,
9333                                            &path);
9334         if (!W_ERROR_IS_OK(werr)) {
9335                 return werr;
9336         }
9337
9338         DEBUG(4,("print processor directory: [%s]\n", path));
9339
9340         r->directory_name = path;
9341
9342         return WERR_OK;
9343 }
9344
9345 /****************************************************************
9346  _spoolss_GetPrintProcessorDirectory
9347 ****************************************************************/
9348
9349 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9350                                            struct spoolss_GetPrintProcessorDirectory *r)
9351 {
9352         WERROR result;
9353
9354         /* that's an [in out] buffer */
9355
9356         if (!r->in.buffer && (r->in.offered != 0)) {
9357                 return WERR_INVALID_PARAM;
9358         }
9359
9360         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9361                 r->in.level));
9362
9363         *r->out.needed = 0;
9364
9365         /* r->in.level is ignored */
9366
9367         /* We always should reply with a local print processor directory so that
9368          * users are not forced to have a [prnproc$] share on the Samba spoolss
9369          * server - Guenther */
9370
9371         result = getprintprocessordirectory_level_1(p->mem_ctx,
9372                                                     NULL, /* r->in.server */
9373                                                     r->in.environment,
9374                                                     &r->out.info->info1);
9375         if (!W_ERROR_IS_OK(result)) {
9376                 TALLOC_FREE(r->out.info);
9377                 return result;
9378         }
9379
9380         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9381                                                r->out.info, r->in.level);
9382         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9383
9384         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9385 }
9386
9387 /*******************************************************************
9388  ********************************************************************/
9389
9390 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9391                                const char *dllname)
9392 {
9393         enum ndr_err_code ndr_err;
9394         struct spoolss_MonitorUi ui;
9395
9396         ui.dll_name = dllname;
9397
9398         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9399                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9400         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9401                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9402         }
9403         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9404 }
9405
9406 /*******************************************************************
9407  Streams the monitor UI DLL name in UNICODE
9408 *******************************************************************/
9409
9410 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9411                                NT_USER_TOKEN *token, DATA_BLOB *in,
9412                                DATA_BLOB *out, uint32_t *needed)
9413 {
9414         const char *dllname = "tcpmonui.dll";
9415
9416         *needed = (strlen(dllname)+1) * 2;
9417
9418         if (out->length < *needed) {
9419                 return WERR_INSUFFICIENT_BUFFER;
9420         }
9421
9422         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9423                 return WERR_NOMEM;
9424         }
9425
9426         return WERR_OK;
9427 }
9428
9429 /*******************************************************************
9430  ********************************************************************/
9431
9432 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9433                              struct spoolss_PortData1 *port1,
9434                              const DATA_BLOB *buf)
9435 {
9436         enum ndr_err_code ndr_err;
9437         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9438                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9439         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9440                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9441         }
9442         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9443 }
9444
9445 /*******************************************************************
9446  ********************************************************************/
9447
9448 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9449                              struct spoolss_PortData2 *port2,
9450                              const DATA_BLOB *buf)
9451 {
9452         enum ndr_err_code ndr_err;
9453         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9454                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9455         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9456                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9457         }
9458         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9459 }
9460
9461 /*******************************************************************
9462  Create a new TCP/IP port
9463 *******************************************************************/
9464
9465 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9466                              NT_USER_TOKEN *token, DATA_BLOB *in,
9467                              DATA_BLOB *out, uint32_t *needed)
9468 {
9469         struct spoolss_PortData1 port1;
9470         struct spoolss_PortData2 port2;
9471         char *device_uri = NULL;
9472         uint32_t version;
9473
9474         const char *portname;
9475         const char *hostaddress;
9476         const char *queue;
9477         uint32_t port_number;
9478         uint32_t protocol;
9479
9480         /* peek for spoolss_PortData version */
9481
9482         if (!in || (in->length < (128 + 4))) {
9483                 return WERR_GENERAL_FAILURE;
9484         }
9485
9486         version = IVAL(in->data, 128);
9487
9488         switch (version) {
9489                 case 1:
9490                         ZERO_STRUCT(port1);
9491
9492                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9493                                 return WERR_NOMEM;
9494                         }
9495
9496                         portname        = port1.portname;
9497                         hostaddress     = port1.hostaddress;
9498                         queue           = port1.queue;
9499                         protocol        = port1.protocol;
9500                         port_number     = port1.port_number;
9501
9502                         break;
9503                 case 2:
9504                         ZERO_STRUCT(port2);
9505
9506                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9507                                 return WERR_NOMEM;
9508                         }
9509
9510                         portname        = port2.portname;
9511                         hostaddress     = port2.hostaddress;
9512                         queue           = port2.queue;
9513                         protocol        = port2.protocol;
9514                         port_number     = port2.port_number;
9515
9516                         break;
9517                 default:
9518                         DEBUG(1,("xcvtcp_addport: "
9519                                 "unknown version of port_data: %d\n", version));
9520                         return WERR_UNKNOWN_PORT;
9521         }
9522
9523         /* create the device URI and call the add_port_hook() */
9524
9525         switch (protocol) {
9526         case PROTOCOL_RAWTCP_TYPE:
9527                 device_uri = talloc_asprintf(mem_ctx,
9528                                 "socket://%s:%d/", hostaddress,
9529                                 port_number);
9530                 break;
9531
9532         case PROTOCOL_LPR_TYPE:
9533                 device_uri = talloc_asprintf(mem_ctx,
9534                         "lpr://%s/%s", hostaddress, queue );
9535                 break;
9536
9537         default:
9538                 return WERR_UNKNOWN_PORT;
9539         }
9540
9541         if (!device_uri) {
9542                 return WERR_NOMEM;
9543         }
9544
9545         return add_port_hook(mem_ctx, token, portname, device_uri);
9546 }
9547
9548 /*******************************************************************
9549 *******************************************************************/
9550
9551 struct xcv_api_table xcvtcp_cmds[] = {
9552         { "MonitorUI",  xcvtcp_monitorui },
9553         { "AddPort",    xcvtcp_addport},
9554         { NULL,         NULL }
9555 };
9556
9557 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9558                                      NT_USER_TOKEN *token, const char *command,
9559                                      DATA_BLOB *inbuf,
9560                                      DATA_BLOB *outbuf,
9561                                      uint32_t *needed )
9562 {
9563         int i;
9564
9565         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9566
9567         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9568                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9569                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9570         }
9571
9572         return WERR_BADFUNC;
9573 }
9574
9575 /*******************************************************************
9576 *******************************************************************/
9577 #if 0   /* don't support management using the "Local Port" monitor */
9578
9579 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9580                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9581                                  DATA_BLOB *out, uint32_t *needed)
9582 {
9583         const char *dllname = "localui.dll";
9584
9585         *needed = (strlen(dllname)+1) * 2;
9586
9587         if (out->length < *needed) {
9588                 return WERR_INSUFFICIENT_BUFFER;
9589         }
9590
9591         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9592                 return WERR_NOMEM;
9593         }
9594
9595         return WERR_OK;
9596 }
9597
9598 /*******************************************************************
9599 *******************************************************************/
9600
9601 struct xcv_api_table xcvlocal_cmds[] = {
9602         { "MonitorUI",  xcvlocal_monitorui },
9603         { NULL,         NULL }
9604 };
9605 #else
9606 struct xcv_api_table xcvlocal_cmds[] = {
9607         { NULL,         NULL }
9608 };
9609 #endif
9610
9611
9612
9613 /*******************************************************************
9614 *******************************************************************/
9615
9616 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9617                                        NT_USER_TOKEN *token, const char *command,
9618                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9619                                        uint32_t *needed)
9620 {
9621         int i;
9622
9623         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9624
9625         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9626                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9627                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9628         }
9629         return WERR_BADFUNC;
9630 }
9631
9632 /****************************************************************
9633  _spoolss_XcvData
9634 ****************************************************************/
9635
9636 WERROR _spoolss_XcvData(pipes_struct *p,
9637                         struct spoolss_XcvData *r)
9638 {
9639         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9640         DATA_BLOB out_data = data_blob_null;
9641         WERROR werror;
9642
9643         if (!Printer) {
9644                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9645                         OUR_HANDLE(r->in.handle)));
9646                 return WERR_BADFID;
9647         }
9648
9649         /* Has to be a handle to the TCP/IP port monitor */
9650
9651         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9652                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9653                 return WERR_BADFID;
9654         }
9655
9656         /* requires administrative access to the server */
9657
9658         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9659                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9660                 return WERR_ACCESS_DENIED;
9661         }
9662
9663         /* Allocate the outgoing buffer */
9664
9665         if (r->in.out_data_size) {
9666                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9667                 if (out_data.data == NULL) {
9668                         return WERR_NOMEM;
9669                 }
9670         }
9671
9672         switch ( Printer->printer_type ) {
9673         case SPLHND_PORTMON_TCP:
9674                 werror = process_xcvtcp_command(p->mem_ctx,
9675                                                 p->server_info->ptok,
9676                                                 r->in.function_name,
9677                                                 &r->in.in_data, &out_data,
9678                                                 r->out.needed);
9679                 break;
9680         case SPLHND_PORTMON_LOCAL:
9681                 werror = process_xcvlocal_command(p->mem_ctx,
9682                                                   p->server_info->ptok,
9683                                                   r->in.function_name,
9684                                                   &r->in.in_data, &out_data,
9685                                                   r->out.needed);
9686                 break;
9687         default:
9688                 werror = WERR_INVALID_PRINT_MONITOR;
9689         }
9690
9691         if (!W_ERROR_IS_OK(werror)) {
9692                 return werror;
9693         }
9694
9695         *r->out.status_code = 0;
9696
9697         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9698                 memcpy(r->out.out_data, out_data.data,
9699                         MIN(r->in.out_data_size, out_data.length));
9700         }
9701
9702         return WERR_OK;
9703 }
9704
9705 /****************************************************************
9706  _spoolss_AddPrintProcessor
9707 ****************************************************************/
9708
9709 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9710                                   struct spoolss_AddPrintProcessor *r)
9711 {
9712         /* for now, just indicate success and ignore the add.  We'll
9713            automatically set the winprint processor for printer
9714            entries later.  Used to debug the LexMark Optra S 1855 PCL
9715            driver --jerry */
9716
9717         return WERR_OK;
9718 }
9719
9720 /****************************************************************
9721  _spoolss_AddPort
9722 ****************************************************************/
9723
9724 WERROR _spoolss_AddPort(pipes_struct *p,
9725                         struct spoolss_AddPort *r)
9726 {
9727         /* do what w2k3 does */
9728
9729         return WERR_NOT_SUPPORTED;
9730 }
9731
9732 /****************************************************************
9733  _spoolss_GetPrinterDriver
9734 ****************************************************************/
9735
9736 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9737                                  struct spoolss_GetPrinterDriver *r)
9738 {
9739         p->rng_fault_state = true;
9740         return WERR_NOT_SUPPORTED;
9741 }
9742
9743 /****************************************************************
9744  _spoolss_ReadPrinter
9745 ****************************************************************/
9746
9747 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9748                             struct spoolss_ReadPrinter *r)
9749 {
9750         p->rng_fault_state = true;
9751         return WERR_NOT_SUPPORTED;
9752 }
9753
9754 /****************************************************************
9755  _spoolss_WaitForPrinterChange
9756 ****************************************************************/
9757
9758 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9759                                      struct spoolss_WaitForPrinterChange *r)
9760 {
9761         p->rng_fault_state = true;
9762         return WERR_NOT_SUPPORTED;
9763 }
9764
9765 /****************************************************************
9766  _spoolss_ConfigurePort
9767 ****************************************************************/
9768
9769 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9770                               struct spoolss_ConfigurePort *r)
9771 {
9772         p->rng_fault_state = true;
9773         return WERR_NOT_SUPPORTED;
9774 }
9775
9776 /****************************************************************
9777  _spoolss_DeletePort
9778 ****************************************************************/
9779
9780 WERROR _spoolss_DeletePort(pipes_struct *p,
9781                            struct spoolss_DeletePort *r)
9782 {
9783         p->rng_fault_state = true;
9784         return WERR_NOT_SUPPORTED;
9785 }
9786
9787 /****************************************************************
9788  _spoolss_CreatePrinterIC
9789 ****************************************************************/
9790
9791 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9792                                 struct spoolss_CreatePrinterIC *r)
9793 {
9794         p->rng_fault_state = true;
9795         return WERR_NOT_SUPPORTED;
9796 }
9797
9798 /****************************************************************
9799  _spoolss_PlayGDIScriptOnPrinterIC
9800 ****************************************************************/
9801
9802 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9803                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9804 {
9805         p->rng_fault_state = true;
9806         return WERR_NOT_SUPPORTED;
9807 }
9808
9809 /****************************************************************
9810  _spoolss_DeletePrinterIC
9811 ****************************************************************/
9812
9813 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9814                                 struct spoolss_DeletePrinterIC *r)
9815 {
9816         p->rng_fault_state = true;
9817         return WERR_NOT_SUPPORTED;
9818 }
9819
9820 /****************************************************************
9821  _spoolss_AddPrinterConnection
9822 ****************************************************************/
9823
9824 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9825                                      struct spoolss_AddPrinterConnection *r)
9826 {
9827         p->rng_fault_state = true;
9828         return WERR_NOT_SUPPORTED;
9829 }
9830
9831 /****************************************************************
9832  _spoolss_DeletePrinterConnection
9833 ****************************************************************/
9834
9835 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9836                                         struct spoolss_DeletePrinterConnection *r)
9837 {
9838         p->rng_fault_state = true;
9839         return WERR_NOT_SUPPORTED;
9840 }
9841
9842 /****************************************************************
9843  _spoolss_PrinterMessageBox
9844 ****************************************************************/
9845
9846 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9847                                   struct spoolss_PrinterMessageBox *r)
9848 {
9849         p->rng_fault_state = true;
9850         return WERR_NOT_SUPPORTED;
9851 }
9852
9853 /****************************************************************
9854  _spoolss_AddMonitor
9855 ****************************************************************/
9856
9857 WERROR _spoolss_AddMonitor(pipes_struct *p,
9858                            struct spoolss_AddMonitor *r)
9859 {
9860         p->rng_fault_state = true;
9861         return WERR_NOT_SUPPORTED;
9862 }
9863
9864 /****************************************************************
9865  _spoolss_DeleteMonitor
9866 ****************************************************************/
9867
9868 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9869                               struct spoolss_DeleteMonitor *r)
9870 {
9871         p->rng_fault_state = true;
9872         return WERR_NOT_SUPPORTED;
9873 }
9874
9875 /****************************************************************
9876  _spoolss_DeletePrintProcessor
9877 ****************************************************************/
9878
9879 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9880                                      struct spoolss_DeletePrintProcessor *r)
9881 {
9882         p->rng_fault_state = true;
9883         return WERR_NOT_SUPPORTED;
9884 }
9885
9886 /****************************************************************
9887  _spoolss_AddPrintProvidor
9888 ****************************************************************/
9889
9890 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9891                                  struct spoolss_AddPrintProvidor *r)
9892 {
9893         p->rng_fault_state = true;
9894         return WERR_NOT_SUPPORTED;
9895 }
9896
9897 /****************************************************************
9898  _spoolss_DeletePrintProvidor
9899 ****************************************************************/
9900
9901 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9902                                     struct spoolss_DeletePrintProvidor *r)
9903 {
9904         p->rng_fault_state = true;
9905         return WERR_NOT_SUPPORTED;
9906 }
9907
9908 /****************************************************************
9909  _spoolss_FindFirstPrinterChangeNotification
9910 ****************************************************************/
9911
9912 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9913                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9914 {
9915         p->rng_fault_state = true;
9916         return WERR_NOT_SUPPORTED;
9917 }
9918
9919 /****************************************************************
9920  _spoolss_FindNextPrinterChangeNotification
9921 ****************************************************************/
9922
9923 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9924                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9925 {
9926         p->rng_fault_state = true;
9927         return WERR_NOT_SUPPORTED;
9928 }
9929
9930 /****************************************************************
9931  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9932 ****************************************************************/
9933
9934 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9935                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9936 {
9937         p->rng_fault_state = true;
9938         return WERR_NOT_SUPPORTED;
9939 }
9940
9941 /****************************************************************
9942  _spoolss_ReplyOpenPrinter
9943 ****************************************************************/
9944
9945 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9946                                  struct spoolss_ReplyOpenPrinter *r)
9947 {
9948         p->rng_fault_state = true;
9949         return WERR_NOT_SUPPORTED;
9950 }
9951
9952 /****************************************************************
9953  _spoolss_RouterReplyPrinter
9954 ****************************************************************/
9955
9956 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9957                                    struct spoolss_RouterReplyPrinter *r)
9958 {
9959         p->rng_fault_state = true;
9960         return WERR_NOT_SUPPORTED;
9961 }
9962
9963 /****************************************************************
9964  _spoolss_ReplyClosePrinter
9965 ****************************************************************/
9966
9967 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9968                                   struct spoolss_ReplyClosePrinter *r)
9969 {
9970         p->rng_fault_state = true;
9971         return WERR_NOT_SUPPORTED;
9972 }
9973
9974 /****************************************************************
9975  _spoolss_AddPortEx
9976 ****************************************************************/
9977
9978 WERROR _spoolss_AddPortEx(pipes_struct *p,
9979                           struct spoolss_AddPortEx *r)
9980 {
9981         p->rng_fault_state = true;
9982         return WERR_NOT_SUPPORTED;
9983 }
9984
9985 /****************************************************************
9986  _spoolss_RouterFindFirstPrinterChangeNotification
9987 ****************************************************************/
9988
9989 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9990                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9991 {
9992         p->rng_fault_state = true;
9993         return WERR_NOT_SUPPORTED;
9994 }
9995
9996 /****************************************************************
9997  _spoolss_SpoolerInit
9998 ****************************************************************/
9999
10000 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10001                             struct spoolss_SpoolerInit *r)
10002 {
10003         p->rng_fault_state = true;
10004         return WERR_NOT_SUPPORTED;
10005 }
10006
10007 /****************************************************************
10008  _spoolss_ResetPrinterEx
10009 ****************************************************************/
10010
10011 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10012                                struct spoolss_ResetPrinterEx *r)
10013 {
10014         p->rng_fault_state = true;
10015         return WERR_NOT_SUPPORTED;
10016 }
10017
10018 /****************************************************************
10019  _spoolss_RouterReplyPrinterEx
10020 ****************************************************************/
10021
10022 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10023                                      struct spoolss_RouterReplyPrinterEx *r)
10024 {
10025         p->rng_fault_state = true;
10026         return WERR_NOT_SUPPORTED;
10027 }
10028
10029 /****************************************************************
10030  _spoolss_44
10031 ****************************************************************/
10032
10033 WERROR _spoolss_44(pipes_struct *p,
10034                    struct spoolss_44 *r)
10035 {
10036         p->rng_fault_state = true;
10037         return WERR_NOT_SUPPORTED;
10038 }
10039
10040 /****************************************************************
10041  _spoolss_47
10042 ****************************************************************/
10043
10044 WERROR _spoolss_47(pipes_struct *p,
10045                    struct spoolss_47 *r)
10046 {
10047         p->rng_fault_state = true;
10048         return WERR_NOT_SUPPORTED;
10049 }
10050
10051 /****************************************************************
10052  _spoolss_4a
10053 ****************************************************************/
10054
10055 WERROR _spoolss_4a(pipes_struct *p,
10056                    struct spoolss_4a *r)
10057 {
10058         p->rng_fault_state = true;
10059         return WERR_NOT_SUPPORTED;
10060 }
10061
10062 /****************************************************************
10063  _spoolss_4b
10064 ****************************************************************/
10065
10066 WERROR _spoolss_4b(pipes_struct *p,
10067                    struct spoolss_4b *r)
10068 {
10069         p->rng_fault_state = true;
10070         return WERR_NOT_SUPPORTED;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_4c
10075 ****************************************************************/
10076
10077 WERROR _spoolss_4c(pipes_struct *p,
10078                    struct spoolss_4c *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085  _spoolss_53
10086 ****************************************************************/
10087
10088 WERROR _spoolss_53(pipes_struct *p,
10089                    struct spoolss_53 *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_55
10097 ****************************************************************/
10098
10099 WERROR _spoolss_55(pipes_struct *p,
10100                    struct spoolss_55 *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107  _spoolss_56
10108 ****************************************************************/
10109
10110 WERROR _spoolss_56(pipes_struct *p,
10111                    struct spoolss_56 *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118  _spoolss_57
10119 ****************************************************************/
10120
10121 WERROR _spoolss_57(pipes_struct *p,
10122                    struct spoolss_57 *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_5a
10130 ****************************************************************/
10131
10132 WERROR _spoolss_5a(pipes_struct *p,
10133                    struct spoolss_5a *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140  _spoolss_5b
10141 ****************************************************************/
10142
10143 WERROR _spoolss_5b(pipes_struct *p,
10144                    struct spoolss_5b *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151  _spoolss_5c
10152 ****************************************************************/
10153
10154 WERROR _spoolss_5c(pipes_struct *p,
10155                    struct spoolss_5c *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162  _spoolss_5d
10163 ****************************************************************/
10164
10165 WERROR _spoolss_5d(pipes_struct *p,
10166                    struct spoolss_5d *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173  _spoolss_5e
10174 ****************************************************************/
10175
10176 WERROR _spoolss_5e(pipes_struct *p,
10177                    struct spoolss_5e *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_5f
10185 ****************************************************************/
10186
10187 WERROR _spoolss_5f(pipes_struct *p,
10188                    struct spoolss_5f *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195  _spoolss_60
10196 ****************************************************************/
10197
10198 WERROR _spoolss_60(pipes_struct *p,
10199                    struct spoolss_60 *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206  _spoolss_61
10207 ****************************************************************/
10208
10209 WERROR _spoolss_61(pipes_struct *p,
10210                    struct spoolss_61 *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217  _spoolss_62
10218 ****************************************************************/
10219
10220 WERROR _spoolss_62(pipes_struct *p,
10221                    struct spoolss_62 *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228  _spoolss_63
10229 ****************************************************************/
10230
10231 WERROR _spoolss_63(pipes_struct *p,
10232                    struct spoolss_63 *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239  _spoolss_64
10240 ****************************************************************/
10241
10242 WERROR _spoolss_64(pipes_struct *p,
10243                    struct spoolss_64 *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250  _spoolss_65
10251 ****************************************************************/
10252
10253 WERROR _spoolss_65(pipes_struct *p,
10254                    struct spoolss_65 *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_GetCorePrinterDrivers
10262 ****************************************************************/
10263
10264 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10265                                       struct spoolss_GetCorePrinterDrivers *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272  _spoolss_67
10273 ****************************************************************/
10274
10275 WERROR _spoolss_67(pipes_struct *p,
10276                    struct spoolss_67 *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283  _spoolss_GetPrinterDriverPackagePath
10284 ****************************************************************/
10285
10286 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10287                                             struct spoolss_GetPrinterDriverPackagePath *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294  _spoolss_69
10295 ****************************************************************/
10296
10297 WERROR _spoolss_69(pipes_struct *p,
10298                    struct spoolss_69 *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305  _spoolss_6a
10306 ****************************************************************/
10307
10308 WERROR _spoolss_6a(pipes_struct *p,
10309                    struct spoolss_6a *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316  _spoolss_6b
10317 ****************************************************************/
10318
10319 WERROR _spoolss_6b(pipes_struct *p,
10320                    struct spoolss_6b *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_6c
10328 ****************************************************************/
10329
10330 WERROR _spoolss_6c(pipes_struct *p,
10331                    struct spoolss_6c *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_6d
10339 ****************************************************************/
10340
10341 WERROR _spoolss_6d(pipes_struct *p,
10342                    struct spoolss_6d *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }