s3: only include gen_ndr headers where needed.
[kai/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 /***********************************************************************
940  Send a change notication message on all handles which have a call
941  back registered
942  **********************************************************************/
943
944 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
945 {
946         Printer_entry            *p;
947         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
948         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
949         SPOOLSS_NOTIFY_MSG       *messages;
950         int                      sending_msg_count;
951
952         if ( !msg_group ) {
953                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954                 return;
955         }
956
957         messages = msg_group->msgs;
958
959         if ( !messages ) {
960                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961                 return;
962         }
963
964         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
965
966         /* loop over all printers */
967
968         for (p = printers_list; p; p = p->next) {
969                 struct spoolss_Notify *notifies;
970                 uint32_t count = 0;
971                 uint32_t id;
972                 int     i;
973
974                 /* Is there notification on this handle? */
975
976                 if ( !p->notify.client_connected )
977                         continue;
978
979                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
980
981                 /* For this printer?  Print servers always receive
982                    notifications. */
983
984                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
985                     ( !strequal(msg_group->printername, p->sharename) ) )
986                         continue;
987
988                 DEBUG(10,("Our printer\n"));
989
990                 /* allocate the max entries possible */
991
992                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
993                 if (!notifies) {
994                         return;
995                 }
996
997                 /* build the array of change notifications */
998
999                 sending_msg_count = 0;
1000
1001                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1002                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1003
1004                         /* Are we monitoring this event? */
1005
1006                         if (!is_monitoring_event(p, msg->type, msg->field))
1007                                 continue;
1008
1009                         sending_msg_count++;
1010
1011
1012                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1013                                 msg->type, msg->field, p->sharename));
1014
1015                         /*
1016                          * if the is a printer notification handle and not a job notification
1017                          * type, then set the id to 0.  Other wise just use what was specified
1018                          * in the message.
1019                          *
1020                          * When registering change notification on a print server handle
1021                          * we always need to send back the id (snum) matching the printer
1022                          * for which the change took place.  For change notify registered
1023                          * on a printer handle, this does not matter and the id should be 0.
1024                          *
1025                          * --jerry
1026                          */
1027
1028                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1029                                 id = 0;
1030                         else
1031                                 id = msg->id;
1032
1033
1034                         /* Convert unix jobid to smb jobid */
1035
1036                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1037                                 id = sysjob_to_jobid(msg->id);
1038
1039                                 if (id == -1) {
1040                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1041                                         goto done;
1042                                 }
1043                         }
1044
1045                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1046
1047                         switch(msg->type) {
1048                         case PRINTER_NOTIFY_TYPE:
1049                                 if ( printer_notify_table[msg->field].fn )
1050                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1051                                 break;
1052
1053                         case JOB_NOTIFY_TYPE:
1054                                 if ( job_notify_table[msg->field].fn )
1055                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1056                                 break;
1057
1058                         default:
1059                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1060                                 goto done;
1061                         }
1062
1063                         count++;
1064                 }
1065
1066                 if ( sending_msg_count ) {
1067                         NTSTATUS status;
1068                         WERROR werr;
1069                         union spoolss_ReplyPrinterInfo info;
1070                         struct spoolss_NotifyInfo info0;
1071                         uint32_t reply_result;
1072
1073                         info0.version   = 0x2;
1074                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1075                         info0.count     = count;
1076                         info0.notifies  = notifies;
1077
1078                         info.info0 = &info0;
1079
1080                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1081                                                                      &p->notify.client_hnd,
1082                                                                      p->notify.change, /* color */
1083                                                                      p->notify.flags,
1084                                                                      &reply_result,
1085                                                                      0, /* reply_type, must be 0 */
1086                                                                      info,
1087                                                                      &werr);
1088                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1089                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1090                                         notify_cli_pipe->srv_name_slash,
1091                                         win_errstr(werr)));
1092                         }
1093                         switch (reply_result) {
1094                                 case 0:
1095                                         break;
1096                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1097                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1098                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1099                                         break;
1100                                 default:
1101                                         break;
1102                         }
1103                 }
1104         }
1105
1106 done:
1107         DEBUG(8,("send_notify2_changes: Exit...\n"));
1108         return;
1109 }
1110
1111 /***********************************************************************
1112  **********************************************************************/
1113
1114 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1115 {
1116
1117         uint32_t tv_sec, tv_usec;
1118         size_t offset = 0;
1119
1120         /* Unpack message */
1121
1122         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1123                              msg->printer);
1124
1125         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1126                                 &tv_sec, &tv_usec,
1127                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1128
1129         if (msg->len == 0)
1130                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1131                            &msg->notify.value[0], &msg->notify.value[1]);
1132         else
1133                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1134                            &msg->len, &msg->notify.data);
1135
1136         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1137                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1138
1139         tv->tv_sec = tv_sec;
1140         tv->tv_usec = tv_usec;
1141
1142         if (msg->len == 0)
1143                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1144                           msg->notify.value[1]));
1145         else
1146                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1147
1148         return true;
1149 }
1150
1151 /********************************************************************
1152  Receive a notify2 message list
1153  ********************************************************************/
1154
1155 static void receive_notify2_message_list(struct messaging_context *msg,
1156                                          void *private_data,
1157                                          uint32_t msg_type,
1158                                          struct server_id server_id,
1159                                          DATA_BLOB *data)
1160 {
1161         size_t                  msg_count, i;
1162         char                    *buf = (char *)data->data;
1163         char                    *msg_ptr;
1164         size_t                  msg_len;
1165         SPOOLSS_NOTIFY_MSG      notify;
1166         SPOOLSS_NOTIFY_MSG_CTR  messages;
1167         int                     num_groups;
1168
1169         if (data->length < 4) {
1170                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1171                 return;
1172         }
1173
1174         msg_count = IVAL(buf, 0);
1175         msg_ptr = buf + 4;
1176
1177         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1178
1179         if (msg_count == 0) {
1180                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1181                 return;
1182         }
1183
1184         /* initialize the container */
1185
1186         ZERO_STRUCT( messages );
1187         notify_msg_ctr_init( &messages );
1188
1189         /*
1190          * build message groups for each printer identified
1191          * in a change_notify msg.  Remember that a PCN message
1192          * includes the handle returned for the srv_spoolss_replyopenprinter()
1193          * call.  Therefore messages are grouped according to printer handle.
1194          */
1195
1196         for ( i=0; i<msg_count; i++ ) {
1197                 struct timeval msg_tv;
1198
1199                 if (msg_ptr + 4 - buf > data->length) {
1200                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1201                         return;
1202                 }
1203
1204                 msg_len = IVAL(msg_ptr,0);
1205                 msg_ptr += 4;
1206
1207                 if (msg_ptr + msg_len - buf > data->length) {
1208                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1209                         return;
1210                 }
1211
1212                 /* unpack messages */
1213
1214                 ZERO_STRUCT( notify );
1215                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1216                 msg_ptr += msg_len;
1217
1218                 /* add to correct list in container */
1219
1220                 notify_msg_ctr_addmsg( &messages, &notify );
1221
1222                 /* free memory that might have been allocated by notify2_unpack_msg() */
1223
1224                 if ( notify.len != 0 )
1225                         SAFE_FREE( notify.notify.data );
1226         }
1227
1228         /* process each group of messages */
1229
1230         num_groups = notify_msg_ctr_numgroups( &messages );
1231         for ( i=0; i<num_groups; i++ )
1232                 send_notify2_changes( &messages, i );
1233
1234
1235         /* cleanup */
1236
1237         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1238                 (uint32_t)msg_count ));
1239
1240         notify_msg_ctr_destroy( &messages );
1241
1242         return;
1243 }
1244
1245 /********************************************************************
1246  Send a message to ourself about new driver being installed
1247  so we can upgrade the information for each printer bound to this
1248  driver
1249  ********************************************************************/
1250
1251 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1252 {
1253         int len = strlen(drivername);
1254
1255         if (!len)
1256                 return false;
1257
1258         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1259                 drivername));
1260
1261         messaging_send_buf(smbd_messaging_context(), procid_self(),
1262                            MSG_PRINTER_DRVUPGRADE,
1263                            (uint8_t *)drivername, len+1);
1264
1265         return true;
1266 }
1267
1268 /**********************************************************************
1269  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1270  over all printers, upgrading ones as necessary
1271  **********************************************************************/
1272
1273 void do_drv_upgrade_printer(struct messaging_context *msg,
1274                             void *private_data,
1275                             uint32_t msg_type,
1276                             struct server_id server_id,
1277                             DATA_BLOB *data)
1278 {
1279         fstring drivername;
1280         int snum;
1281         int n_services = lp_numservices();
1282         size_t len;
1283
1284         len = MIN(data->length,sizeof(drivername)-1);
1285         strncpy(drivername, (const char *)data->data, len);
1286
1287         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1288
1289         /* Iterate the printer list */
1290
1291         for (snum=0; snum<n_services; snum++)
1292         {
1293                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1294                 {
1295                         WERROR result;
1296                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1297
1298                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1299                         if (!W_ERROR_IS_OK(result))
1300                                 continue;
1301
1302                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1303                         {
1304                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1305
1306                                 /* all we care about currently is the change_id */
1307
1308                                 result = mod_a_printer(printer, 2);
1309                                 if (!W_ERROR_IS_OK(result)) {
1310                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1311                                                 win_errstr(result)));
1312                                 }
1313                         }
1314
1315                         free_a_printer(&printer, 2);
1316                 }
1317         }
1318
1319         /* all done */
1320 }
1321
1322 /********************************************************************
1323  Update the cache for all printq's with a registered client
1324  connection
1325  ********************************************************************/
1326
1327 void update_monitored_printq_cache( void )
1328 {
1329         Printer_entry *printer = printers_list;
1330         int snum;
1331
1332         /* loop through all printers and update the cache where
1333            client_connected == true */
1334         while ( printer )
1335         {
1336                 if ( (printer->printer_type == SPLHND_PRINTER)
1337                         && printer->notify.client_connected )
1338                 {
1339                         snum = print_queue_snum(printer->sharename);
1340                         print_queue_status( snum, NULL, NULL );
1341                 }
1342
1343                 printer = printer->next;
1344         }
1345
1346         return;
1347 }
1348 /********************************************************************
1349  Send a message to ourself about new driver being installed
1350  so we can upgrade the information for each printer bound to this
1351  driver
1352  ********************************************************************/
1353
1354 static bool srv_spoolss_reset_printerdata(char* drivername)
1355 {
1356         int len = strlen(drivername);
1357
1358         if (!len)
1359                 return false;
1360
1361         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1362                 drivername));
1363
1364         messaging_send_buf(smbd_messaging_context(), procid_self(),
1365                            MSG_PRINTERDATA_INIT_RESET,
1366                            (uint8_t *)drivername, len+1);
1367
1368         return true;
1369 }
1370
1371 /**********************************************************************
1372  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1373  over all printers, resetting printer data as neessary
1374  **********************************************************************/
1375
1376 void reset_all_printerdata(struct messaging_context *msg,
1377                            void *private_data,
1378                            uint32_t msg_type,
1379                            struct server_id server_id,
1380                            DATA_BLOB *data)
1381 {
1382         fstring drivername;
1383         int snum;
1384         int n_services = lp_numservices();
1385         size_t len;
1386
1387         len = MIN( data->length, sizeof(drivername)-1 );
1388         strncpy( drivername, (const char *)data->data, len );
1389
1390         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1391
1392         /* Iterate the printer list */
1393
1394         for ( snum=0; snum<n_services; snum++ )
1395         {
1396                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1397                 {
1398                         WERROR result;
1399                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1400
1401                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1402                         if ( !W_ERROR_IS_OK(result) )
1403                                 continue;
1404
1405                         /*
1406                          * if the printer is bound to the driver,
1407                          * then reset to the new driver initdata
1408                          */
1409
1410                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1411                         {
1412                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1413
1414                                 if ( !set_driver_init(printer, 2) ) {
1415                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1416                                                 printer->info_2->printername, printer->info_2->drivername));
1417                                 }
1418
1419                                 result = mod_a_printer( printer, 2 );
1420                                 if ( !W_ERROR_IS_OK(result) ) {
1421                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1422                                                 get_dos_error_msg(result)));
1423                                 }
1424                         }
1425
1426                         free_a_printer( &printer, 2 );
1427                 }
1428         }
1429
1430         /* all done */
1431
1432         return;
1433 }
1434
1435 /****************************************************************
1436  _spoolss_OpenPrinter
1437 ****************************************************************/
1438
1439 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1440                             struct spoolss_OpenPrinter *r)
1441 {
1442         struct spoolss_OpenPrinterEx e;
1443         WERROR werr;
1444
1445         ZERO_STRUCT(e.in.userlevel);
1446
1447         e.in.printername        = r->in.printername;
1448         e.in.datatype           = r->in.datatype;
1449         e.in.devmode_ctr        = r->in.devmode_ctr;
1450         e.in.access_mask        = r->in.access_mask;
1451         e.in.level              = 0;
1452
1453         e.out.handle            = r->out.handle;
1454
1455         werr = _spoolss_OpenPrinterEx(p, &e);
1456
1457         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1458                 /* OpenPrinterEx returns this for a bad
1459                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1460                  * instead.
1461                  */
1462                 werr = WERR_INVALID_PRINTER_NAME;
1463         }
1464
1465         return werr;
1466 }
1467
1468 /********************************************************************
1469  ********************************************************************/
1470
1471 bool convert_devicemode(const char *printername,
1472                         const struct spoolss_DeviceMode *devmode,
1473                         NT_DEVICEMODE **pp_nt_devmode)
1474 {
1475         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1476
1477         /*
1478          * Ensure nt_devmode is a valid pointer
1479          * as we will be overwriting it.
1480          */
1481
1482         if (nt_devmode == NULL) {
1483                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1484                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1485                         return false;
1486         }
1487
1488         fstrcpy(nt_devmode->devicename, devmode->devicename);
1489         fstrcpy(nt_devmode->formname, devmode->formname);
1490
1491         nt_devmode->devicename[31] = '\0';
1492         nt_devmode->formname[31] = '\0';
1493
1494         nt_devmode->specversion         = devmode->specversion;
1495         nt_devmode->driverversion       = devmode->driverversion;
1496         nt_devmode->size                = devmode->size;
1497         nt_devmode->fields              = devmode->fields;
1498         nt_devmode->orientation         = devmode->orientation;
1499         nt_devmode->papersize           = devmode->papersize;
1500         nt_devmode->paperlength         = devmode->paperlength;
1501         nt_devmode->paperwidth          = devmode->paperwidth;
1502         nt_devmode->scale               = devmode->scale;
1503         nt_devmode->copies              = devmode->copies;
1504         nt_devmode->defaultsource       = devmode->defaultsource;
1505         nt_devmode->printquality        = devmode->printquality;
1506         nt_devmode->color               = devmode->color;
1507         nt_devmode->duplex              = devmode->duplex;
1508         nt_devmode->yresolution         = devmode->yresolution;
1509         nt_devmode->ttoption            = devmode->ttoption;
1510         nt_devmode->collate             = devmode->collate;
1511
1512         nt_devmode->logpixels           = devmode->logpixels;
1513         nt_devmode->bitsperpel          = devmode->bitsperpel;
1514         nt_devmode->pelswidth           = devmode->pelswidth;
1515         nt_devmode->pelsheight          = devmode->pelsheight;
1516         nt_devmode->displayflags        = devmode->displayflags;
1517         nt_devmode->displayfrequency    = devmode->displayfrequency;
1518         nt_devmode->icmmethod           = devmode->icmmethod;
1519         nt_devmode->icmintent           = devmode->icmintent;
1520         nt_devmode->mediatype           = devmode->mediatype;
1521         nt_devmode->dithertype          = devmode->dithertype;
1522         nt_devmode->reserved1           = devmode->reserved1;
1523         nt_devmode->reserved2           = devmode->reserved2;
1524         nt_devmode->panningwidth        = devmode->panningwidth;
1525         nt_devmode->panningheight       = devmode->panningheight;
1526
1527         /*
1528          * Only change private and driverextra if the incoming devmode
1529          * has a new one. JRA.
1530          */
1531
1532         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1533                 SAFE_FREE(nt_devmode->nt_dev_private);
1534                 nt_devmode->driverextra = devmode->__driverextra_length;
1535                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1536                         return false;
1537                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1538         }
1539
1540         *pp_nt_devmode = nt_devmode;
1541
1542         return true;
1543 }
1544
1545 /****************************************************************
1546  _spoolss_OpenPrinterEx
1547 ****************************************************************/
1548
1549 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1550                               struct spoolss_OpenPrinterEx *r)
1551 {
1552         int snum;
1553         Printer_entry *Printer=NULL;
1554
1555         if (!r->in.printername) {
1556                 return WERR_INVALID_PARAM;
1557         }
1558
1559         /* some sanity check because you can open a printer or a print server */
1560         /* aka: \\server\printer or \\server */
1561
1562         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1563
1564         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1565                 ZERO_STRUCTP(r->out.handle);
1566                 return WERR_INVALID_PARAM;
1567         }
1568
1569         Printer = find_printer_index_by_hnd(p, r->out.handle);
1570         if ( !Printer ) {
1571                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1572                         "handle we created for printer %s\n", r->in.printername));
1573                 close_printer_handle(p, r->out.handle);
1574                 ZERO_STRUCTP(r->out.handle);
1575                 return WERR_INVALID_PARAM;
1576         }
1577
1578         /*
1579          * First case: the user is opening the print server:
1580          *
1581          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1582          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1583          *
1584          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1585          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1586          * or if the user is listed in the smb.conf printer admin parameter.
1587          *
1588          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1589          * client view printer folder, but does not show the MSAPW.
1590          *
1591          * Note: this test needs code to check access rights here too. Jeremy
1592          * could you look at this?
1593          *
1594          * Second case: the user is opening a printer:
1595          * NT doesn't let us connect to a printer if the connecting user
1596          * doesn't have print permission.
1597          *
1598          * Third case: user is opening a Port Monitor
1599          * access checks same as opening a handle to the print server.
1600          */
1601
1602         switch (Printer->printer_type )
1603         {
1604         case SPLHND_SERVER:
1605         case SPLHND_PORTMON_TCP:
1606         case SPLHND_PORTMON_LOCAL:
1607                 /* Printserver handles use global struct... */
1608
1609                 snum = -1;
1610
1611                 /* Map standard access rights to object specific access rights */
1612
1613                 se_map_standard(&r->in.access_mask,
1614                                 &printserver_std_mapping);
1615
1616                 /* Deny any object specific bits that don't apply to print
1617                    servers (i.e printer and job specific bits) */
1618
1619                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1620
1621                 if (r->in.access_mask &
1622                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1623                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1624                         close_printer_handle(p, r->out.handle);
1625                         ZERO_STRUCTP(r->out.handle);
1626                         return WERR_ACCESS_DENIED;
1627                 }
1628
1629                 /* Allow admin access */
1630
1631                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1632                 {
1633                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1634
1635                         if (!lp_ms_add_printer_wizard()) {
1636                                 close_printer_handle(p, r->out.handle);
1637                                 ZERO_STRUCTP(r->out.handle);
1638                                 return WERR_ACCESS_DENIED;
1639                         }
1640
1641                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1642                            and not a printer admin, then fail */
1643
1644                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1645                             !user_has_privileges(p->server_info->ptok,
1646                                                  &se_printop ) &&
1647                             !token_contains_name_in_list(
1648                                     uidtoname(p->server_info->utok.uid),
1649                                     NULL, NULL,
1650                                     p->server_info->ptok,
1651                                     lp_printer_admin(snum))) {
1652                                 close_printer_handle(p, r->out.handle);
1653                                 ZERO_STRUCTP(r->out.handle);
1654                                 return WERR_ACCESS_DENIED;
1655                         }
1656
1657                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1658                 }
1659                 else
1660                 {
1661                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1662                 }
1663
1664                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1665                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1666
1667                 /* We fall through to return WERR_OK */
1668                 break;
1669
1670         case SPLHND_PRINTER:
1671                 /* NT doesn't let us connect to a printer if the connecting user
1672                    doesn't have print permission.  */
1673
1674                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1675                         close_printer_handle(p, r->out.handle);
1676                         ZERO_STRUCTP(r->out.handle);
1677                         return WERR_BADFID;
1678                 }
1679
1680                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1681                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1682                 }
1683
1684                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1685
1686                 /* map an empty access mask to the minimum access mask */
1687                 if (r->in.access_mask == 0x0)
1688                         r->in.access_mask = PRINTER_ACCESS_USE;
1689
1690                 /*
1691                  * If we are not serving the printer driver for this printer,
1692                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1693                  * will keep NT clients happy  --jerry
1694                  */
1695
1696                 if (lp_use_client_driver(snum)
1697                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1698                 {
1699                         r->in.access_mask = PRINTER_ACCESS_USE;
1700                 }
1701
1702                 /* check smb.conf parameters and the the sec_desc */
1703
1704                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1705                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1706                         ZERO_STRUCTP(r->out.handle);
1707                         return WERR_ACCESS_DENIED;
1708                 }
1709
1710                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1711                                    p->server_info->ptok, snum) ||
1712                     !print_access_check(p->server_info, snum,
1713                                         r->in.access_mask)) {
1714                         DEBUG(3, ("access DENIED for printer open\n"));
1715                         close_printer_handle(p, r->out.handle);
1716                         ZERO_STRUCTP(r->out.handle);
1717                         return WERR_ACCESS_DENIED;
1718                 }
1719
1720                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1721                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1722                         close_printer_handle(p, r->out.handle);
1723                         ZERO_STRUCTP(r->out.handle);
1724                         return WERR_ACCESS_DENIED;
1725                 }
1726
1727                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1728                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1729                 else
1730                         r->in.access_mask = PRINTER_ACCESS_USE;
1731
1732                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1733                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1734
1735                 break;
1736
1737         default:
1738                 /* sanity check to prevent programmer error */
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return WERR_BADFID;
1741         }
1742
1743         Printer->access_granted = r->in.access_mask;
1744
1745         /*
1746          * If the client sent a devmode in the OpenPrinter() call, then
1747          * save it here in case we get a job submission on this handle
1748          */
1749
1750          if ((Printer->printer_type != SPLHND_SERVER) &&
1751              r->in.devmode_ctr.devmode) {
1752                 convert_devicemode(Printer->sharename,
1753                                    r->in.devmode_ctr.devmode,
1754                                    &Printer->nt_devmode);
1755          }
1756
1757 #if 0   /* JERRY -- I'm doubtful this is really effective */
1758         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1759            optimization in Windows 2000 clients  --jerry */
1760
1761         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1762                 && (RA_WIN2K == get_remote_arch()) )
1763         {
1764                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1765                 sys_usleep( 500000 );
1766         }
1767 #endif
1768
1769         return WERR_OK;
1770 }
1771
1772 /****************************************************************************
1773 ****************************************************************************/
1774
1775 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1776                                               NT_PRINTER_INFO_LEVEL_2 *d)
1777 {
1778         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1779
1780         if (!r || !d) {
1781                 return false;
1782         }
1783
1784         d->attributes           = r->attributes;
1785         d->priority             = r->priority;
1786         d->default_priority     = r->defaultpriority;
1787         d->starttime            = r->starttime;
1788         d->untiltime            = r->untiltime;
1789         d->status               = r->status;
1790         d->cjobs                = r->cjobs;
1791
1792         fstrcpy(d->servername,  r->servername);
1793         fstrcpy(d->printername, r->printername);
1794         fstrcpy(d->sharename,   r->sharename);
1795         fstrcpy(d->portname,    r->portname);
1796         fstrcpy(d->drivername,  r->drivername);
1797         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1798         fstrcpy(d->location,    r->location);
1799         fstrcpy(d->sepfile,     r->sepfile);
1800         fstrcpy(d->printprocessor, r->printprocessor);
1801         fstrcpy(d->datatype,    r->datatype);
1802         fstrcpy(d->parameters,  r->parameters);
1803
1804         return true;
1805 }
1806
1807 /****************************************************************************
1808 ****************************************************************************/
1809
1810 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1811                                  NT_PRINTER_INFO_LEVEL *printer)
1812 {
1813         bool ret;
1814
1815         switch (info_ctr->level) {
1816         case 2:
1817                 /* allocate memory if needed.  Messy because
1818                    convert_printer_info is used to update an existing
1819                    printer or build a new one */
1820
1821                 if (!printer->info_2) {
1822                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1823                         if (!printer->info_2) {
1824                                 DEBUG(0,("convert_printer_info: "
1825                                         "talloc() failed!\n"));
1826                                 return false;
1827                         }
1828                 }
1829
1830                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1831                                                         printer->info_2);
1832                 printer->info_2->setuptime = time(NULL);
1833                 return ret;
1834         }
1835
1836         return false;
1837 }
1838
1839 /****************************************************************
1840  _spoolss_ClosePrinter
1841 ****************************************************************/
1842
1843 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1844                              struct spoolss_ClosePrinter *r)
1845 {
1846         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1847
1848         if (Printer && Printer->document_started) {
1849                 struct spoolss_EndDocPrinter e;
1850
1851                 e.in.handle = r->in.handle;
1852
1853                 _spoolss_EndDocPrinter(p, &e);
1854         }
1855
1856         if (!close_printer_handle(p, r->in.handle))
1857                 return WERR_BADFID;
1858
1859         /* clear the returned printer handle.  Observed behavior
1860            from Win2k server.  Don't think this really matters.
1861            Previous code just copied the value of the closed
1862            handle.    --jerry */
1863
1864         ZERO_STRUCTP(r->out.handle);
1865
1866         return WERR_OK;
1867 }
1868
1869 /****************************************************************
1870  _spoolss_DeletePrinter
1871 ****************************************************************/
1872
1873 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1874                               struct spoolss_DeletePrinter *r)
1875 {
1876         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1877         WERROR result;
1878
1879         if (Printer && Printer->document_started) {
1880                 struct spoolss_EndDocPrinter e;
1881
1882                 e.in.handle = r->in.handle;
1883
1884                 _spoolss_EndDocPrinter(p, &e);
1885         }
1886
1887         result = delete_printer_handle(p, r->in.handle);
1888
1889         update_c_setprinter(false);
1890
1891         return result;
1892 }
1893
1894 /*******************************************************************
1895  * static function to lookup the version id corresponding to an
1896  * long architecture string
1897  ******************************************************************/
1898
1899 static const struct print_architecture_table_node archi_table[]= {
1900
1901         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1902         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1903         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1904         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1905         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1906         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1907         {"Windows x64",          SPL_ARCH_X64,          3 },
1908         {NULL,                   "",            -1 }
1909 };
1910
1911 static int get_version_id(const char *arch)
1912 {
1913         int i;
1914
1915         for (i=0; archi_table[i].long_archi != NULL; i++)
1916         {
1917                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1918                         return (archi_table[i].version);
1919         }
1920
1921         return -1;
1922 }
1923
1924 /****************************************************************
1925  _spoolss_DeletePrinterDriver
1926 ****************************************************************/
1927
1928 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1929                                     struct spoolss_DeletePrinterDriver *r)
1930 {
1931
1932         struct spoolss_DriverInfo8 *info = NULL;
1933         struct spoolss_DriverInfo8 *info_win2k = NULL;
1934         int                             version;
1935         WERROR                          status;
1936         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1937         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1938
1939         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1940            and not a printer admin, then fail */
1941
1942         if ( (p->server_info->utok.uid != sec_initial_uid())
1943                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1944                 && !token_contains_name_in_list(
1945                         uidtoname(p->server_info->utok.uid), NULL,
1946                         NULL, p->server_info->ptok,
1947                         lp_printer_admin(-1)) )
1948         {
1949                 return WERR_ACCESS_DENIED;
1950         }
1951
1952         /* check that we have a valid driver name first */
1953
1954         if ((version = get_version_id(r->in.architecture)) == -1)
1955                 return WERR_INVALID_ENVIRONMENT;
1956
1957         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1958                                                 r->in.architecture,
1959                                                 version)))
1960         {
1961                 /* try for Win2k driver if "Windows NT x86" */
1962
1963                 if ( version == 2 ) {
1964                         version = 3;
1965                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1966                                                                 &info,
1967                                                                 r->in.driver,
1968                                                                 r->in.architecture,
1969                                                                 version))) {
1970                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1971                                 goto done;
1972                         }
1973                 }
1974                 /* otherwise it was a failure */
1975                 else {
1976                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1977                         goto done;
1978                 }
1979
1980         }
1981
1982         if (printer_driver_in_use(info)) {
1983                 status = WERR_PRINTER_DRIVER_IN_USE;
1984                 goto done;
1985         }
1986
1987         if ( version == 2 )
1988         {
1989                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1990                                                        &info_win2k,
1991                                                        r->in.driver,
1992                                                        r->in.architecture, 3)))
1993                 {
1994                         /* if we get to here, we now have 2 driver info structures to remove */
1995                         /* remove the Win2k driver first*/
1996
1997                         status_win2k = delete_printer_driver(
1998                                 p, info_win2k, 3, false);
1999                         free_a_printer_driver(info_win2k);
2000
2001                         /* this should not have failed---if it did, report to client */
2002                         if ( !W_ERROR_IS_OK(status_win2k) )
2003                         {
2004                                 status = status_win2k;
2005                                 goto done;
2006                         }
2007                 }
2008         }
2009
2010         status = delete_printer_driver(p, info, version, false);
2011
2012         /* if at least one of the deletes succeeded return OK */
2013
2014         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2015                 status = WERR_OK;
2016
2017 done:
2018         free_a_printer_driver(info);
2019
2020         return status;
2021 }
2022
2023 /****************************************************************
2024  _spoolss_DeletePrinterDriverEx
2025 ****************************************************************/
2026
2027 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2028                                       struct spoolss_DeletePrinterDriverEx *r)
2029 {
2030         struct spoolss_DriverInfo8      *info = NULL;
2031         struct spoolss_DriverInfo8      *info_win2k = NULL;
2032         int                             version;
2033         bool                            delete_files;
2034         WERROR                          status;
2035         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2036         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2037
2038         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2039            and not a printer admin, then fail */
2040
2041         if ( (p->server_info->utok.uid != sec_initial_uid())
2042                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2043                 && !token_contains_name_in_list(
2044                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2045                         p->server_info->ptok, lp_printer_admin(-1)) )
2046         {
2047                 return WERR_ACCESS_DENIED;
2048         }
2049
2050         /* check that we have a valid driver name first */
2051         if ((version = get_version_id(r->in.architecture)) == -1) {
2052                 /* this is what NT returns */
2053                 return WERR_INVALID_ENVIRONMENT;
2054         }
2055
2056         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2057                 version = r->in.version;
2058
2059         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2060                                       r->in.architecture, version);
2061
2062         if ( !W_ERROR_IS_OK(status) )
2063         {
2064                 /*
2065                  * if the client asked for a specific version,
2066                  * or this is something other than Windows NT x86,
2067                  * then we've failed
2068                  */
2069
2070                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2071                         goto done;
2072
2073                 /* try for Win2k driver if "Windows NT x86" */
2074
2075                 version = 3;
2076                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2077                                                         r->in.architecture,
2078                                                         version))) {
2079                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2080                         goto done;
2081                 }
2082         }
2083
2084         if (printer_driver_in_use(info)) {
2085                 status = WERR_PRINTER_DRIVER_IN_USE;
2086                 goto done;
2087         }
2088
2089         /*
2090          * we have a couple of cases to consider.
2091          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2092          *     then the delete should fail if **any** files overlap with
2093          *     other drivers
2094          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2095          *     non-overlapping files
2096          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2097          *     is set, the do not delete any files
2098          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2099          */
2100
2101         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2102
2103         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2104
2105         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2106                 /* no idea of the correct error here */
2107                 status = WERR_ACCESS_DENIED;
2108                 goto done;
2109         }
2110
2111
2112         /* also check for W32X86/3 if necessary; maybe we already have? */
2113
2114         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2115                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2116                                                        r->in.driver,
2117                                                        r->in.architecture, 3)))
2118                 {
2119
2120                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2121                                 /* no idea of the correct error here */
2122                                 free_a_printer_driver(info_win2k);
2123                                 status = WERR_ACCESS_DENIED;
2124                                 goto done;
2125                         }
2126
2127                         /* if we get to here, we now have 2 driver info structures to remove */
2128                         /* remove the Win2k driver first*/
2129
2130                         status_win2k = delete_printer_driver(
2131                                 p, info_win2k, 3, delete_files);
2132                         free_a_printer_driver(info_win2k);
2133
2134                         /* this should not have failed---if it did, report to client */
2135
2136                         if ( !W_ERROR_IS_OK(status_win2k) )
2137                                 goto done;
2138                 }
2139         }
2140
2141         status = delete_printer_driver(p, info, version, delete_files);
2142
2143         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2144                 status = WERR_OK;
2145 done:
2146         free_a_printer_driver(info);
2147
2148         return status;
2149 }
2150
2151
2152 /****************************************************************************
2153  Internal routine for removing printerdata
2154  ***************************************************************************/
2155
2156 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2157 {
2158         return delete_printer_data( printer->info_2, key, value );
2159 }
2160
2161 /****************************************************************************
2162  Internal routine for storing printerdata
2163  ***************************************************************************/
2164
2165 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2166                           const char *key, const char *value,
2167                           uint32_t type, uint8_t *data, int real_len)
2168 {
2169         /* the registry objects enforce uniqueness based on value name */
2170
2171         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2172 }
2173
2174 /********************************************************************
2175  GetPrinterData on a printer server Handle.
2176 ********************************************************************/
2177
2178 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2179                                             const char *value,
2180                                             enum winreg_Type *type,
2181                                             union spoolss_PrinterData *data)
2182 {
2183         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2184
2185         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2186                 *type = REG_DWORD;
2187                 data->value = 0x00;
2188                 return WERR_OK;
2189         }
2190
2191         if (!StrCaseCmp(value, "BeepEnabled")) {
2192                 *type = REG_DWORD;
2193                 data->value = 0x00;
2194                 return WERR_OK;
2195         }
2196
2197         if (!StrCaseCmp(value, "EventLog")) {
2198                 *type = REG_DWORD;
2199                 /* formally was 0x1b */
2200                 data->value = 0x00;
2201                 return WERR_OK;
2202         }
2203
2204         if (!StrCaseCmp(value, "NetPopup")) {
2205                 *type = REG_DWORD;
2206                 data->value = 0x00;
2207                 return WERR_OK;
2208         }
2209
2210         if (!StrCaseCmp(value, "MajorVersion")) {
2211                 *type = REG_DWORD;
2212
2213                 /* Windows NT 4.0 seems to not allow uploading of drivers
2214                    to a server that reports 0x3 as the MajorVersion.
2215                    need to investigate more how Win2k gets around this .
2216                    -- jerry */
2217
2218                 if (RA_WINNT == get_remote_arch()) {
2219                         data->value = 0x02;
2220                 } else {
2221                         data->value = 0x03;
2222                 }
2223
2224                 return WERR_OK;
2225         }
2226
2227         if (!StrCaseCmp(value, "MinorVersion")) {
2228                 *type = REG_DWORD;
2229                 data->value = 0x00;
2230                 return WERR_OK;
2231         }
2232
2233         /* REG_BINARY
2234          *  uint32_t size        = 0x114
2235          *  uint32_t major       = 5
2236          *  uint32_t minor       = [0|1]
2237          *  uint32_t build       = [2195|2600]
2238          *  extra unicode string = e.g. "Service Pack 3"
2239          */
2240         if (!StrCaseCmp(value, "OSVersion")) {
2241                 DATA_BLOB blob;
2242                 enum ndr_err_code ndr_err;
2243                 struct spoolss_OSVersion os;
2244
2245                 os.major                = 5;    /* Windows 2000 == 5.0 */
2246                 os.minor                = 0;
2247                 os.build                = 2195; /* build */
2248                 os.extra_string         = "";   /* leave extra string empty */
2249
2250                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2251                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2252                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2253                         return WERR_GENERAL_FAILURE;
2254                 }
2255
2256                 *type = REG_BINARY;
2257                 data->binary = blob;
2258
2259                 return WERR_OK;
2260         }
2261
2262
2263         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2264                 *type = REG_SZ;
2265
2266                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2267                 W_ERROR_HAVE_NO_MEMORY(data->string);
2268
2269                 return WERR_OK;
2270         }
2271
2272         if (!StrCaseCmp(value, "Architecture")) {
2273                 *type = REG_SZ;
2274                 data->string = talloc_strdup(mem_ctx,
2275                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2276                 W_ERROR_HAVE_NO_MEMORY(data->string);
2277
2278                 return WERR_OK;
2279         }
2280
2281         if (!StrCaseCmp(value, "DsPresent")) {
2282                 *type = REG_DWORD;
2283
2284                 /* only show the publish check box if we are a
2285                    member of a AD domain */
2286
2287                 if (lp_security() == SEC_ADS) {
2288                         data->value = 0x01;
2289                 } else {
2290                         data->value = 0x00;
2291                 }
2292                 return WERR_OK;
2293         }
2294
2295         if (!StrCaseCmp(value, "DNSMachineName")) {
2296                 const char *hostname = get_mydnsfullname();
2297
2298                 if (!hostname) {
2299                         return WERR_BADFILE;
2300                 }
2301
2302                 *type = REG_SZ;
2303                 data->string = talloc_strdup(mem_ctx, hostname);
2304                 W_ERROR_HAVE_NO_MEMORY(data->string);
2305
2306                 return WERR_OK;
2307         }
2308
2309         *type = REG_NONE;
2310
2311         return WERR_INVALID_PARAM;
2312 }
2313
2314 /****************************************************************
2315  _spoolss_GetPrinterData
2316 ****************************************************************/
2317
2318 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2319                                struct spoolss_GetPrinterData *r)
2320 {
2321         struct spoolss_GetPrinterDataEx r2;
2322
2323         r2.in.handle            = r->in.handle;
2324         r2.in.key_name          = "PrinterDriverData";
2325         r2.in.value_name        = r->in.value_name;
2326         r2.in.offered           = r->in.offered;
2327         r2.out.type             = r->out.type;
2328         r2.out.data             = r->out.data;
2329         r2.out.needed           = r->out.needed;
2330
2331         return _spoolss_GetPrinterDataEx(p, &r2);
2332 }
2333
2334 /*********************************************************
2335  Connect to the client machine.
2336 **********************************************************/
2337
2338 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2339                         struct sockaddr_storage *client_ss, const char *remote_machine)
2340 {
2341         NTSTATUS ret;
2342         struct cli_state *the_cli;
2343         struct sockaddr_storage rm_addr;
2344         char addr[INET6_ADDRSTRLEN];
2345
2346         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2347                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2348                         remote_machine));
2349                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2350                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2351                         return false;
2352                 }
2353                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2354         } else {
2355                 rm_addr = *client_ss;
2356                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2357                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2358                         addr));
2359         }
2360
2361         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2362                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2363                         addr));
2364                 return false;
2365         }
2366
2367         /* setup the connection */
2368         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2369                 &rm_addr, 0, "IPC$", "IPC",
2370                 "", /* username */
2371                 "", /* domain */
2372                 "", /* password */
2373                 0, lp_client_signing(), NULL );
2374
2375         if ( !NT_STATUS_IS_OK( ret ) ) {
2376                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2377                         remote_machine ));
2378                 return false;
2379         }
2380
2381         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2382                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2383                 cli_shutdown(the_cli);
2384                 return false;
2385         }
2386
2387         /*
2388          * Ok - we have an anonymous connection to the IPC$ share.
2389          * Now start the NT Domain stuff :-).
2390          */
2391
2392         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2393         if (!NT_STATUS_IS_OK(ret)) {
2394                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2395                         remote_machine, nt_errstr(ret)));
2396                 cli_shutdown(the_cli);
2397                 return false;
2398         }
2399
2400         return true;
2401 }
2402
2403 /***************************************************************************
2404  Connect to the client.
2405 ****************************************************************************/
2406
2407 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2408                                         uint32_t localprinter, uint32_t type,
2409                                         struct policy_handle *handle,
2410                                         struct sockaddr_storage *client_ss)
2411 {
2412         WERROR result;
2413         NTSTATUS status;
2414
2415         /*
2416          * If it's the first connection, contact the client
2417          * and connect to the IPC$ share anonymously
2418          */
2419         if (smb_connections==0) {
2420                 fstring unix_printer;
2421
2422                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2423
2424                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2425                         return false;
2426
2427                 messaging_register(smbd_messaging_context(), NULL,
2428                                    MSG_PRINTER_NOTIFY2,
2429                                    receive_notify2_message_list);
2430                 /* Tell the connections db we're now interested in printer
2431                  * notify messages. */
2432                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2433         }
2434
2435         /*
2436          * Tell the specific printing tdb we want messages for this printer
2437          * by registering our PID.
2438          */
2439
2440         if (!print_notify_register_pid(snum))
2441                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2442
2443         smb_connections++;
2444
2445         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2446                                                  printer,
2447                                                  localprinter,
2448                                                  type,
2449                                                  0,
2450                                                  NULL,
2451                                                  handle,
2452                                                  &result);
2453         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2454                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2455                         win_errstr(result)));
2456
2457         return (W_ERROR_IS_OK(result));
2458 }
2459
2460 /****************************************************************
2461  ****************************************************************/
2462
2463 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2464                                                              const struct spoolss_NotifyOption *r)
2465 {
2466         struct spoolss_NotifyOption *option;
2467         uint32_t i,k;
2468
2469         if (!r) {
2470                 return NULL;
2471         }
2472
2473         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2474         if (!option) {
2475                 return NULL;
2476         }
2477
2478         *option = *r;
2479
2480         if (!option->count) {
2481                 return option;
2482         }
2483
2484         option->types = talloc_zero_array(option,
2485                 struct spoolss_NotifyOptionType, option->count);
2486         if (!option->types) {
2487                 talloc_free(option);
2488                 return NULL;
2489         }
2490
2491         for (i=0; i < option->count; i++) {
2492                 option->types[i] = r->types[i];
2493
2494                 if (option->types[i].count) {
2495                         option->types[i].fields = talloc_zero_array(option,
2496                                 union spoolss_Field, option->types[i].count);
2497                         if (!option->types[i].fields) {
2498                                 talloc_free(option);
2499                                 return NULL;
2500                         }
2501                         for (k=0; k<option->types[i].count; k++) {
2502                                 option->types[i].fields[k] =
2503                                         r->types[i].fields[k];
2504                         }
2505                 }
2506         }
2507
2508         return option;
2509 }
2510
2511 /****************************************************************
2512  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2513  *
2514  * before replying OK: status=0 a rpc call is made to the workstation
2515  * asking ReplyOpenPrinter
2516  *
2517  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2518  * called from api_spoolss_rffpcnex
2519 ****************************************************************/
2520
2521 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2522                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2523 {
2524         int snum = -1;
2525         struct spoolss_NotifyOption *option = r->in.notify_options;
2526         struct sockaddr_storage client_ss;
2527
2528         /* store the notify value in the printer struct */
2529
2530         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2531
2532         if (!Printer) {
2533                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2534                         "Invalid handle (%s:%u:%u).\n",
2535                         OUR_HANDLE(r->in.handle)));
2536                 return WERR_BADFID;
2537         }
2538
2539         Printer->notify.flags           = r->in.flags;
2540         Printer->notify.options         = r->in.options;
2541         Printer->notify.printerlocal    = r->in.printer_local;
2542
2543         TALLOC_FREE(Printer->notify.option);
2544         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2545
2546         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2547
2548         /* Connect to the client machine and send a ReplyOpenPrinter */
2549
2550         if ( Printer->printer_type == SPLHND_SERVER)
2551                 snum = -1;
2552         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2553                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2554                 return WERR_BADFID;
2555
2556         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2557                 "client_address is %s\n", p->client_address));
2558
2559         if (!interpret_string_addr(&client_ss, p->client_address,
2560                                    AI_NUMERICHOST)) {
2561                 return WERR_SERVER_UNAVAILABLE;
2562         }
2563
2564         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2565                                         Printer->notify.printerlocal, 1,
2566                                         &Printer->notify.client_hnd, &client_ss))
2567                 return WERR_SERVER_UNAVAILABLE;
2568
2569         Printer->notify.client_connected = true;
2570
2571         return WERR_OK;
2572 }
2573
2574 /*******************************************************************
2575  * fill a notify_info_data with the servername
2576  ********************************************************************/
2577
2578 void spoolss_notify_server_name(int snum,
2579                                        struct spoolss_Notify *data,
2580                                        print_queue_struct *queue,
2581                                        NT_PRINTER_INFO_LEVEL *printer,
2582                                        TALLOC_CTX *mem_ctx)
2583 {
2584         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2585 }
2586
2587 /*******************************************************************
2588  * fill a notify_info_data with the printername (not including the servername).
2589  ********************************************************************/
2590
2591 void spoolss_notify_printer_name(int snum,
2592                                         struct spoolss_Notify *data,
2593                                         print_queue_struct *queue,
2594                                         NT_PRINTER_INFO_LEVEL *printer,
2595                                         TALLOC_CTX *mem_ctx)
2596 {
2597         /* the notify name should not contain the \\server\ part */
2598         char *p = strrchr(printer->info_2->printername, '\\');
2599
2600         if (!p) {
2601                 p = printer->info_2->printername;
2602         } else {
2603                 p++;
2604         }
2605
2606         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2607 }
2608
2609 /*******************************************************************
2610  * fill a notify_info_data with the servicename
2611  ********************************************************************/
2612
2613 void spoolss_notify_share_name(int snum,
2614                                       struct spoolss_Notify *data,
2615                                       print_queue_struct *queue,
2616                                       NT_PRINTER_INFO_LEVEL *printer,
2617                                       TALLOC_CTX *mem_ctx)
2618 {
2619         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2620 }
2621
2622 /*******************************************************************
2623  * fill a notify_info_data with the port name
2624  ********************************************************************/
2625
2626 void spoolss_notify_port_name(int snum,
2627                                      struct spoolss_Notify *data,
2628                                      print_queue_struct *queue,
2629                                      NT_PRINTER_INFO_LEVEL *printer,
2630                                      TALLOC_CTX *mem_ctx)
2631 {
2632         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2633 }
2634
2635 /*******************************************************************
2636  * fill a notify_info_data with the printername
2637  * but it doesn't exist, have to see what to do
2638  ********************************************************************/
2639
2640 void spoolss_notify_driver_name(int snum,
2641                                        struct spoolss_Notify *data,
2642                                        print_queue_struct *queue,
2643                                        NT_PRINTER_INFO_LEVEL *printer,
2644                                        TALLOC_CTX *mem_ctx)
2645 {
2646         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2647 }
2648
2649 /*******************************************************************
2650  * fill a notify_info_data with the comment
2651  ********************************************************************/
2652
2653 void spoolss_notify_comment(int snum,
2654                                    struct spoolss_Notify *data,
2655                                    print_queue_struct *queue,
2656                                    NT_PRINTER_INFO_LEVEL *printer,
2657                                    TALLOC_CTX *mem_ctx)
2658 {
2659         char *p;
2660
2661         if (*printer->info_2->comment == '\0') {
2662                 p = lp_comment(snum);
2663         } else {
2664                 p = printer->info_2->comment;
2665         }
2666
2667         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2668 }
2669
2670 /*******************************************************************
2671  * fill a notify_info_data with the comment
2672  * location = "Room 1, floor 2, building 3"
2673  ********************************************************************/
2674
2675 void spoolss_notify_location(int snum,
2676                                     struct spoolss_Notify *data,
2677                                     print_queue_struct *queue,
2678                                     NT_PRINTER_INFO_LEVEL *printer,
2679                                     TALLOC_CTX *mem_ctx)
2680 {
2681         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2682 }
2683
2684 /*******************************************************************
2685  * fill a notify_info_data with the device mode
2686  * jfm:xxxx don't to it for know but that's a real problem !!!
2687  ********************************************************************/
2688
2689 static void spoolss_notify_devmode(int snum,
2690                                    struct spoolss_Notify *data,
2691                                    print_queue_struct *queue,
2692                                    NT_PRINTER_INFO_LEVEL *printer,
2693                                    TALLOC_CTX *mem_ctx)
2694 {
2695         /* for a dummy implementation we have to zero the fields */
2696         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2697 }
2698
2699 /*******************************************************************
2700  * fill a notify_info_data with the separator file name
2701  ********************************************************************/
2702
2703 void spoolss_notify_sepfile(int snum,
2704                                    struct spoolss_Notify *data,
2705                                    print_queue_struct *queue,
2706                                    NT_PRINTER_INFO_LEVEL *printer,
2707                                    TALLOC_CTX *mem_ctx)
2708 {
2709         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2710 }
2711
2712 /*******************************************************************
2713  * fill a notify_info_data with the print processor
2714  * jfm:xxxx return always winprint to indicate we don't do anything to it
2715  ********************************************************************/
2716
2717 void spoolss_notify_print_processor(int snum,
2718                                            struct spoolss_Notify *data,
2719                                            print_queue_struct *queue,
2720                                            NT_PRINTER_INFO_LEVEL *printer,
2721                                            TALLOC_CTX *mem_ctx)
2722 {
2723         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2724 }
2725
2726 /*******************************************************************
2727  * fill a notify_info_data with the print processor options
2728  * jfm:xxxx send an empty string
2729  ********************************************************************/
2730
2731 void spoolss_notify_parameters(int snum,
2732                                       struct spoolss_Notify *data,
2733                                       print_queue_struct *queue,
2734                                       NT_PRINTER_INFO_LEVEL *printer,
2735                                       TALLOC_CTX *mem_ctx)
2736 {
2737         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2738 }
2739
2740 /*******************************************************************
2741  * fill a notify_info_data with the data type
2742  * jfm:xxxx always send RAW as data type
2743  ********************************************************************/
2744
2745 void spoolss_notify_datatype(int snum,
2746                                     struct spoolss_Notify *data,
2747                                     print_queue_struct *queue,
2748                                     NT_PRINTER_INFO_LEVEL *printer,
2749                                     TALLOC_CTX *mem_ctx)
2750 {
2751         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2752 }
2753
2754 /*******************************************************************
2755  * fill a notify_info_data with the security descriptor
2756  * jfm:xxxx send an null pointer to say no security desc
2757  * have to implement security before !
2758  ********************************************************************/
2759
2760 static void spoolss_notify_security_desc(int snum,
2761                                          struct spoolss_Notify *data,
2762                                          print_queue_struct *queue,
2763                                          NT_PRINTER_INFO_LEVEL *printer,
2764                                          TALLOC_CTX *mem_ctx)
2765 {
2766         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2767                                           printer->info_2->secdesc_buf->sd_size,
2768                                           printer->info_2->secdesc_buf->sd);
2769 }
2770
2771 /*******************************************************************
2772  * fill a notify_info_data with the attributes
2773  * jfm:xxxx a samba printer is always shared
2774  ********************************************************************/
2775
2776 void spoolss_notify_attributes(int snum,
2777                                       struct spoolss_Notify *data,
2778                                       print_queue_struct *queue,
2779                                       NT_PRINTER_INFO_LEVEL *printer,
2780                                       TALLOC_CTX *mem_ctx)
2781 {
2782         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2783 }
2784
2785 /*******************************************************************
2786  * fill a notify_info_data with the priority
2787  ********************************************************************/
2788
2789 static void spoolss_notify_priority(int snum,
2790                                     struct spoolss_Notify *data,
2791                                     print_queue_struct *queue,
2792                                     NT_PRINTER_INFO_LEVEL *printer,
2793                                     TALLOC_CTX *mem_ctx)
2794 {
2795         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2796 }
2797
2798 /*******************************************************************
2799  * fill a notify_info_data with the default priority
2800  ********************************************************************/
2801
2802 static void spoolss_notify_default_priority(int snum,
2803                                             struct spoolss_Notify *data,
2804                                             print_queue_struct *queue,
2805                                             NT_PRINTER_INFO_LEVEL *printer,
2806                                             TALLOC_CTX *mem_ctx)
2807 {
2808         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2809 }
2810
2811 /*******************************************************************
2812  * fill a notify_info_data with the start time
2813  ********************************************************************/
2814
2815 static void spoolss_notify_start_time(int snum,
2816                                       struct spoolss_Notify *data,
2817                                       print_queue_struct *queue,
2818                                       NT_PRINTER_INFO_LEVEL *printer,
2819                                       TALLOC_CTX *mem_ctx)
2820 {
2821         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2822 }
2823
2824 /*******************************************************************
2825  * fill a notify_info_data with the until time
2826  ********************************************************************/
2827
2828 static void spoolss_notify_until_time(int snum,
2829                                       struct spoolss_Notify *data,
2830                                       print_queue_struct *queue,
2831                                       NT_PRINTER_INFO_LEVEL *printer,
2832                                       TALLOC_CTX *mem_ctx)
2833 {
2834         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2835 }
2836
2837 /*******************************************************************
2838  * fill a notify_info_data with the status
2839  ********************************************************************/
2840
2841 static void spoolss_notify_status(int snum,
2842                                   struct spoolss_Notify *data,
2843                                   print_queue_struct *queue,
2844                                   NT_PRINTER_INFO_LEVEL *printer,
2845                                   TALLOC_CTX *mem_ctx)
2846 {
2847         print_status_struct status;
2848
2849         print_queue_length(snum, &status);
2850         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2851 }
2852
2853 /*******************************************************************
2854  * fill a notify_info_data with the number of jobs queued
2855  ********************************************************************/
2856
2857 void spoolss_notify_cjobs(int snum,
2858                                  struct spoolss_Notify *data,
2859                                  print_queue_struct *queue,
2860                                  NT_PRINTER_INFO_LEVEL *printer,
2861                                  TALLOC_CTX *mem_ctx)
2862 {
2863         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2864 }
2865
2866 /*******************************************************************
2867  * fill a notify_info_data with the average ppm
2868  ********************************************************************/
2869
2870 static void spoolss_notify_average_ppm(int snum,
2871                                        struct spoolss_Notify *data,
2872                                        print_queue_struct *queue,
2873                                        NT_PRINTER_INFO_LEVEL *printer,
2874                                        TALLOC_CTX *mem_ctx)
2875 {
2876         /* always respond 8 pages per minutes */
2877         /* a little hard ! */
2878         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with username
2883  ********************************************************************/
2884
2885 static void spoolss_notify_username(int snum,
2886                                     struct spoolss_Notify *data,
2887                                     print_queue_struct *queue,
2888                                     NT_PRINTER_INFO_LEVEL *printer,
2889                                     TALLOC_CTX *mem_ctx)
2890 {
2891         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2892 }
2893
2894 /*******************************************************************
2895  * fill a notify_info_data with job status
2896  ********************************************************************/
2897
2898 static void spoolss_notify_job_status(int snum,
2899                                       struct spoolss_Notify *data,
2900                                       print_queue_struct *queue,
2901                                       NT_PRINTER_INFO_LEVEL *printer,
2902                                       TALLOC_CTX *mem_ctx)
2903 {
2904         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2905 }
2906
2907 /*******************************************************************
2908  * fill a notify_info_data with job name
2909  ********************************************************************/
2910
2911 static void spoolss_notify_job_name(int snum,
2912                                     struct spoolss_Notify *data,
2913                                     print_queue_struct *queue,
2914                                     NT_PRINTER_INFO_LEVEL *printer,
2915                                     TALLOC_CTX *mem_ctx)
2916 {
2917         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2918 }
2919
2920 /*******************************************************************
2921  * fill a notify_info_data with job status
2922  ********************************************************************/
2923
2924 static void spoolss_notify_job_status_string(int snum,
2925                                              struct spoolss_Notify *data,
2926                                              print_queue_struct *queue,
2927                                              NT_PRINTER_INFO_LEVEL *printer,
2928                                              TALLOC_CTX *mem_ctx)
2929 {
2930         /*
2931          * Now we're returning job status codes we just return a "" here. JRA.
2932          */
2933
2934         const char *p = "";
2935
2936 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2937         p = "unknown";
2938
2939         switch (queue->status) {
2940         case LPQ_QUEUED:
2941                 p = "Queued";
2942                 break;
2943         case LPQ_PAUSED:
2944                 p = "";    /* NT provides the paused string */
2945                 break;
2946         case LPQ_SPOOLING:
2947                 p = "Spooling";
2948                 break;
2949         case LPQ_PRINTING:
2950                 p = "Printing";
2951                 break;
2952         }
2953 #endif /* NO LONGER NEEDED. */
2954
2955         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2956 }
2957
2958 /*******************************************************************
2959  * fill a notify_info_data with job time
2960  ********************************************************************/
2961
2962 static void spoolss_notify_job_time(int snum,
2963                                     struct spoolss_Notify *data,
2964                                     print_queue_struct *queue,
2965                                     NT_PRINTER_INFO_LEVEL *printer,
2966                                     TALLOC_CTX *mem_ctx)
2967 {
2968         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2969 }
2970
2971 /*******************************************************************
2972  * fill a notify_info_data with job size
2973  ********************************************************************/
2974
2975 static void spoolss_notify_job_size(int snum,
2976                                     struct spoolss_Notify *data,
2977                                     print_queue_struct *queue,
2978                                     NT_PRINTER_INFO_LEVEL *printer,
2979                                     TALLOC_CTX *mem_ctx)
2980 {
2981         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2982 }
2983
2984 /*******************************************************************
2985  * fill a notify_info_data with page info
2986  ********************************************************************/
2987 static void spoolss_notify_total_pages(int snum,
2988                                 struct spoolss_Notify *data,
2989                                 print_queue_struct *queue,
2990                                 NT_PRINTER_INFO_LEVEL *printer,
2991                                 TALLOC_CTX *mem_ctx)
2992 {
2993         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2994 }
2995
2996 /*******************************************************************
2997  * fill a notify_info_data with pages printed info.
2998  ********************************************************************/
2999 static void spoolss_notify_pages_printed(int snum,
3000                                 struct spoolss_Notify *data,
3001                                 print_queue_struct *queue,
3002                                 NT_PRINTER_INFO_LEVEL *printer,
3003                                 TALLOC_CTX *mem_ctx)
3004 {
3005         /* Add code when back-end tracks this */
3006         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3007 }
3008
3009 /*******************************************************************
3010  Fill a notify_info_data with job position.
3011  ********************************************************************/
3012
3013 static void spoolss_notify_job_position(int snum,
3014                                         struct spoolss_Notify *data,
3015                                         print_queue_struct *queue,
3016                                         NT_PRINTER_INFO_LEVEL *printer,
3017                                         TALLOC_CTX *mem_ctx)
3018 {
3019         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3020 }
3021
3022 /*******************************************************************
3023  Fill a notify_info_data with submitted time.
3024  ********************************************************************/
3025
3026 static void spoolss_notify_submitted_time(int snum,
3027                                           struct spoolss_Notify *data,
3028                                           print_queue_struct *queue,
3029                                           NT_PRINTER_INFO_LEVEL *printer,
3030                                           TALLOC_CTX *mem_ctx)
3031 {
3032         data->data.string.string = NULL;
3033         data->data.string.size = 0;
3034
3035         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3036                                &data->data.string.string,
3037                                &data->data.string.size);
3038
3039 }
3040
3041 struct s_notify_info_data_table
3042 {
3043         enum spoolss_NotifyType type;
3044         uint16_t field;
3045         const char *name;
3046         enum spoolss_NotifyTable variable_type;
3047         void (*fn) (int snum, struct spoolss_Notify *data,
3048                     print_queue_struct *queue,
3049                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3050 };
3051
3052 /* A table describing the various print notification constants and
3053    whether the notification data is a pointer to a variable sized
3054    buffer, a one value uint32_t or a two value uint32_t. */
3055
3056 static const struct s_notify_info_data_table notify_info_data_table[] =
3057 {
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3083 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3084 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3085 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3086 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3087 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3088 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3100 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3101 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3102 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3103 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3104 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3105 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3106 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3107 };
3108
3109 /*******************************************************************
3110  Return the variable_type of info_data structure.
3111 ********************************************************************/
3112
3113 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3114                                                   uint16_t field)
3115 {
3116         int i=0;
3117
3118         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3119                 if ( (notify_info_data_table[i].type == type) &&
3120                      (notify_info_data_table[i].field == field) ) {
3121                         return notify_info_data_table[i].variable_type;
3122                 }
3123         }
3124
3125         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3126
3127         return 0;
3128 }
3129
3130 /****************************************************************************
3131 ****************************************************************************/
3132
3133 static bool search_notify(enum spoolss_NotifyType type,
3134                           uint16_t field,
3135                           int *value)
3136 {
3137         int i;
3138
3139         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3140                 if (notify_info_data_table[i].type == type &&
3141                     notify_info_data_table[i].field == field &&
3142                     notify_info_data_table[i].fn != NULL) {
3143                         *value = i;
3144                         return true;
3145                 }
3146         }
3147
3148         return false;
3149 }
3150
3151 /****************************************************************************
3152 ****************************************************************************/
3153
3154 void construct_info_data(struct spoolss_Notify *info_data,
3155                          enum spoolss_NotifyType type,
3156                          uint16_t field,
3157                          int id)
3158 {
3159         info_data->type                 = type;
3160         info_data->field.field          = field;
3161         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3162         info_data->job_id               = id;
3163 }
3164
3165 /*******************************************************************
3166  *
3167  * fill a notify_info struct with info asked
3168  *
3169  ********************************************************************/
3170
3171 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3172                                           struct spoolss_NotifyInfo *info,
3173                                           int snum,
3174                                           const struct spoolss_NotifyOptionType *option_type,
3175                                           uint32_t id,
3176                                           TALLOC_CTX *mem_ctx)
3177 {
3178         int field_num,j;
3179         enum spoolss_NotifyType type;
3180         uint16_t field;
3181
3182         struct spoolss_Notify *current_data;
3183         NT_PRINTER_INFO_LEVEL *printer = NULL;
3184         print_queue_struct *queue=NULL;
3185
3186         type = option_type->type;
3187
3188         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3189                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3190                 option_type->count, lp_servicename(snum)));
3191
3192         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3193                 return false;
3194
3195         for(field_num=0; field_num < option_type->count; field_num++) {
3196                 field = option_type->fields[field_num].field;
3197
3198                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3199
3200                 if (!search_notify(type, field, &j) )
3201                         continue;
3202
3203                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3204                                                       struct spoolss_Notify,
3205                                                       info->count + 1);
3206                 if (info->notifies == NULL) {
3207                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3208                         free_a_printer(&printer, 2);
3209                         return false;
3210                 }
3211
3212                 current_data = &info->notifies[info->count];
3213
3214                 construct_info_data(current_data, type, field, id);
3215
3216                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3217                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3218
3219                 notify_info_data_table[j].fn(snum, current_data, queue,
3220                                              printer, mem_ctx);
3221
3222                 info->count++;
3223         }
3224
3225         free_a_printer(&printer, 2);
3226         return true;
3227 }
3228
3229 /*******************************************************************
3230  *
3231  * fill a notify_info struct with info asked
3232  *
3233  ********************************************************************/
3234
3235 static bool construct_notify_jobs_info(print_queue_struct *queue,
3236                                        struct spoolss_NotifyInfo *info,
3237                                        NT_PRINTER_INFO_LEVEL *printer,
3238                                        int snum,
3239                                        const struct spoolss_NotifyOptionType *option_type,
3240                                        uint32_t id,
3241                                        TALLOC_CTX *mem_ctx)
3242 {
3243         int field_num,j;
3244         enum spoolss_NotifyType type;
3245         uint16_t field;
3246         struct spoolss_Notify *current_data;
3247
3248         DEBUG(4,("construct_notify_jobs_info\n"));
3249
3250         type = option_type->type;
3251
3252         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3253                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3254                 option_type->count));
3255
3256         for(field_num=0; field_num<option_type->count; field_num++) {
3257                 field = option_type->fields[field_num].field;
3258
3259                 if (!search_notify(type, field, &j) )
3260                         continue;
3261
3262                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3263                                                       struct spoolss_Notify,
3264                                                       info->count + 1);
3265                 if (info->notifies == NULL) {
3266                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3267                         return false;
3268                 }
3269
3270                 current_data=&(info->notifies[info->count]);
3271
3272                 construct_info_data(current_data, type, field, id);
3273                 notify_info_data_table[j].fn(snum, current_data, queue,
3274                                              printer, mem_ctx);
3275                 info->count++;
3276         }
3277
3278         return true;
3279 }
3280
3281 /*
3282  * JFM: The enumeration is not that simple, it's even non obvious.
3283  *
3284  * let's take an example: I want to monitor the PRINTER SERVER for
3285  * the printer's name and the number of jobs currently queued.
3286  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3287  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3288  *
3289  * I have 3 printers on the back of my server.
3290  *
3291  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3292  * structures.
3293  *   Number     Data                    Id
3294  *      1       printer 1 name          1
3295  *      2       printer 1 cjob          1
3296  *      3       printer 2 name          2
3297  *      4       printer 2 cjob          2
3298  *      5       printer 3 name          3
3299  *      6       printer 3 name          3
3300  *
3301  * that's the print server case, the printer case is even worse.
3302  */
3303
3304 /*******************************************************************
3305  *
3306  * enumerate all printers on the printserver
3307  * fill a notify_info struct with info asked
3308  *
3309  ********************************************************************/
3310
3311 static WERROR printserver_notify_info(pipes_struct *p,
3312                                       struct policy_handle *hnd,
3313                                       struct spoolss_NotifyInfo *info,
3314                                       TALLOC_CTX *mem_ctx)
3315 {
3316         int snum;
3317         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3318         int n_services=lp_numservices();
3319         int i;
3320         struct spoolss_NotifyOption *option;
3321         struct spoolss_NotifyOptionType option_type;
3322
3323         DEBUG(4,("printserver_notify_info\n"));
3324
3325         if (!Printer)
3326                 return WERR_BADFID;
3327
3328         option = Printer->notify.option;
3329
3330         info->version   = 2;
3331         info->notifies  = NULL;
3332         info->count     = 0;
3333
3334         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3335            sending a ffpcn() request first */
3336
3337         if ( !option )
3338                 return WERR_BADFID;
3339
3340         for (i=0; i<option->count; i++) {
3341                 option_type = option->types[i];
3342
3343                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3344                         continue;
3345
3346                 for (snum=0; snum<n_services; snum++)
3347                 {
3348                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3349                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3350                 }
3351         }
3352
3353 #if 0
3354         /*
3355          * Debugging information, don't delete.
3356          */
3357
3358         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3359         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3360         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3361
3362         for (i=0; i<info->count; i++) {
3363                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3364                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3365                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3366         }
3367 #endif
3368
3369         return WERR_OK;
3370 }
3371
3372 /*******************************************************************
3373  *
3374  * fill a notify_info struct with info asked
3375  *
3376  ********************************************************************/
3377
3378 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3379                                   struct spoolss_NotifyInfo *info,
3380                                   TALLOC_CTX *mem_ctx)
3381 {
3382         int snum;
3383         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3384         int i;
3385         uint32_t id;
3386         struct spoolss_NotifyOption *option;
3387         struct spoolss_NotifyOptionType option_type;
3388         int count,j;
3389         print_queue_struct *queue=NULL;
3390         print_status_struct status;
3391
3392         DEBUG(4,("printer_notify_info\n"));
3393
3394         if (!Printer)
3395                 return WERR_BADFID;
3396
3397         option = Printer->notify.option;
3398         id = 0x0;
3399
3400         info->version   = 2;
3401         info->notifies  = NULL;
3402         info->count     = 0;
3403
3404         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3405            sending a ffpcn() request first */
3406
3407         if ( !option )
3408                 return WERR_BADFID;
3409
3410         get_printer_snum(p, hnd, &snum, NULL);
3411
3412         for (i=0; i<option->count; i++) {
3413                 option_type = option->types[i];
3414
3415                 switch (option_type.type) {
3416                 case PRINTER_NOTIFY_TYPE:
3417                         if(construct_notify_printer_info(Printer, info, snum,
3418                                                          &option_type, id,
3419                                                          mem_ctx))
3420                                 id--;
3421                         break;
3422
3423                 case JOB_NOTIFY_TYPE: {
3424                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3425
3426                         count = print_queue_status(snum, &queue, &status);
3427
3428                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3429                                 goto done;
3430
3431                         for (j=0; j<count; j++) {
3432                                 construct_notify_jobs_info(&queue[j], info,
3433                                                            printer, snum,
3434                                                            &option_type,
3435                                                            queue[j].job,
3436                                                            mem_ctx);
3437                         }
3438
3439                         free_a_printer(&printer, 2);
3440
3441                 done:
3442                         SAFE_FREE(queue);
3443                         break;
3444                 }
3445                 }
3446         }
3447
3448         /*
3449          * Debugging information, don't delete.
3450          */
3451         /*
3452         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3453         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3454         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3455
3456         for (i=0; i<info->count; i++) {
3457                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3458                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3459                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3460         }
3461         */
3462         return WERR_OK;
3463 }
3464
3465 /****************************************************************
3466  _spoolss_RouterRefreshPrinterChangeNotify
3467 ****************************************************************/
3468
3469 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3470                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3471 {
3472         struct spoolss_NotifyInfo *info;
3473
3474         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3475         WERROR result = WERR_BADFID;
3476
3477         /* we always have a spoolss_NotifyInfo struct */
3478         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3479         if (!info) {
3480                 result = WERR_NOMEM;
3481                 goto done;
3482         }
3483
3484         *r->out.info = info;
3485
3486         if (!Printer) {
3487                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3488                         "Invalid handle (%s:%u:%u).\n",
3489                         OUR_HANDLE(r->in.handle)));
3490                 goto done;
3491         }
3492
3493         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3494
3495         /*
3496          *      We are now using the change value, and
3497          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3498          *      I don't have a global notification system, I'm sending back all the
3499          *      informations even when _NOTHING_ has changed.
3500          */
3501
3502         /* We need to keep track of the change value to send back in
3503            RRPCN replies otherwise our updates are ignored. */
3504
3505         Printer->notify.fnpcn = true;
3506
3507         if (Printer->notify.client_connected) {
3508                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3509                         "Saving change value in request [%x]\n",
3510                         r->in.change_low));
3511                 Printer->notify.change = r->in.change_low;
3512         }
3513
3514         /* just ignore the spoolss_NotifyOption */
3515
3516         switch (Printer->printer_type) {
3517                 case SPLHND_SERVER:
3518                         result = printserver_notify_info(p, r->in.handle,
3519                                                          info, p->mem_ctx);
3520                         break;
3521
3522                 case SPLHND_PRINTER:
3523                         result = printer_notify_info(p, r->in.handle,
3524                                                      info, p->mem_ctx);
3525                         break;
3526         }
3527
3528         Printer->notify.fnpcn = false;
3529
3530 done:
3531         return result;
3532 }
3533
3534 /********************************************************************
3535  * construct_printer_info_0
3536  * fill a printer_info_0 struct
3537  ********************************************************************/
3538
3539 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3540                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3541                                       struct spoolss_PrinterInfo0 *r,
3542                                       int snum)
3543 {
3544         int count;
3545         counter_printer_0 *session_counter;
3546         time_t setuptime;
3547         print_status_struct status;
3548
3549         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3550         W_ERROR_HAVE_NO_MEMORY(r->printername);
3551
3552         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3553         W_ERROR_HAVE_NO_MEMORY(r->servername);
3554
3555         count = print_queue_length(snum, &status);
3556
3557         /* check if we already have a counter for this printer */
3558         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3559                 if (session_counter->snum == snum)
3560                         break;
3561         }
3562
3563         /* it's the first time, add it to the list */
3564         if (session_counter == NULL) {
3565                 session_counter = SMB_MALLOC_P(counter_printer_0);
3566                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3567                 ZERO_STRUCTP(session_counter);
3568                 session_counter->snum           = snum;
3569                 session_counter->counter        = 0;
3570                 DLIST_ADD(counter_list, session_counter);
3571         }
3572
3573         /* increment it */
3574         session_counter->counter++;
3575
3576         r->cjobs                        = count;
3577         r->total_jobs                   = 0;
3578         r->total_bytes                  = 0;
3579
3580         setuptime = (time_t)ntprinter->info_2->setuptime;
3581
3582         init_systemtime(&r->time, gmtime(&setuptime));
3583
3584         /* JFM:
3585          * the global_counter should be stored in a TDB as it's common to all the clients
3586          * and should be zeroed on samba startup
3587          */
3588         r->global_counter               = session_counter->counter;
3589         r->total_pages                  = 0;
3590         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3591         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3592         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3593         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3594         r->spooling                     = 0;
3595         r->max_spooling                 = 0;
3596         r->session_counter              = session_counter->counter;
3597         r->num_error_out_of_paper       = 0x0;
3598         r->num_error_not_ready          = 0x0;          /* number of print failure */
3599         r->job_error                    = 0x0;
3600         r->number_of_processors         = 0x1;
3601         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3602         r->high_part_total_bytes        = 0x0;
3603         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3604         r->last_error                   = WERR_OK;
3605         r->status                       = nt_printq_status(status.status);
3606         r->enumerate_network_printers   = 0x0;
3607         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3608         r->processor_architecture       = 0x0;
3609         r->processor_level              = 0x6;          /* 6  ???*/
3610         r->ref_ic                       = 0;
3611         r->reserved2                    = 0;
3612         r->reserved3                    = 0;
3613
3614         return WERR_OK;
3615 }
3616
3617 /****************************************************************************
3618  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3619  should be valid upon entry
3620 ****************************************************************************/
3621
3622 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3623                                     struct spoolss_DeviceMode *r,
3624                                     const NT_DEVICEMODE *ntdevmode)
3625 {
3626         if (!r || !ntdevmode) {
3627                 return WERR_INVALID_PARAM;
3628         }
3629
3630         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3631         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3632
3633         r->specversion          = ntdevmode->specversion;
3634         r->driverversion        = ntdevmode->driverversion;
3635         r->size                 = ntdevmode->size;
3636         r->__driverextra_length = ntdevmode->driverextra;
3637         r->fields               = ntdevmode->fields;
3638
3639         r->orientation          = ntdevmode->orientation;
3640         r->papersize            = ntdevmode->papersize;
3641         r->paperlength          = ntdevmode->paperlength;
3642         r->paperwidth           = ntdevmode->paperwidth;
3643         r->scale                = ntdevmode->scale;
3644         r->copies               = ntdevmode->copies;
3645         r->defaultsource        = ntdevmode->defaultsource;
3646         r->printquality         = ntdevmode->printquality;
3647         r->color                = ntdevmode->color;
3648         r->duplex               = ntdevmode->duplex;
3649         r->yresolution          = ntdevmode->yresolution;
3650         r->ttoption             = ntdevmode->ttoption;
3651         r->collate              = ntdevmode->collate;
3652
3653         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3654         W_ERROR_HAVE_NO_MEMORY(r->formname);
3655
3656         r->logpixels            = ntdevmode->logpixels;
3657         r->bitsperpel           = ntdevmode->bitsperpel;
3658         r->pelswidth            = ntdevmode->pelswidth;
3659         r->pelsheight           = ntdevmode->pelsheight;
3660         r->displayflags         = ntdevmode->displayflags;
3661         r->displayfrequency     = ntdevmode->displayfrequency;
3662         r->icmmethod            = ntdevmode->icmmethod;
3663         r->icmintent            = ntdevmode->icmintent;
3664         r->mediatype            = ntdevmode->mediatype;
3665         r->dithertype           = ntdevmode->dithertype;
3666         r->reserved1            = ntdevmode->reserved1;
3667         r->reserved2            = ntdevmode->reserved2;
3668         r->panningwidth         = ntdevmode->panningwidth;
3669         r->panningheight        = ntdevmode->panningheight;
3670
3671         if (ntdevmode->nt_dev_private != NULL) {
3672                 r->driverextra_data = data_blob_talloc(mem_ctx,
3673                         ntdevmode->nt_dev_private,
3674                         ntdevmode->driverextra);
3675                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3676         }
3677
3678         return WERR_OK;
3679 }
3680
3681
3682 /****************************************************************************
3683  Create a spoolss_DeviceMode struct. Returns talloced memory.
3684 ****************************************************************************/
3685
3686 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3687                                               const char *servicename)
3688 {
3689         WERROR result;
3690         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3691         struct spoolss_DeviceMode *devmode = NULL;
3692
3693         DEBUG(7,("construct_dev_mode\n"));
3694
3695         DEBUGADD(8,("getting printer characteristics\n"));
3696
3697         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3698                 return NULL;
3699
3700         if (!printer->info_2->devmode) {
3701                 DEBUG(5, ("BONG! There was no device mode!\n"));
3702                 goto done;
3703         }
3704
3705         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3706         if (!devmode) {
3707                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3708                 goto done;
3709         }
3710
3711         DEBUGADD(8,("loading DEVICEMODE\n"));
3712
3713         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3714         if (!W_ERROR_IS_OK(result)) {
3715                 TALLOC_FREE(devmode);
3716         }
3717
3718 done:
3719         free_a_printer(&printer,2);
3720
3721         return devmode;
3722 }
3723
3724 /********************************************************************
3725  * construct_printer_info1
3726  * fill a spoolss_PrinterInfo1 struct
3727 ********************************************************************/
3728
3729 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3730                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3731                                       uint32_t flags,
3732                                       struct spoolss_PrinterInfo1 *r,
3733                                       int snum)
3734 {
3735         r->flags                = flags;
3736
3737         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3738                                                   ntprinter->info_2->printername,
3739                                                   ntprinter->info_2->drivername,
3740                                                   ntprinter->info_2->location);
3741         W_ERROR_HAVE_NO_MEMORY(r->description);
3742
3743         if (*ntprinter->info_2->comment == '\0') {
3744                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3745         } else {
3746                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3747         }
3748         W_ERROR_HAVE_NO_MEMORY(r->comment);
3749
3750         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3751         W_ERROR_HAVE_NO_MEMORY(r->name);
3752
3753         return WERR_OK;
3754 }
3755
3756 /********************************************************************
3757  * construct_printer_info2
3758  * fill a spoolss_PrinterInfo2 struct
3759 ********************************************************************/
3760
3761 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3762                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3763                                       struct spoolss_PrinterInfo2 *r,
3764                                       int snum)
3765 {
3766         int count;
3767
3768         print_status_struct status;
3769
3770         count = print_queue_length(snum, &status);
3771
3772         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3773         W_ERROR_HAVE_NO_MEMORY(r->servername);
3774         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3775         W_ERROR_HAVE_NO_MEMORY(r->printername);
3776         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3777         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3778         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3779         W_ERROR_HAVE_NO_MEMORY(r->portname);
3780         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3781         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3782
3783         if (*ntprinter->info_2->comment == '\0') {
3784                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3785         } else {
3786                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3787         }
3788         W_ERROR_HAVE_NO_MEMORY(r->comment);
3789
3790         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3791         W_ERROR_HAVE_NO_MEMORY(r->location);
3792         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3793         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3794         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3795         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3796         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3797         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3798         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3799         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3800
3801         r->attributes           = ntprinter->info_2->attributes;
3802
3803         r->priority             = ntprinter->info_2->priority;
3804         r->defaultpriority      = ntprinter->info_2->default_priority;
3805         r->starttime            = ntprinter->info_2->starttime;
3806         r->untiltime            = ntprinter->info_2->untiltime;
3807         r->status               = nt_printq_status(status.status);
3808         r->cjobs                = count;
3809         r->averageppm           = ntprinter->info_2->averageppm;
3810
3811         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3812         if (!r->devmode) {
3813                 DEBUG(8,("Returning NULL Devicemode!\n"));
3814         }
3815
3816         r->secdesc              = NULL;
3817
3818         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3819                 /* don't use talloc_steal() here unless you do a deep steal of all
3820                    the SEC_DESC members */
3821
3822                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3823         }
3824
3825         return WERR_OK;
3826 }
3827
3828 /********************************************************************
3829  * construct_printer_info3
3830  * fill a spoolss_PrinterInfo3 struct
3831  ********************************************************************/
3832
3833 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3834                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3835                                       struct spoolss_PrinterInfo3 *r,
3836                                       int snum)
3837 {
3838         /* These are the components of the SD we are returning. */
3839
3840         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3841                 /* don't use talloc_steal() here unless you do a deep steal of all
3842                    the SEC_DESC members */
3843
3844                 r->secdesc = dup_sec_desc(mem_ctx,
3845                                           ntprinter->info_2->secdesc_buf->sd);
3846                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3847         }
3848
3849         return WERR_OK;
3850 }
3851
3852 /********************************************************************
3853  * construct_printer_info4
3854  * fill a spoolss_PrinterInfo4 struct
3855  ********************************************************************/
3856
3857 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3858                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3859                                       struct spoolss_PrinterInfo4 *r,
3860                                       int snum)
3861 {
3862         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3863         W_ERROR_HAVE_NO_MEMORY(r->printername);
3864         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3865         W_ERROR_HAVE_NO_MEMORY(r->servername);
3866
3867         r->attributes   = ntprinter->info_2->attributes;
3868
3869         return WERR_OK;
3870 }
3871
3872 /********************************************************************
3873  * construct_printer_info5
3874  * fill a spoolss_PrinterInfo5 struct
3875  ********************************************************************/
3876
3877 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3878                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3879                                       struct spoolss_PrinterInfo5 *r,
3880                                       int snum)
3881 {
3882         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3883         W_ERROR_HAVE_NO_MEMORY(r->printername);
3884         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3885         W_ERROR_HAVE_NO_MEMORY(r->portname);
3886
3887         r->attributes   = ntprinter->info_2->attributes;
3888
3889         /* these two are not used by NT+ according to MSDN */
3890
3891         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3892         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3893
3894         return WERR_OK;
3895 }
3896
3897 /********************************************************************
3898  * construct_printer_info_6
3899  * fill a spoolss_PrinterInfo6 struct
3900  ********************************************************************/
3901
3902 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3903                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3904                                       struct spoolss_PrinterInfo6 *r,
3905                                       int snum)
3906 {
3907         int count;
3908         print_status_struct status;
3909
3910         count = print_queue_length(snum, &status);
3911
3912         r->status = nt_printq_status(status.status);
3913
3914         return WERR_OK;
3915 }
3916
3917 /********************************************************************
3918  * construct_printer_info7
3919  * fill a spoolss_PrinterInfo7 struct
3920  ********************************************************************/
3921
3922 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3923                                       Printer_entry *print_hnd,
3924                                       struct spoolss_PrinterInfo7 *r,
3925                                       int snum)
3926 {
3927         struct GUID guid;
3928
3929         if (is_printer_published(print_hnd, snum, &guid)) {
3930                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3931                 r->action = DSPRINT_PUBLISH;
3932         } else {
3933                 r->guid = talloc_strdup(mem_ctx, "");
3934                 r->action = DSPRINT_UNPUBLISH;
3935         }
3936         W_ERROR_HAVE_NO_MEMORY(r->guid);
3937
3938         return WERR_OK;
3939 }
3940
3941 /********************************************************************
3942  * construct_printer_info8
3943  * fill a spoolss_PrinterInfo8 struct
3944  ********************************************************************/
3945
3946 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3947                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3948                                       struct spoolss_DeviceModeInfo *r,
3949                                       int snum)
3950 {
3951         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3952         if (!r->devmode) {
3953                 DEBUG(8,("Returning NULL Devicemode!\n"));
3954         }
3955
3956         return WERR_OK;
3957 }
3958
3959
3960 /********************************************************************
3961 ********************************************************************/
3962
3963 static bool snum_is_shared_printer(int snum)
3964 {
3965         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3966 }
3967
3968 /********************************************************************
3969  Spoolss_enumprinters.
3970 ********************************************************************/
3971
3972 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3973                                            uint32_t level,
3974                                            uint32_t flags,
3975                                            union spoolss_PrinterInfo **info_p,
3976                                            uint32_t *count_p)
3977 {
3978         int snum;
3979         int n_services = lp_numservices();
3980         union spoolss_PrinterInfo *info = NULL;
3981         uint32_t count = 0;
3982         WERROR result = WERR_OK;
3983
3984         *count_p = 0;
3985         *info_p = NULL;
3986
3987         for (snum = 0; snum < n_services; snum++) {
3988
3989                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3990
3991                 if (!snum_is_shared_printer(snum)) {
3992                         continue;
3993                 }
3994
3995                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3996                         lp_servicename(snum), snum));
3997
3998                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3999                                             union spoolss_PrinterInfo,
4000                                             count + 1);
4001                 if (!info) {
4002                         result = WERR_NOMEM;
4003                         goto out;
4004                 }
4005
4006                 result = get_a_printer(NULL, &ntprinter, 2,
4007                                        lp_const_servicename(snum));
4008                 if (!W_ERROR_IS_OK(result)) {
4009                         goto out;
4010                 }
4011
4012                 switch (level) {
4013                 case 0:
4014                         result = construct_printer_info0(info, ntprinter,
4015                                                          &info[count].info0, snum);
4016                         break;
4017                 case 1:
4018                         result = construct_printer_info1(info, ntprinter, flags,
4019                                                          &info[count].info1, snum);
4020                         break;
4021                 case 2:
4022                         result = construct_printer_info2(info, ntprinter,
4023                                                          &info[count].info2, snum);
4024                         break;
4025                 case 4:
4026                         result = construct_printer_info4(info, ntprinter,
4027                                                          &info[count].info4, snum);
4028                         break;
4029                 case 5:
4030                         result = construct_printer_info5(info, ntprinter,
4031                                                          &info[count].info5, snum);
4032                         break;
4033
4034                 default:
4035                         result = WERR_UNKNOWN_LEVEL;
4036                         free_a_printer(&ntprinter, 2);
4037                         goto out;
4038                 }
4039
4040                 free_a_printer(&ntprinter, 2);
4041                 if (!W_ERROR_IS_OK(result)) {
4042                         goto out;
4043                 }
4044
4045                 count++;
4046         }
4047
4048         *count_p = count;
4049         *info_p = info;
4050
4051  out:
4052         if (!W_ERROR_IS_OK(result)) {
4053                 TALLOC_FREE(info);
4054                 return result;
4055         }
4056
4057         *info_p = info;
4058
4059         return WERR_OK;
4060 }
4061
4062 /********************************************************************
4063  * handle enumeration of printers at level 0
4064  ********************************************************************/
4065
4066 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4067                                   uint32_t flags,
4068                                   const char *servername,
4069                                   union spoolss_PrinterInfo **info,
4070                                   uint32_t *count)
4071 {
4072         DEBUG(4,("enum_all_printers_info_0\n"));
4073
4074         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4075 }
4076
4077
4078 /********************************************************************
4079 ********************************************************************/
4080
4081 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4082                                        uint32_t flags,
4083                                        union spoolss_PrinterInfo **info,
4084                                        uint32_t *count)
4085 {
4086         DEBUG(4,("enum_all_printers_info_1\n"));
4087
4088         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4089 }
4090
4091 /********************************************************************
4092  enum_all_printers_info_1_local.
4093 *********************************************************************/
4094
4095 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4096                                              union spoolss_PrinterInfo **info,
4097                                              uint32_t *count)
4098 {
4099         DEBUG(4,("enum_all_printers_info_1_local\n"));
4100
4101         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4102 }
4103
4104 /********************************************************************
4105  enum_all_printers_info_1_name.
4106 *********************************************************************/
4107
4108 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4109                                             const char *name,
4110                                             union spoolss_PrinterInfo **info,
4111                                             uint32_t *count)
4112 {
4113         const char *s = name;
4114
4115         DEBUG(4,("enum_all_printers_info_1_name\n"));
4116
4117         if ((name[0] == '\\') && (name[1] == '\\')) {
4118                 s = name + 2;
4119         }
4120
4121         if (!is_myname_or_ipaddr(s)) {
4122                 return WERR_INVALID_NAME;
4123         }
4124
4125         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4126 }
4127
4128 /********************************************************************
4129  enum_all_printers_info_1_network.
4130 *********************************************************************/
4131
4132 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4133                                                const char *name,
4134                                                union spoolss_PrinterInfo **info,
4135                                                uint32_t *count)
4136 {
4137         const char *s = name;
4138
4139         DEBUG(4,("enum_all_printers_info_1_network\n"));
4140
4141         /* If we respond to a enum_printers level 1 on our name with flags
4142            set to PRINTER_ENUM_REMOTE with a list of printers then these
4143            printers incorrectly appear in the APW browse list.
4144            Specifically the printers for the server appear at the workgroup
4145            level where all the other servers in the domain are
4146            listed. Windows responds to this call with a
4147            WERR_CAN_NOT_COMPLETE so we should do the same. */
4148
4149         if (name[0] == '\\' && name[1] == '\\') {
4150                  s = name + 2;
4151         }
4152
4153         if (is_myname_or_ipaddr(s)) {
4154                  return WERR_CAN_NOT_COMPLETE;
4155         }
4156
4157         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4158 }
4159
4160 /********************************************************************
4161  * api_spoolss_enumprinters
4162  *
4163  * called from api_spoolss_enumprinters (see this to understand)
4164  ********************************************************************/
4165
4166 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4167                                        union spoolss_PrinterInfo **info,
4168                                        uint32_t *count)
4169 {
4170         DEBUG(4,("enum_all_printers_info_2\n"));
4171
4172         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4173 }
4174
4175 /********************************************************************
4176  * handle enumeration of printers at level 1
4177  ********************************************************************/
4178
4179 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4180                                   uint32_t flags,
4181                                   const char *name,
4182                                   union spoolss_PrinterInfo **info,
4183                                   uint32_t *count)
4184 {
4185         /* Not all the flags are equals */
4186
4187         if (flags & PRINTER_ENUM_LOCAL) {
4188                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4189         }
4190
4191         if (flags & PRINTER_ENUM_NAME) {
4192                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4193         }
4194
4195         if (flags & PRINTER_ENUM_NETWORK) {
4196                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4197         }
4198
4199         return WERR_OK; /* NT4sp5 does that */
4200 }
4201
4202 /********************************************************************
4203  * handle enumeration of printers at level 2
4204  ********************************************************************/
4205
4206 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4207                                   uint32_t flags,
4208                                   const char *servername,
4209                                   union spoolss_PrinterInfo **info,
4210                                   uint32_t *count)
4211 {
4212         if (flags & PRINTER_ENUM_LOCAL) {
4213                 return enum_all_printers_info_2(mem_ctx, info, count);
4214         }
4215
4216         if (flags & PRINTER_ENUM_NAME) {
4217                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4218                         return WERR_INVALID_NAME;
4219                 }
4220
4221                 return enum_all_printers_info_2(mem_ctx, info, count);
4222         }
4223
4224         if (flags & PRINTER_ENUM_REMOTE) {
4225                 return WERR_UNKNOWN_LEVEL;
4226         }
4227
4228         return WERR_OK;
4229 }
4230
4231 /********************************************************************
4232  * handle enumeration of printers at level 4
4233  ********************************************************************/
4234
4235 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4236                                   uint32_t flags,
4237                                   const char *servername,
4238                                   union spoolss_PrinterInfo **info,
4239                                   uint32_t *count)
4240 {
4241         DEBUG(4,("enum_all_printers_info_4\n"));
4242
4243         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4244 }
4245
4246
4247 /********************************************************************
4248  * handle enumeration of printers at level 5
4249  ********************************************************************/
4250
4251 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4252                                   uint32_t flags,
4253                                   const char *servername,
4254                                   union spoolss_PrinterInfo **info,
4255                                   uint32_t *count)
4256 {
4257         DEBUG(4,("enum_all_printers_info_5\n"));
4258
4259         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4260 }
4261
4262 /****************************************************************
4263  _spoolss_EnumPrinters
4264 ****************************************************************/
4265
4266 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4267                              struct spoolss_EnumPrinters *r)
4268 {
4269         const char *name = NULL;
4270         WERROR result;
4271
4272         /* that's an [in out] buffer */
4273
4274         if (!r->in.buffer && (r->in.offered != 0)) {
4275                 return WERR_INVALID_PARAM;
4276         }
4277
4278         DEBUG(4,("_spoolss_EnumPrinters\n"));
4279
4280         *r->out.needed = 0;
4281         *r->out.count = 0;
4282         *r->out.info = NULL;
4283
4284         /*
4285          * Level 1:
4286          *          flags==PRINTER_ENUM_NAME
4287          *           if name=="" then enumerates all printers
4288          *           if name!="" then enumerate the printer
4289          *          flags==PRINTER_ENUM_REMOTE
4290          *          name is NULL, enumerate printers
4291          * Level 2: name!="" enumerates printers, name can't be NULL
4292          * Level 3: doesn't exist
4293          * Level 4: does a local registry lookup
4294          * Level 5: same as Level 2
4295          */
4296
4297         if (r->in.server) {
4298                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4299                 W_ERROR_HAVE_NO_MEMORY(name);
4300         }
4301
4302         switch (r->in.level) {
4303         case 0:
4304                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4305                                              r->out.info, r->out.count);
4306                 break;
4307         case 1:
4308                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4309                                              r->out.info, r->out.count);
4310                 break;
4311         case 2:
4312                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4313                                              r->out.info, r->out.count);
4314                 break;
4315         case 4:
4316                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4317                                              r->out.info, r->out.count);
4318                 break;
4319         case 5:
4320                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4321                                              r->out.info, r->out.count);
4322                 break;
4323         default:
4324                 return WERR_UNKNOWN_LEVEL;
4325         }
4326
4327         if (!W_ERROR_IS_OK(result)) {
4328                 return result;
4329         }
4330
4331         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4332                                                      spoolss_EnumPrinters, NULL,
4333                                                      *r->out.info, r->in.level,
4334                                                      *r->out.count);
4335         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4336         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4337
4338         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4339 }
4340
4341 /****************************************************************
4342  _spoolss_GetPrinter
4343 ****************************************************************/
4344
4345 WERROR _spoolss_GetPrinter(pipes_struct *p,
4346                            struct spoolss_GetPrinter *r)
4347 {
4348         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4349         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4350         WERROR result = WERR_OK;
4351
4352         int snum;
4353
4354         /* that's an [in out] buffer */
4355
4356         if (!r->in.buffer && (r->in.offered != 0)) {
4357                 return WERR_INVALID_PARAM;
4358         }
4359
4360         *r->out.needed = 0;
4361
4362         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4363                 return WERR_BADFID;
4364         }
4365
4366         result = get_a_printer(Printer, &ntprinter, 2,
4367                                lp_const_servicename(snum));
4368         if (!W_ERROR_IS_OK(result)) {
4369                 return result;
4370         }
4371
4372         switch (r->in.level) {
4373         case 0:
4374                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4375                                                  &r->out.info->info0, snum);
4376                 break;
4377         case 1:
4378                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4379                                                  PRINTER_ENUM_ICON8,
4380                                                  &r->out.info->info1, snum);
4381                 break;
4382         case 2:
4383                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4384                                                  &r->out.info->info2, snum);
4385                 break;
4386         case 3:
4387                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4388                                                  &r->out.info->info3, snum);
4389                 break;
4390         case 4:
4391                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4392                                                  &r->out.info->info4, snum);
4393                 break;
4394         case 5:
4395                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4396                                                  &r->out.info->info5, snum);
4397                 break;
4398         case 6:
4399                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4400                                                  &r->out.info->info6, snum);
4401                 break;
4402         case 7:
4403                 result = construct_printer_info7(p->mem_ctx, Printer,
4404                                                  &r->out.info->info7, snum);
4405                 break;
4406         case 8:
4407                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4408                                                  &r->out.info->info8, snum);
4409                 break;
4410         default:
4411                 result = WERR_UNKNOWN_LEVEL;
4412                 break;
4413         }
4414
4415         free_a_printer(&ntprinter, 2);
4416
4417         if (!W_ERROR_IS_OK(result)) {
4418                 TALLOC_FREE(r->out.info);
4419                 return result;
4420         }
4421
4422         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4423                                                r->out.info, r->in.level);
4424         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4425
4426         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4427 }
4428
4429 /********************************************************************
4430  ********************************************************************/
4431
4432 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4433                                                   const char **string_array,
4434                                                   const char *cservername)
4435 {
4436         int i, num_strings = 0;
4437         const char **array = NULL;
4438
4439         if (!string_array) {
4440                 return NULL;
4441         }
4442
4443         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4444
4445                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4446                                                   cservername, string_array[i]);
4447                 if (!str) {
4448                         TALLOC_FREE(array);
4449                         return NULL;
4450                 }
4451
4452
4453                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4454                         TALLOC_FREE(array);
4455                         return NULL;
4456                 }
4457         }
4458
4459         if (i > 0) {
4460                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4461                              &array, &num_strings);
4462         }
4463
4464         return array;
4465 }
4466
4467 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4468         do { \
4469                 if (in && strlen(in)) { \
4470                         out = talloc_strdup(mem_ctx, in); \
4471                         W_ERROR_HAVE_NO_MEMORY(out); \
4472                 } else { \
4473                         out = NULL; \
4474                 } \
4475         } while (0);
4476
4477 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4478         do { \
4479                 if (in && strlen(in)) { \
4480                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4481                 } else { \
4482                         out = talloc_strdup(mem_ctx, ""); \
4483                 } \
4484                 W_ERROR_HAVE_NO_MEMORY(out); \
4485         } while (0);
4486
4487 /********************************************************************
4488  * fill a spoolss_DriverInfo1 struct
4489  ********************************************************************/
4490
4491 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4492                                         struct spoolss_DriverInfo1 *r,
4493                                         const struct spoolss_DriverInfo8 *driver,
4494                                         const char *servername)
4495 {
4496         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4497         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4498
4499         return WERR_OK;
4500 }
4501
4502 /********************************************************************
4503  * fill a spoolss_DriverInfo2 struct
4504  ********************************************************************/
4505
4506 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4507                                         struct spoolss_DriverInfo2 *r,
4508                                         const struct spoolss_DriverInfo8 *driver,
4509                                         const char *servername)
4510
4511 {
4512         const char *cservername = canon_servername(servername);
4513
4514         r->version              = driver->version;
4515
4516         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4517         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4518         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4519         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4520
4521         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4522                                driver->driver_path,
4523                                r->driver_path);
4524
4525         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4526                                driver->data_file,
4527                                r->data_file);
4528
4529         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4530                                driver->config_file,
4531                                r->config_file);
4532
4533         return WERR_OK;
4534 }
4535
4536 /********************************************************************
4537  * fill a spoolss_DriverInfo3 struct
4538  ********************************************************************/
4539
4540 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4541                                         struct spoolss_DriverInfo3 *r,
4542                                         const struct spoolss_DriverInfo8 *driver,
4543                                         const char *servername)
4544 {
4545         const char *cservername = canon_servername(servername);
4546
4547         r->version              = driver->version;
4548
4549         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4550         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4551         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4552         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4553
4554         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4555                                driver->driver_path,
4556                                r->driver_path);
4557
4558         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4559                                driver->data_file,
4560                                r->data_file);
4561
4562         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4563                                driver->config_file,
4564                                r->config_file);
4565
4566         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4567                                driver->help_file,
4568                                r->help_file);
4569
4570         FILL_DRIVER_STRING(mem_ctx,
4571                            driver->monitor_name,
4572                            r->monitor_name);
4573
4574         FILL_DRIVER_STRING(mem_ctx,
4575                            driver->default_datatype,
4576                            r->default_datatype);
4577
4578         r->dependent_files = string_array_from_driver_info(mem_ctx,
4579                                                            driver->dependent_files,
4580                                                            cservername);
4581         return WERR_OK;
4582 }
4583
4584 /********************************************************************
4585  * fill a spoolss_DriverInfo4 struct
4586  ********************************************************************/
4587
4588 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4589                                         struct spoolss_DriverInfo4 *r,
4590                                         const struct spoolss_DriverInfo8 *driver,
4591                                         const char *servername)
4592 {
4593         const char *cservername = canon_servername(servername);
4594
4595         r->version              = driver->version;
4596
4597         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4598         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4599         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4600         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4601
4602         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4603                                driver->driver_path,
4604                                r->driver_path);
4605
4606         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4607                                driver->data_file,
4608                                r->data_file);
4609
4610         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4611                                driver->config_file,
4612                                r->config_file);
4613
4614         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4615                                driver->help_file,
4616                                r->help_file);
4617
4618         r->dependent_files = string_array_from_driver_info(mem_ctx,
4619                                                            driver->dependent_files,
4620                                                            cservername);
4621
4622         FILL_DRIVER_STRING(mem_ctx,
4623                            driver->monitor_name,
4624                            r->monitor_name);
4625
4626         FILL_DRIVER_STRING(mem_ctx,
4627                            driver->default_datatype,
4628                            r->default_datatype);
4629
4630         r->previous_names = string_array_from_driver_info(mem_ctx,
4631                                                           driver->previous_names,
4632                                                           cservername);
4633
4634         return WERR_OK;
4635 }
4636
4637 /********************************************************************
4638  * fill a spoolss_DriverInfo5 struct
4639  ********************************************************************/
4640
4641 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4642                                         struct spoolss_DriverInfo5 *r,
4643                                         const struct spoolss_DriverInfo8 *driver,
4644                                         const char *servername)
4645 {
4646         const char *cservername = canon_servername(servername);
4647
4648         r->version              = driver->version;
4649
4650         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4651         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4652         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4653         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4654
4655         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4656                                driver->driver_path,
4657                                r->driver_path);
4658
4659         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4660                                driver->data_file,
4661                                r->data_file);
4662
4663         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4664                                driver->config_file,
4665                                r->config_file);
4666
4667         r->driver_attributes    = 0;
4668         r->config_version       = 0;
4669         r->driver_version       = 0;
4670
4671         return WERR_OK;
4672 }
4673 /********************************************************************
4674  * fill a spoolss_DriverInfo6 struct
4675  ********************************************************************/
4676
4677 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4678                                         struct spoolss_DriverInfo6 *r,
4679                                         const struct spoolss_DriverInfo8 *driver,
4680                                         const char *servername)
4681 {
4682         const char *cservername = canon_servername(servername);
4683
4684         r->version              = driver->version;
4685
4686         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4687         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4688         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4689         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4690
4691         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4692                                driver->driver_path,
4693                                r->driver_path);
4694
4695         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4696                                driver->data_file,
4697                                r->data_file);
4698
4699         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4700                                driver->config_file,
4701                                r->config_file);
4702
4703         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4704                                driver->help_file,
4705                                r->help_file);
4706
4707         FILL_DRIVER_STRING(mem_ctx,
4708                            driver->monitor_name,
4709                            r->monitor_name);
4710
4711         FILL_DRIVER_STRING(mem_ctx,
4712                            driver->default_datatype,
4713                            r->default_datatype);
4714
4715         r->dependent_files = string_array_from_driver_info(mem_ctx,
4716                                                            driver->dependent_files,
4717                                                            cservername);
4718         r->previous_names = string_array_from_driver_info(mem_ctx,
4719                                                           driver->previous_names,
4720                                                           cservername);
4721
4722         r->driver_date          = driver->driver_date;
4723         r->driver_version       = driver->driver_version;
4724
4725         FILL_DRIVER_STRING(mem_ctx,
4726                            driver->manufacturer_name,
4727                            r->manufacturer_name);
4728         FILL_DRIVER_STRING(mem_ctx,
4729                            driver->manufacturer_url,
4730                            r->manufacturer_url);
4731         FILL_DRIVER_STRING(mem_ctx,
4732                            driver->hardware_id,
4733                            r->hardware_id);
4734         FILL_DRIVER_STRING(mem_ctx,
4735                            driver->provider,
4736                            r->provider);
4737
4738         return WERR_OK;
4739 }
4740
4741 /********************************************************************
4742  * fill a spoolss_DriverInfo8 struct
4743  ********************************************************************/
4744
4745 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4746                                         struct spoolss_DriverInfo8 *r,
4747                                         const struct spoolss_DriverInfo8 *driver,
4748                                         const char *servername)
4749 {
4750         const char *cservername = canon_servername(servername);
4751
4752         r->version              = driver->version;
4753
4754         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4755         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4756         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4757         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4758
4759         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4760                                driver->driver_path,
4761                                r->driver_path);
4762
4763         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4764                                driver->data_file,
4765                                r->data_file);
4766
4767         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4768                                driver->config_file,
4769                                r->config_file);
4770
4771         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4772                                driver->help_file,
4773                                r->help_file);
4774
4775         FILL_DRIVER_STRING(mem_ctx,
4776                            driver->monitor_name,
4777                            r->monitor_name);
4778
4779         FILL_DRIVER_STRING(mem_ctx,
4780                            driver->default_datatype,
4781                            r->default_datatype);
4782
4783         r->dependent_files = string_array_from_driver_info(mem_ctx,
4784                                                            driver->dependent_files,
4785                                                            cservername);
4786         r->previous_names = string_array_from_driver_info(mem_ctx,
4787                                                           driver->previous_names,
4788                                                           cservername);
4789
4790         r->driver_date          = driver->driver_date;
4791         r->driver_version       = driver->driver_version;
4792
4793         FILL_DRIVER_STRING(mem_ctx,
4794                            driver->manufacturer_name,
4795                            r->manufacturer_name);
4796         FILL_DRIVER_STRING(mem_ctx,
4797                            driver->manufacturer_url,
4798                            r->manufacturer_url);
4799         FILL_DRIVER_STRING(mem_ctx,
4800                            driver->hardware_id,
4801                            r->hardware_id);
4802         FILL_DRIVER_STRING(mem_ctx,
4803                            driver->provider,
4804                            r->provider);
4805
4806         FILL_DRIVER_STRING(mem_ctx,
4807                            driver->print_processor,
4808                            r->print_processor);
4809         FILL_DRIVER_STRING(mem_ctx,
4810                            driver->vendor_setup,
4811                            r->vendor_setup);
4812
4813         r->color_profiles = string_array_from_driver_info(mem_ctx,
4814                                                           driver->color_profiles,
4815                                                           cservername);
4816
4817         FILL_DRIVER_STRING(mem_ctx,
4818                            driver->inf_path,
4819                            r->inf_path);
4820
4821         r->printer_driver_attributes    = driver->printer_driver_attributes;
4822
4823         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4824                                                                     driver->core_driver_dependencies,
4825                                                                     cservername);
4826
4827         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4828         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4829
4830         return WERR_OK;
4831 }
4832
4833 #if 0 /* disabled until marshalling issues are resolved - gd */
4834 /********************************************************************
4835  ********************************************************************/
4836
4837 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4838                                           struct spoolss_DriverFileInfo *r,
4839                                           const char *cservername,
4840                                           const char *file_name,
4841                                           enum spoolss_DriverFileType file_type,
4842                                           uint32_t file_version)
4843 {
4844         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4845                                           cservername, file_name);
4846         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4847         r->file_type    = file_type;
4848         r->file_version = file_version;
4849
4850         return WERR_OK;
4851 }
4852
4853 /********************************************************************
4854  ********************************************************************/
4855
4856 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4857                                                  const struct spoolss_DriverInfo8 *driver,
4858                                                  const char *cservername,
4859                                                  struct spoolss_DriverFileInfo **info_p,
4860                                                  uint32_t *count_p)
4861 {
4862         struct spoolss_DriverFileInfo *info = NULL;
4863         uint32_t count = 0;
4864         WERROR result;
4865         uint32_t i;
4866
4867         *info_p = NULL;
4868         *count_p = 0;
4869
4870         if (strlen(driver->driver_path)) {
4871                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4872                                             struct spoolss_DriverFileInfo,
4873                                             count + 1);
4874                 W_ERROR_HAVE_NO_MEMORY(info);
4875                 result = fill_spoolss_DriverFileInfo(info,
4876                                                      &info[count],
4877                                                      cservername,
4878                                                      driver->driver_path,
4879                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4880                                                      0);
4881                 W_ERROR_NOT_OK_RETURN(result);
4882                 count++;
4883         }
4884
4885         if (strlen(driver->config_file)) {
4886                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4887                                             struct spoolss_DriverFileInfo,
4888                                             count + 1);
4889                 W_ERROR_HAVE_NO_MEMORY(info);
4890                 result = fill_spoolss_DriverFileInfo(info,
4891                                                      &info[count],
4892                                                      cservername,
4893                                                      driver->config_file,
4894                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4895                                                      0);
4896                 W_ERROR_NOT_OK_RETURN(result);
4897                 count++;
4898         }
4899
4900         if (strlen(driver->data_file)) {
4901                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4902                                             struct spoolss_DriverFileInfo,
4903                                             count + 1);
4904                 W_ERROR_HAVE_NO_MEMORY(info);
4905                 result = fill_spoolss_DriverFileInfo(info,
4906                                                      &info[count],
4907                                                      cservername,
4908                                                      driver->data_file,
4909                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4910                                                      0);
4911                 W_ERROR_NOT_OK_RETURN(result);
4912                 count++;
4913         }
4914
4915         if (strlen(driver->help_file)) {
4916                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4917                                             struct spoolss_DriverFileInfo,
4918                                             count + 1);
4919                 W_ERROR_HAVE_NO_MEMORY(info);
4920                 result = fill_spoolss_DriverFileInfo(info,
4921                                                      &info[count],
4922                                                      cservername,
4923                                                      driver->help_file,
4924                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4925                                                      0);
4926                 W_ERROR_NOT_OK_RETURN(result);
4927                 count++;
4928         }
4929
4930         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4931                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4932                                             struct spoolss_DriverFileInfo,
4933                                             count + 1);
4934                 W_ERROR_HAVE_NO_MEMORY(info);
4935                 result = fill_spoolss_DriverFileInfo(info,
4936                                                      &info[count],
4937                                                      cservername,
4938                                                      driver->dependent_files[i],
4939                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4940                                                      0);
4941                 W_ERROR_NOT_OK_RETURN(result);
4942                 count++;
4943         }
4944
4945         *info_p = info;
4946         *count_p = count;
4947
4948         return WERR_OK;
4949 }
4950
4951 /********************************************************************
4952  * fill a spoolss_DriverInfo101 struct
4953  ********************************************************************/
4954
4955 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4956                                           struct spoolss_DriverInfo101 *r,
4957                                           const struct spoolss_DriverInfo8 *driver,
4958                                           const char *servername)
4959 {
4960         const char *cservername = canon_servername(servername);
4961         WERROR result;
4962
4963         r->version              = driver->version;
4964
4965         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4966         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4967         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4968         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4969
4970         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4971                                                     cservername,
4972                                                     &r->file_info,
4973                                                     &r->file_count);
4974         if (!W_ERROR_IS_OK(result)) {
4975                 return result;
4976         }
4977
4978         FILL_DRIVER_STRING(mem_ctx,
4979                            driver->monitor_name,
4980                            r->monitor_name);
4981
4982         FILL_DRIVER_STRING(mem_ctx,
4983                            driver->default_datatype,
4984                            r->default_datatype);
4985
4986         r->previous_names = string_array_from_driver_info(mem_ctx,
4987                                                           driver->previous_names,
4988                                                           cservername);
4989         r->driver_date          = driver->driver_date;
4990         r->driver_version       = driver->driver_version;
4991
4992         FILL_DRIVER_STRING(mem_ctx,
4993                            driver->manufacturer_name,
4994                            r->manufacturer_name);
4995         FILL_DRIVER_STRING(mem_ctx,
4996                            driver->manufacturer_url,
4997                            r->manufacturer_url);
4998         FILL_DRIVER_STRING(mem_ctx,
4999                            driver->hardware_id,
5000                            r->hardware_id);
5001         FILL_DRIVER_STRING(mem_ctx,
5002                            driver->provider,
5003                            r->provider);
5004
5005         return WERR_OK;
5006 }
5007 #endif
5008 /********************************************************************
5009  ********************************************************************/
5010
5011 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5012                                                   uint32_t level,
5013                                                   union spoolss_DriverInfo *r,
5014                                                   int snum,
5015                                                   const char *servername,
5016                                                   const char *architecture,
5017                                                   uint32_t version)
5018 {
5019         NT_PRINTER_INFO_LEVEL *printer = NULL;
5020         struct spoolss_DriverInfo8 *driver;
5021         WERROR result;
5022
5023         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5024
5025         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5026                 win_errstr(result)));
5027
5028         if (!W_ERROR_IS_OK(result)) {
5029                 return WERR_INVALID_PRINTER_NAME;
5030         }
5031
5032         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5033                                       architecture, version);
5034
5035         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5036                 win_errstr(result)));
5037
5038         if (!W_ERROR_IS_OK(result)) {
5039                 /*
5040                  * Is this a W2k client ?
5041                  */
5042
5043                 if (version < 3) {
5044                         free_a_printer(&printer, 2);
5045                         return WERR_UNKNOWN_PRINTER_DRIVER;
5046                 }
5047
5048                 /* Yes - try again with a WinNT driver. */
5049                 version = 2;
5050                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5051                                               architecture, version);
5052                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5053                         win_errstr(result)));
5054                 if (!W_ERROR_IS_OK(result)) {
5055                         free_a_printer(&printer, 2);
5056                         return WERR_UNKNOWN_PRINTER_DRIVER;
5057                 }
5058         }
5059
5060         switch (level) {
5061         case 1:
5062                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5063                 break;
5064         case 2:
5065                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5066                 break;
5067         case 3:
5068                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5069                 break;
5070         case 4:
5071                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5072                 break;
5073         case 5:
5074                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5075                 break;
5076         case 6:
5077                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5078                 break;
5079         case 8:
5080                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5081                 break;
5082 #if 0 /* disabled until marshalling issues are resolved - gd */
5083         case 101:
5084                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5085                 break;
5086 #endif
5087         default:
5088                 result = WERR_UNKNOWN_LEVEL;
5089                 break;
5090         }
5091
5092         free_a_printer(&printer, 2);
5093         free_a_printer_driver(driver);
5094
5095         return result;
5096 }
5097
5098 /****************************************************************
5099  _spoolss_GetPrinterDriver2
5100 ****************************************************************/
5101
5102 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5103                                   struct spoolss_GetPrinterDriver2 *r)
5104 {
5105         Printer_entry *printer;
5106         WERROR result;
5107
5108         const char *servername;
5109         int snum;
5110
5111         /* that's an [in out] buffer */
5112
5113         if (!r->in.buffer && (r->in.offered != 0)) {
5114                 return WERR_INVALID_PARAM;
5115         }
5116
5117         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5118
5119         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5120                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5121                 return WERR_INVALID_PRINTER_NAME;
5122         }
5123
5124         *r->out.needed = 0;
5125         *r->out.server_major_version = 0;
5126         *r->out.server_minor_version = 0;
5127
5128         servername = get_server_name(printer);
5129
5130         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5131                 return WERR_BADFID;
5132         }
5133
5134         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5135                                                      r->out.info, snum,
5136                                                      servername,
5137                                                      r->in.architecture,
5138                                                      r->in.client_major_version);
5139         if (!W_ERROR_IS_OK(result)) {
5140                 TALLOC_FREE(r->out.info);
5141                 return result;
5142         }
5143
5144         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5145                                                r->out.info, r->in.level);
5146         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5147
5148         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5149 }
5150
5151
5152 /****************************************************************
5153  _spoolss_StartPagePrinter
5154 ****************************************************************/
5155
5156 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5157                                  struct spoolss_StartPagePrinter *r)
5158 {
5159         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5160
5161         if (!Printer) {
5162                 DEBUG(3,("_spoolss_StartPagePrinter: "
5163                         "Error in startpageprinter printer handle\n"));
5164                 return WERR_BADFID;
5165         }
5166
5167         Printer->page_started = true;
5168         return WERR_OK;
5169 }
5170
5171 /****************************************************************
5172  _spoolss_EndPagePrinter
5173 ****************************************************************/
5174
5175 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5176                                struct spoolss_EndPagePrinter *r)
5177 {
5178         int snum;
5179
5180         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5181
5182         if (!Printer) {
5183                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5184                         OUR_HANDLE(r->in.handle)));
5185                 return WERR_BADFID;
5186         }
5187
5188         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5189                 return WERR_BADFID;
5190
5191         Printer->page_started = false;
5192         print_job_endpage(snum, Printer->jobid);
5193
5194         return WERR_OK;
5195 }
5196
5197 /****************************************************************
5198  _spoolss_StartDocPrinter
5199 ****************************************************************/
5200
5201 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5202                                 struct spoolss_StartDocPrinter *r)
5203 {
5204         struct spoolss_DocumentInfo1 *info_1;
5205         int snum;
5206         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5207
5208         if (!Printer) {
5209                 DEBUG(2,("_spoolss_StartDocPrinter: "
5210                         "Invalid handle (%s:%u:%u)\n",
5211                         OUR_HANDLE(r->in.handle)));
5212                 return WERR_BADFID;
5213         }
5214
5215         if (r->in.level != 1) {
5216                 return WERR_UNKNOWN_LEVEL;
5217         }
5218
5219         info_1 = r->in.info.info1;
5220
5221         /*
5222          * a nice thing with NT is it doesn't listen to what you tell it.
5223          * when asked to send _only_ RAW datas, it tries to send datas
5224          * in EMF format.
5225          *
5226          * So I add checks like in NT Server ...
5227          */
5228
5229         if (info_1->datatype) {
5230                 if (strcmp(info_1->datatype, "RAW") != 0) {
5231                         *r->out.job_id = 0;
5232                         return WERR_INVALID_DATATYPE;
5233                 }
5234         }
5235
5236         /* get the share number of the printer */
5237         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5238                 return WERR_BADFID;
5239         }
5240
5241         Printer->jobid = print_job_start(p->server_info, snum,
5242                                          info_1->document_name,
5243                                          Printer->nt_devmode);
5244
5245         /* An error occured in print_job_start() so return an appropriate
5246            NT error code. */
5247
5248         if (Printer->jobid == -1) {
5249                 return map_werror_from_unix(errno);
5250         }
5251
5252         Printer->document_started = true;
5253         *r->out.job_id = Printer->jobid;
5254
5255         return WERR_OK;
5256 }
5257
5258 /****************************************************************
5259  _spoolss_EndDocPrinter
5260 ****************************************************************/
5261
5262 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5263                               struct spoolss_EndDocPrinter *r)
5264 {
5265         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5266         int snum;
5267
5268         if (!Printer) {
5269                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5270                         OUR_HANDLE(r->in.handle)));
5271                 return WERR_BADFID;
5272         }
5273
5274         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5275                 return WERR_BADFID;
5276         }
5277
5278         Printer->document_started = false;
5279         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5280         /* error codes unhandled so far ... */
5281
5282         return WERR_OK;
5283 }
5284
5285 /****************************************************************
5286  _spoolss_WritePrinter
5287 ****************************************************************/
5288
5289 WERROR _spoolss_WritePrinter(pipes_struct *p,
5290                              struct spoolss_WritePrinter *r)
5291 {
5292         ssize_t buffer_written;
5293         int snum;
5294         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5295
5296         if (!Printer) {
5297                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5298                         OUR_HANDLE(r->in.handle)));
5299                 *r->out.num_written = r->in._data_size;
5300                 return WERR_BADFID;
5301         }
5302
5303         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5304                 return WERR_BADFID;
5305
5306         buffer_written = print_job_write(snum, Printer->jobid,
5307                                                    (const char *)r->in.data.data,
5308                                                    (SMB_OFF_T)-1,
5309                                                    (size_t)r->in._data_size);
5310         if (buffer_written == (ssize_t)-1) {
5311                 *r->out.num_written = 0;
5312                 if (errno == ENOSPC)
5313                         return WERR_NO_SPOOL_SPACE;
5314                 else
5315                         return WERR_ACCESS_DENIED;
5316         }
5317
5318         *r->out.num_written = r->in._data_size;
5319
5320         return WERR_OK;
5321 }
5322
5323 /********************************************************************
5324  * api_spoolss_getprinter
5325  * called from the spoolss dispatcher
5326  *
5327  ********************************************************************/
5328
5329 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5330                               pipes_struct *p)
5331 {
5332         int snum;
5333         WERROR errcode = WERR_BADFUNC;
5334         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5335
5336         if (!Printer) {
5337                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5338                         OUR_HANDLE(handle)));
5339                 return WERR_BADFID;
5340         }
5341
5342         if (!get_printer_snum(p, handle, &snum, NULL))
5343                 return WERR_BADFID;
5344
5345         switch (command) {
5346         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5347                 errcode = print_queue_pause(p->server_info, snum);
5348                 break;
5349         case SPOOLSS_PRINTER_CONTROL_RESUME:
5350         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5351                 errcode = print_queue_resume(p->server_info, snum);
5352                 break;
5353         case SPOOLSS_PRINTER_CONTROL_PURGE:
5354                 errcode = print_queue_purge(p->server_info, snum);
5355                 break;
5356         default:
5357                 return WERR_UNKNOWN_LEVEL;
5358         }
5359
5360         return errcode;
5361 }
5362
5363
5364 /****************************************************************
5365  _spoolss_AbortPrinter
5366  * From MSDN: "Deletes printer's spool file if printer is configured
5367  * for spooling"
5368 ****************************************************************/
5369
5370 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5371                              struct spoolss_AbortPrinter *r)
5372 {
5373         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5374         int             snum;
5375         WERROR          errcode = WERR_OK;
5376
5377         if (!Printer) {
5378                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5379                         OUR_HANDLE(r->in.handle)));
5380                 return WERR_BADFID;
5381         }
5382
5383         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5384                 return WERR_BADFID;
5385
5386         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5387
5388         return errcode;
5389 }
5390
5391 /********************************************************************
5392  * called by spoolss_api_setprinter
5393  * when updating a printer description
5394  ********************************************************************/
5395
5396 static WERROR update_printer_sec(struct policy_handle *handle,
5397                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5398 {
5399         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5400         WERROR result;
5401         int snum;
5402
5403         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5404
5405         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5406                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5407                          OUR_HANDLE(handle)));
5408
5409                 result = WERR_BADFID;
5410                 goto done;
5411         }
5412
5413         if (!secdesc_ctr) {
5414                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5415                 result = WERR_INVALID_PARAM;
5416                 goto done;
5417         }
5418
5419         /* Check the user has permissions to change the security
5420            descriptor.  By experimentation with two NT machines, the user
5421            requires Full Access to the printer to change security
5422            information. */
5423
5424         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5425                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5426                 result = WERR_ACCESS_DENIED;
5427                 goto done;
5428         }
5429
5430         /* NT seems to like setting the security descriptor even though
5431            nothing may have actually changed. */
5432
5433         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5434                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5435                 result = WERR_BADFID;
5436                 goto done;
5437         }
5438
5439         if (DEBUGLEVEL >= 10) {
5440                 SEC_ACL *the_acl;
5441                 int i;
5442
5443                 the_acl = old_secdesc_ctr->sd->dacl;
5444                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5445                            PRINTERNAME(snum), the_acl->num_aces));
5446
5447                 for (i = 0; i < the_acl->num_aces; i++) {
5448                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5449                                            &the_acl->aces[i].trustee),
5450                                   the_acl->aces[i].access_mask));
5451                 }
5452
5453                 the_acl = secdesc_ctr->sd->dacl;
5454
5455                 if (the_acl) {
5456                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5457                                    PRINTERNAME(snum), the_acl->num_aces));
5458
5459                         for (i = 0; i < the_acl->num_aces; i++) {
5460                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5461                                                    &the_acl->aces[i].trustee),
5462                                            the_acl->aces[i].access_mask));
5463                         }
5464                 } else {
5465                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5466                 }
5467         }
5468
5469         new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5470         if (!new_secdesc_ctr) {
5471                 result = WERR_NOMEM;
5472                 goto done;
5473         }
5474
5475         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5476                 result = WERR_OK;
5477                 goto done;
5478         }
5479
5480         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5481
5482  done:
5483
5484         return result;
5485 }
5486
5487 /********************************************************************
5488  Canonicalize printer info from a client
5489
5490  ATTN: It does not matter what we set the servername to hear
5491  since we do the necessary work in get_a_printer() to set it to
5492  the correct value based on what the client sent in the
5493  _spoolss_open_printer_ex().
5494  ********************************************************************/
5495
5496 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5497 {
5498         fstring printername;
5499         const char *p;
5500
5501         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5502                 "portname=%s drivername=%s comment=%s location=%s\n",
5503                 info->servername, info->printername, info->sharename,
5504                 info->portname, info->drivername, info->comment, info->location));
5505
5506         /* we force some elements to "correct" values */
5507         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5508         fstrcpy(info->sharename, lp_servicename(snum));
5509
5510         /* check to see if we allow printername != sharename */
5511
5512         if ( lp_force_printername(snum) ) {
5513                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5514                         global_myname(), info->sharename );
5515         } else {
5516
5517                 /* make sure printername is in \\server\printername format */
5518
5519                 fstrcpy( printername, info->printername );
5520                 p = printername;
5521                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5522                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5523                                 p++;
5524                 }
5525
5526                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5527                          global_myname(), p );
5528         }
5529
5530         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5531         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5532
5533
5534
5535         return true;
5536 }
5537
5538 /****************************************************************************
5539 ****************************************************************************/
5540
5541 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5542 {
5543         char *cmd = lp_addport_cmd();
5544         char *command = NULL;
5545         int ret;
5546         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5547         bool is_print_op = false;
5548
5549         if ( !*cmd ) {
5550                 return WERR_ACCESS_DENIED;
5551         }
5552
5553         command = talloc_asprintf(ctx,
5554                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5555         if (!command) {
5556                 return WERR_NOMEM;
5557         }
5558
5559         if ( token )
5560                 is_print_op = user_has_privileges( token, &se_printop );
5561
5562         DEBUG(10,("Running [%s]\n", command));
5563
5564         /********* BEGIN SePrintOperatorPrivilege **********/
5565
5566         if ( is_print_op )
5567                 become_root();
5568
5569         ret = smbrun(command, NULL);
5570
5571         if ( is_print_op )
5572                 unbecome_root();
5573
5574         /********* END SePrintOperatorPrivilege **********/
5575
5576         DEBUGADD(10,("returned [%d]\n", ret));
5577
5578         TALLOC_FREE(command);
5579
5580         if ( ret != 0 ) {
5581                 return WERR_ACCESS_DENIED;
5582         }
5583
5584         return WERR_OK;
5585 }
5586
5587 /****************************************************************************
5588 ****************************************************************************/
5589
5590 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5591 {
5592         char *cmd = lp_addprinter_cmd();
5593         char **qlines;
5594         char *command = NULL;
5595         int numlines;
5596         int ret;
5597         int fd;
5598         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5599         bool is_print_op = false;
5600         char *remote_machine = talloc_strdup(ctx, "%m");
5601
5602         if (!remote_machine) {
5603                 return false;
5604         }
5605         remote_machine = talloc_sub_basic(ctx,
5606                                 current_user_info.smb_name,
5607                                 current_user_info.domain,
5608                                 remote_machine);
5609         if (!remote_machine) {
5610                 return false;
5611         }
5612
5613         command = talloc_asprintf(ctx,
5614                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5615                         cmd, printer->info_2->printername, printer->info_2->sharename,
5616                         printer->info_2->portname, printer->info_2->drivername,
5617                         printer->info_2->location, printer->info_2->comment, remote_machine);
5618         if (!command) {
5619                 return false;
5620         }
5621
5622         if ( token )
5623                 is_print_op = user_has_privileges( token, &se_printop );
5624
5625         DEBUG(10,("Running [%s]\n", command));
5626
5627         /********* BEGIN SePrintOperatorPrivilege **********/
5628
5629         if ( is_print_op )
5630                 become_root();
5631
5632         if ( (ret = smbrun(command, &fd)) == 0 ) {
5633                 /* Tell everyone we updated smb.conf. */
5634                 message_send_all(smbd_messaging_context(),
5635                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5636         }
5637
5638         if ( is_print_op )
5639                 unbecome_root();
5640
5641         /********* END SePrintOperatorPrivilege **********/
5642
5643         DEBUGADD(10,("returned [%d]\n", ret));
5644
5645         TALLOC_FREE(command);
5646         TALLOC_FREE(remote_machine);
5647
5648         if ( ret != 0 ) {
5649                 if (fd != -1)
5650                         close(fd);
5651                 return false;
5652         }
5653
5654         /* reload our services immediately */
5655         become_root();
5656         reload_services(false);
5657         unbecome_root();
5658
5659         numlines = 0;
5660         /* Get lines and convert them back to dos-codepage */
5661         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5662         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5663         close(fd);
5664
5665         /* Set the portname to what the script says the portname should be. */
5666         /* but don't require anything to be return from the script exit a good error code */
5667
5668         if (numlines) {
5669                 /* Set the portname to what the script says the portname should be. */
5670                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5671                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5672         }
5673
5674         TALLOC_FREE(qlines);
5675         return true;
5676 }
5677
5678
5679 /********************************************************************
5680  * Called by spoolss_api_setprinter
5681  * when updating a printer description.
5682  ********************************************************************/
5683
5684 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5685                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5686                              struct spoolss_DeviceMode *devmode)
5687 {
5688         int snum;
5689         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5690         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5691         WERROR result;
5692         DATA_BLOB buffer;
5693         fstring asc_buffer;
5694
5695         DEBUG(8,("update_printer\n"));
5696
5697         result = WERR_OK;
5698
5699         if (!Printer) {
5700                 result = WERR_BADFID;
5701                 goto done;
5702         }
5703
5704         if (!get_printer_snum(p, handle, &snum, NULL)) {
5705                 result = WERR_BADFID;
5706                 goto done;
5707         }
5708
5709         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5710             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5711                 result = WERR_BADFID;
5712                 goto done;
5713         }
5714
5715         DEBUGADD(8,("Converting info_2 struct\n"));
5716
5717         /*
5718          * convert_printer_info converts the incoming
5719          * info from the client and overwrites the info
5720          * just read from the tdb in the pointer 'printer'.
5721          */
5722
5723         if (!convert_printer_info(info_ctr, printer)) {
5724                 result =  WERR_NOMEM;
5725                 goto done;
5726         }
5727
5728         if (devmode) {
5729                 /* we have a valid devmode
5730                    convert it and link it*/
5731
5732                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5733                 if (!convert_devicemode(printer->info_2->printername, devmode,
5734                                         &printer->info_2->devmode)) {
5735                         result =  WERR_NOMEM;
5736                         goto done;
5737                 }
5738         }
5739
5740         /* Do sanity check on the requested changes for Samba */
5741
5742         if (!check_printer_ok(printer->info_2, snum)) {
5743                 result = WERR_INVALID_PARAM;
5744                 goto done;
5745         }
5746
5747         /* FIXME!!! If the driver has changed we really should verify that
5748            it is installed before doing much else   --jerry */
5749
5750         /* Check calling user has permission to update printer description */
5751
5752         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5753                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5754                 result = WERR_ACCESS_DENIED;
5755                 goto done;
5756         }
5757
5758         /* Call addprinter hook */
5759         /* Check changes to see if this is really needed */
5760
5761         if ( *lp_addprinter_cmd()
5762                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5763                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5764                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5765                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5766         {
5767                 /* add_printer_hook() will call reload_services() */
5768
5769                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5770                                        printer) ) {
5771                         result = WERR_ACCESS_DENIED;
5772                         goto done;
5773                 }
5774         }
5775
5776         /*
5777          * When a *new* driver is bound to a printer, the drivername is used to
5778          * lookup previously saved driver initialization info, which is then
5779          * bound to the printer, simulating what happens in the Windows arch.
5780          */
5781         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5782         {
5783                 if (!set_driver_init(printer, 2))
5784                 {
5785                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5786                                 printer->info_2->drivername));
5787                 }
5788
5789                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5790                         printer->info_2->drivername));
5791
5792                 notify_printer_driver(snum, printer->info_2->drivername);
5793         }
5794
5795         /*
5796          * flag which changes actually occured.  This is a small subset of
5797          * all the possible changes.  We also have to update things in the
5798          * DsSpooler key.
5799          */
5800
5801         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5802                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->comment);
5803                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5804                         REG_SZ, buffer.data, buffer.length);
5805
5806                 notify_printer_comment(snum, printer->info_2->comment);
5807         }
5808
5809         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5810                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->sharename);
5811                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5812                         REG_SZ, buffer.data, buffer.length);
5813
5814                 notify_printer_sharename(snum, printer->info_2->sharename);
5815         }
5816
5817         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5818                 char *pname;
5819
5820                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5821                         pname++;
5822                 else
5823                         pname = printer->info_2->printername;
5824
5825
5826                 push_reg_sz(talloc_tos(), NULL, &buffer, pname);
5827                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5828                         REG_SZ, buffer.data, buffer.length);
5829
5830                 notify_printer_printername( snum, pname );
5831         }
5832
5833         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5834                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->portname);
5835                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5836                         REG_SZ, buffer.data, buffer.length);
5837
5838                 notify_printer_port(snum, printer->info_2->portname);
5839         }
5840
5841         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5842                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->location);
5843                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5844                         REG_SZ, buffer.data, buffer.length);
5845
5846                 notify_printer_location(snum, printer->info_2->location);
5847         }
5848
5849         /* here we need to update some more DsSpooler keys */
5850         /* uNCName, serverName, shortServerName */
5851
5852         push_reg_sz(talloc_tos(), NULL, &buffer, global_myname());
5853         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5854                 REG_SZ, buffer.data, buffer.length);
5855         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5856                 REG_SZ, buffer.data, buffer.length);
5857
5858         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5859                  global_myname(), printer->info_2->sharename );
5860         push_reg_sz(talloc_tos(), NULL, &buffer, asc_buffer);
5861         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5862                 REG_SZ, buffer.data, buffer.length);
5863
5864         /* Update printer info */
5865         result = mod_a_printer(printer, 2);
5866
5867 done:
5868         free_a_printer(&printer, 2);
5869         free_a_printer(&old_printer, 2);
5870
5871
5872         return result;
5873 }
5874
5875 /****************************************************************************
5876 ****************************************************************************/
5877 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5878                                            struct policy_handle *handle,
5879                                            struct spoolss_SetPrinterInfo7 *info7)
5880 {
5881 #ifdef HAVE_ADS
5882         int snum;
5883         Printer_entry *Printer;
5884
5885         if ( lp_security() != SEC_ADS ) {
5886                 return WERR_UNKNOWN_LEVEL;
5887         }
5888
5889         Printer = find_printer_index_by_hnd(p, handle);
5890
5891         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5892
5893         if (!Printer)
5894                 return WERR_BADFID;
5895
5896         if (!get_printer_snum(p, handle, &snum, NULL))
5897                 return WERR_BADFID;
5898
5899         nt_printer_publish(Printer, snum, info7->action);
5900
5901         return WERR_OK;
5902 #else
5903         return WERR_UNKNOWN_LEVEL;
5904 #endif
5905 }
5906
5907 /********************************************************************
5908  ********************************************************************/
5909
5910 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5911                                      struct spoolss_DeviceMode *devmode)
5912 {
5913         int snum;
5914         NT_PRINTER_INFO_LEVEL *printer = NULL;
5915         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5916         WERROR result;
5917
5918         DEBUG(8,("update_printer_devmode\n"));
5919
5920         result = WERR_OK;
5921
5922         if (!Printer) {
5923                 result = WERR_BADFID;
5924                 goto done;
5925         }
5926
5927         if (!get_printer_snum(p, handle, &snum, NULL)) {
5928                 result = WERR_BADFID;
5929                 goto done;
5930         }
5931
5932         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5933                 result = WERR_BADFID;
5934                 goto done;
5935         }
5936
5937         if (devmode) {
5938                 /* we have a valid devmode
5939                    convert it and link it*/
5940
5941                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5942                 if (!convert_devicemode(printer->info_2->printername, devmode,
5943                                         &printer->info_2->devmode)) {
5944                         result =  WERR_NOMEM;
5945                         goto done;
5946                 }
5947         }
5948
5949         /* Check calling user has permission to update printer description */
5950
5951         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5952                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5953                 result = WERR_ACCESS_DENIED;
5954                 goto done;
5955         }
5956
5957
5958         /* Update printer info */
5959         result = mod_a_printer(printer, 2);
5960
5961 done:
5962         free_a_printer(&printer, 2);
5963
5964         return result;
5965 }
5966
5967
5968 /****************************************************************
5969  _spoolss_SetPrinter
5970 ****************************************************************/
5971
5972 WERROR _spoolss_SetPrinter(pipes_struct *p,
5973                            struct spoolss_SetPrinter *r)
5974 {
5975         WERROR result;
5976
5977         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5978
5979         if (!Printer) {
5980                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5981                         OUR_HANDLE(r->in.handle)));
5982                 return WERR_BADFID;
5983         }
5984
5985         /* check the level */
5986         switch (r->in.info_ctr->level) {
5987                 case 0:
5988                         return control_printer(r->in.handle, r->in.command, p);
5989                 case 2:
5990                         result = update_printer(p, r->in.handle,
5991                                                 r->in.info_ctr,
5992                                                 r->in.devmode_ctr->devmode);
5993                         if (!W_ERROR_IS_OK(result))
5994                                 return result;
5995                         if (r->in.secdesc_ctr->sd)
5996                                 result = update_printer_sec(r->in.handle, p,
5997                                                             r->in.secdesc_ctr);
5998                         return result;
5999                 case 3:
6000                         return update_printer_sec(r->in.handle, p,
6001                                                   r->in.secdesc_ctr);
6002                 case 7:
6003                         return publish_or_unpublish_printer(p, r->in.handle,
6004                                                             r->in.info_ctr->info.info7);
6005                 case 8:
6006                         return update_printer_devmode(p, r->in.handle,
6007                                                       r->in.devmode_ctr->devmode);
6008                 default:
6009                         return WERR_UNKNOWN_LEVEL;
6010         }
6011 }
6012
6013 /****************************************************************
6014  _spoolss_FindClosePrinterNotify
6015 ****************************************************************/
6016
6017 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6018                                        struct spoolss_FindClosePrinterNotify *r)
6019 {
6020         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6021
6022         if (!Printer) {
6023                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6024                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6025                 return WERR_BADFID;
6026         }
6027
6028         if (Printer->notify.client_connected == true) {
6029                 int snum = -1;
6030
6031                 if ( Printer->printer_type == SPLHND_SERVER)
6032                         snum = -1;
6033                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6034                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6035                         return WERR_BADFID;
6036
6037                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6038         }
6039
6040         Printer->notify.flags=0;
6041         Printer->notify.options=0;
6042         Printer->notify.localmachine[0]='\0';
6043         Printer->notify.printerlocal=0;
6044         TALLOC_FREE(Printer->notify.option);
6045         Printer->notify.client_connected = false;
6046
6047         return WERR_OK;
6048 }
6049
6050 /****************************************************************
6051  _spoolss_AddJob
6052 ****************************************************************/
6053
6054 WERROR _spoolss_AddJob(pipes_struct *p,
6055                        struct spoolss_AddJob *r)
6056 {
6057         if (!r->in.buffer && (r->in.offered != 0)) {
6058                 return WERR_INVALID_PARAM;
6059         }
6060
6061         /* this is what a NT server returns for AddJob. AddJob must fail on
6062          * non-local printers */
6063
6064         if (r->in.level != 1) {
6065                 return WERR_UNKNOWN_LEVEL;
6066         }
6067
6068         return WERR_INVALID_PARAM;
6069 }
6070
6071 /****************************************************************************
6072 fill_job_info1
6073 ****************************************************************************/
6074
6075 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6076                              struct spoolss_JobInfo1 *r,
6077                              const print_queue_struct *queue,
6078                              int position, int snum,
6079                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6080 {
6081         struct tm *t;
6082
6083         t = gmtime(&queue->time);
6084
6085         r->job_id               = queue->job;
6086
6087         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6088         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6089         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6090         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6091         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6092         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6093         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6094         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6095         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6096         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6097         r->text_status          = talloc_strdup(mem_ctx, "");
6098         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6099
6100         r->status               = nt_printj_status(queue->status);
6101         r->priority             = queue->priority;
6102         r->position             = position;
6103         r->total_pages          = queue->page_count;
6104         r->pages_printed        = 0; /* ??? */
6105
6106         init_systemtime(&r->submitted, t);
6107
6108         return WERR_OK;
6109 }
6110
6111 /****************************************************************************
6112 fill_job_info2
6113 ****************************************************************************/
6114
6115 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6116                              struct spoolss_JobInfo2 *r,
6117                              const print_queue_struct *queue,
6118                              int position, int snum,
6119                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6120                              struct spoolss_DeviceMode *devmode)
6121 {
6122         struct tm *t;
6123
6124         t = gmtime(&queue->time);
6125
6126         r->job_id               = queue->job;
6127
6128         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6129         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6130         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6131         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6132         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6133         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6134         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6135         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6136         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6137         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6138         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6139         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6140         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6141         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6142         r->parameters           = talloc_strdup(mem_ctx, "");
6143         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6144         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6145         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6146
6147         r->devmode              = devmode;
6148
6149         r->text_status          = talloc_strdup(mem_ctx, "");
6150         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6151
6152         r->secdesc              = NULL;
6153
6154         r->status               = nt_printj_status(queue->status);
6155         r->priority             = queue->priority;
6156         r->position             = position;
6157         r->start_time           = 0;
6158         r->until_time           = 0;
6159         r->total_pages          = queue->page_count;
6160         r->size                 = queue->size;
6161         init_systemtime(&r->submitted, t);
6162         r->time                 = 0;
6163         r->pages_printed        = 0; /* ??? */
6164
6165         return WERR_OK;
6166 }
6167
6168 /****************************************************************************
6169 fill_job_info3
6170 ****************************************************************************/
6171
6172 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6173                              struct spoolss_JobInfo3 *r,
6174                              const print_queue_struct *queue,
6175                              const print_queue_struct *next_queue,
6176                              int position, int snum,
6177                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6178 {
6179         r->job_id               = queue->job;
6180         r->next_job_id          = 0;
6181         if (next_queue) {
6182                 r->next_job_id  = next_queue->job;
6183         }
6184         r->reserved             = 0;
6185
6186         return WERR_OK;
6187 }
6188
6189 /****************************************************************************
6190  Enumjobs at level 1.
6191 ****************************************************************************/
6192
6193 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6194                               const print_queue_struct *queue,
6195                               uint32_t num_queues, int snum,
6196                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6197                               union spoolss_JobInfo **info_p,
6198                               uint32_t *count)
6199 {
6200         union spoolss_JobInfo *info;
6201         int i;
6202         WERROR result = WERR_OK;
6203
6204         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6205         W_ERROR_HAVE_NO_MEMORY(info);
6206
6207         *count = num_queues;
6208
6209         for (i=0; i<*count; i++) {
6210                 result = fill_job_info1(info,
6211                                         &info[i].info1,
6212                                         &queue[i],
6213                                         i,
6214                                         snum,
6215                                         ntprinter);
6216                 if (!W_ERROR_IS_OK(result)) {
6217                         goto out;
6218                 }
6219         }
6220
6221  out:
6222         if (!W_ERROR_IS_OK(result)) {
6223                 TALLOC_FREE(info);
6224                 *count = 0;
6225                 return result;
6226         }
6227
6228         *info_p = info;
6229
6230         return WERR_OK;
6231 }
6232
6233 /****************************************************************************
6234  Enumjobs at level 2.
6235 ****************************************************************************/
6236
6237 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6238                               const print_queue_struct *queue,
6239                               uint32_t num_queues, int snum,
6240                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6241                               union spoolss_JobInfo **info_p,
6242                               uint32_t *count)
6243 {
6244         union spoolss_JobInfo *info;
6245         int i;
6246         WERROR result = WERR_OK;
6247
6248         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6249         W_ERROR_HAVE_NO_MEMORY(info);
6250
6251         *count = num_queues;
6252
6253         for (i=0; i<*count; i++) {
6254
6255                 struct spoolss_DeviceMode *devmode;
6256
6257                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6258                 if (!devmode) {
6259                         result = WERR_NOMEM;
6260                         goto out;
6261                 }
6262
6263                 result = fill_job_info2(info,
6264                                         &info[i].info2,
6265                                         &queue[i],
6266                                         i,
6267                                         snum,
6268                                         ntprinter,
6269                                         devmode);
6270                 if (!W_ERROR_IS_OK(result)) {
6271                         goto out;
6272                 }
6273         }
6274
6275  out:
6276         if (!W_ERROR_IS_OK(result)) {
6277                 TALLOC_FREE(info);
6278                 *count = 0;
6279                 return result;
6280         }
6281
6282         *info_p = info;
6283
6284         return WERR_OK;
6285 }
6286
6287 /****************************************************************************
6288  Enumjobs at level 3.
6289 ****************************************************************************/
6290
6291 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6292                               const print_queue_struct *queue,
6293                               uint32_t num_queues, int snum,
6294                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6295                               union spoolss_JobInfo **info_p,
6296                               uint32_t *count)
6297 {
6298         union spoolss_JobInfo *info;
6299         int i;
6300         WERROR result = WERR_OK;
6301
6302         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6303         W_ERROR_HAVE_NO_MEMORY(info);
6304
6305         *count = num_queues;
6306
6307         for (i=0; i<*count; i++) {
6308                 const print_queue_struct *next_queue = NULL;
6309
6310                 if (i+1 < *count) {
6311                         next_queue = &queue[i+1];
6312                 }
6313
6314                 result = fill_job_info3(info,
6315                                         &info[i].info3,
6316                                         &queue[i],
6317                                         next_queue,
6318                                         i,
6319                                         snum,
6320                                         ntprinter);
6321                 if (!W_ERROR_IS_OK(result)) {
6322                         goto out;
6323                 }
6324         }
6325
6326  out:
6327         if (!W_ERROR_IS_OK(result)) {
6328                 TALLOC_FREE(info);
6329                 *count = 0;
6330                 return result;
6331         }
6332
6333         *info_p = info;
6334
6335         return WERR_OK;
6336 }
6337
6338 /****************************************************************
6339  _spoolss_EnumJobs
6340 ****************************************************************/
6341
6342 WERROR _spoolss_EnumJobs(pipes_struct *p,
6343                          struct spoolss_EnumJobs *r)
6344 {
6345         WERROR result;
6346         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6347         int snum;
6348         print_status_struct prt_status;
6349         print_queue_struct *queue = NULL;
6350         uint32_t count;
6351
6352         /* that's an [in out] buffer */
6353
6354         if (!r->in.buffer && (r->in.offered != 0)) {
6355                 return WERR_INVALID_PARAM;
6356         }
6357
6358         DEBUG(4,("_spoolss_EnumJobs\n"));
6359
6360         *r->out.needed = 0;
6361         *r->out.count = 0;
6362         *r->out.info = NULL;
6363
6364         /* lookup the printer snum and tdb entry */
6365
6366         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6367                 return WERR_BADFID;
6368         }
6369
6370         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6371         if (!W_ERROR_IS_OK(result)) {
6372                 return result;
6373         }
6374
6375         count = print_queue_status(snum, &queue, &prt_status);
6376         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6377                 count, prt_status.status, prt_status.message));
6378
6379         if (count == 0) {
6380                 SAFE_FREE(queue);
6381                 free_a_printer(&ntprinter, 2);
6382                 return WERR_OK;
6383         }
6384
6385         switch (r->in.level) {
6386         case 1:
6387                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6388                                          ntprinter, r->out.info, r->out.count);
6389                 break;
6390         case 2:
6391                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6392                                          ntprinter, r->out.info, r->out.count);
6393                 break;
6394         case 3:
6395                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6396                                          ntprinter, r->out.info, r->out.count);
6397                 break;
6398         default:
6399                 result = WERR_UNKNOWN_LEVEL;
6400                 break;
6401         }
6402
6403         SAFE_FREE(queue);
6404         free_a_printer(&ntprinter, 2);
6405
6406         if (!W_ERROR_IS_OK(result)) {
6407                 return result;
6408         }
6409
6410         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6411                                                      spoolss_EnumJobs, NULL,
6412                                                      *r->out.info, r->in.level,
6413                                                      *r->out.count);
6414         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6415         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6416
6417         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6418 }
6419
6420 /****************************************************************
6421  _spoolss_ScheduleJob
6422 ****************************************************************/
6423
6424 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6425                             struct spoolss_ScheduleJob *r)
6426 {
6427         return WERR_OK;
6428 }
6429
6430 /****************************************************************
6431 ****************************************************************/
6432
6433 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6434                                const char *printer_name,
6435                                uint32_t job_id,
6436                                struct spoolss_SetJobInfo1 *r)
6437 {
6438         char *old_doc_name;
6439
6440         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6441                 return WERR_BADFID;
6442         }
6443
6444         if (strequal(old_doc_name, r->document_name)) {
6445                 return WERR_OK;
6446         }
6447
6448         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6449                 return WERR_BADFID;
6450         }
6451
6452         return WERR_OK;
6453 }
6454
6455 /****************************************************************
6456  _spoolss_SetJob
6457 ****************************************************************/
6458
6459 WERROR _spoolss_SetJob(pipes_struct *p,
6460                        struct spoolss_SetJob *r)
6461 {
6462         int snum;
6463         WERROR errcode = WERR_BADFUNC;
6464
6465         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6466                 return WERR_BADFID;
6467         }
6468
6469         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6470                 return WERR_INVALID_PRINTER_NAME;
6471         }
6472
6473         switch (r->in.command) {
6474         case SPOOLSS_JOB_CONTROL_CANCEL:
6475         case SPOOLSS_JOB_CONTROL_DELETE:
6476                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6477                         errcode = WERR_OK;
6478                 }
6479                 break;
6480         case SPOOLSS_JOB_CONTROL_PAUSE:
6481                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6482                         errcode = WERR_OK;
6483                 }
6484                 break;
6485         case SPOOLSS_JOB_CONTROL_RESTART:
6486         case SPOOLSS_JOB_CONTROL_RESUME:
6487                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6488                         errcode = WERR_OK;
6489                 }
6490                 break;
6491         case 0:
6492                 errcode = WERR_OK;
6493                 break;
6494         default:
6495                 return WERR_UNKNOWN_LEVEL;
6496         }
6497
6498         if (!W_ERROR_IS_OK(errcode)) {
6499                 return errcode;
6500         }
6501
6502         if (r->in.ctr == NULL) {
6503                 return errcode;
6504         }
6505
6506         switch (r->in.ctr->level) {
6507         case 1:
6508                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6509                                            r->in.job_id,
6510                                            r->in.ctr->info.info1);
6511                 break;
6512         case 2:
6513         case 3:
6514         case 4:
6515         default:
6516                 return WERR_UNKNOWN_LEVEL;
6517         }
6518
6519         return errcode;
6520 }
6521
6522 /****************************************************************************
6523  Enumerates all printer drivers by level and architecture.
6524 ****************************************************************************/
6525
6526 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6527                                                        const char *servername,
6528                                                        const char *architecture,
6529                                                        uint32_t level,
6530                                                        union spoolss_DriverInfo **info_p,
6531                                                        uint32_t *count_p)
6532 {
6533         int i;
6534         int ndrivers;
6535         uint32_t version;
6536         fstring *list = NULL;
6537         struct spoolss_DriverInfo8 *driver;
6538         union spoolss_DriverInfo *info = NULL;
6539         uint32_t count = 0;
6540         WERROR result = WERR_OK;
6541
6542         *count_p = 0;
6543         *info_p = NULL;
6544
6545         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6546                 list = NULL;
6547                 ndrivers = get_ntdrivers(&list, architecture, version);
6548                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6549                         ndrivers, architecture, version));
6550
6551                 if (ndrivers == -1) {
6552                         result = WERR_NOMEM;
6553                         goto out;
6554                 }
6555
6556                 if (ndrivers != 0) {
6557                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6558                                                     union spoolss_DriverInfo,
6559                                                     count + ndrivers);
6560                         if (!info) {
6561                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6562                                         "failed to enlarge driver info buffer!\n"));
6563                                 result = WERR_NOMEM;
6564                                 goto out;
6565                         }
6566                 }
6567
6568                 for (i=0; i<ndrivers; i++) {
6569                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6570                         ZERO_STRUCT(driver);
6571                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6572                                                       architecture, version);
6573                         if (!W_ERROR_IS_OK(result)) {
6574                                 goto out;
6575                         }
6576
6577                         switch (level) {
6578                         case 1:
6579                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6580                                                                    driver, servername);
6581                                 break;
6582                         case 2:
6583                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6584                                                                    driver, servername);
6585                                 break;
6586                         case 3:
6587                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6588                                                                    driver, servername);
6589                                 break;
6590                         case 4:
6591                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6592                                                                    driver, servername);
6593                                 break;
6594                         case 5:
6595                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6596                                                                    driver, servername);
6597                                 break;
6598                         case 6:
6599                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6600                                                                    driver, servername);
6601                                 break;
6602                         case 8:
6603                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6604                                                                    driver, servername);
6605                                 break;
6606                         default:
6607                                 result = WERR_UNKNOWN_LEVEL;
6608                                 break;
6609                         }
6610
6611                         free_a_printer_driver(driver);
6612
6613                         if (!W_ERROR_IS_OK(result)) {
6614                                 goto out;
6615                         }
6616                 }
6617
6618                 count += ndrivers;
6619                 SAFE_FREE(list);
6620         }
6621
6622  out:
6623         SAFE_FREE(list);
6624
6625         if (!W_ERROR_IS_OK(result)) {
6626                 TALLOC_FREE(info);
6627                 return result;
6628         }
6629
6630         *info_p = info;
6631         *count_p = count;
6632
6633         return WERR_OK;
6634 }
6635
6636 /****************************************************************************
6637  Enumerates all printer drivers by level.
6638 ****************************************************************************/
6639
6640 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6641                                        const char *servername,
6642                                        const char *architecture,
6643                                        uint32_t level,
6644                                        union spoolss_DriverInfo **info_p,
6645                                        uint32_t *count_p)
6646 {
6647         uint32_t a,i;
6648         WERROR result = WERR_OK;
6649
6650         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6651
6652                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6653
6654                         union spoolss_DriverInfo *info = NULL;
6655                         uint32_t count = 0;
6656
6657                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6658                                                                           servername,
6659                                                                           archi_table[a].long_archi,
6660                                                                           level,
6661                                                                           &info,
6662                                                                           &count);
6663                         if (!W_ERROR_IS_OK(result)) {
6664                                 continue;
6665                         }
6666
6667                         for (i=0; i < count; i++) {
6668                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6669                                              info[i], info_p, count_p);
6670                         }
6671                 }
6672
6673                 return result;
6674         }
6675
6676         return enumprinterdrivers_level_by_architecture(mem_ctx,
6677                                                         servername,
6678                                                         architecture,
6679                                                         level,
6680                                                         info_p,
6681                                                         count_p);
6682 }
6683
6684 /****************************************************************
6685  _spoolss_EnumPrinterDrivers
6686 ****************************************************************/
6687
6688 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6689                                    struct spoolss_EnumPrinterDrivers *r)
6690 {
6691         const char *cservername;
6692         WERROR result;
6693
6694         /* that's an [in out] buffer */
6695
6696         if (!r->in.buffer && (r->in.offered != 0)) {
6697                 return WERR_INVALID_PARAM;
6698         }
6699
6700         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6701
6702         *r->out.needed = 0;
6703         *r->out.count = 0;
6704         *r->out.info = NULL;
6705
6706         cservername = canon_servername(r->in.server);
6707
6708         if (!is_myname_or_ipaddr(cservername)) {
6709                 return WERR_UNKNOWN_PRINTER_DRIVER;
6710         }
6711
6712         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6713                                           r->in.environment,
6714                                           r->in.level,
6715                                           r->out.info,
6716                                           r->out.count);
6717         if (!W_ERROR_IS_OK(result)) {
6718                 return result;
6719         }
6720
6721         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6722                                                      spoolss_EnumPrinterDrivers, NULL,
6723                                                      *r->out.info, r->in.level,
6724                                                      *r->out.count);
6725         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6726         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6727
6728         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6729 }
6730
6731 /****************************************************************************
6732 ****************************************************************************/
6733
6734 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6735                                struct spoolss_FormInfo1 *r,
6736                                const nt_forms_struct *form)
6737 {
6738         r->form_name    = talloc_strdup(mem_ctx, form->name);
6739         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6740
6741         r->flags        = form->flag;
6742         r->size.width   = form->width;
6743         r->size.height  = form->length;
6744         r->area.left    = form->left;
6745         r->area.top     = form->top;
6746         r->area.right   = form->right;
6747         r->area.bottom  = form->bottom;
6748
6749         return WERR_OK;
6750 }
6751
6752 /****************************************************************
6753  spoolss_enumforms_level1
6754 ****************************************************************/
6755
6756 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6757                                        const nt_forms_struct *builtin_forms,
6758                                        uint32_t num_builtin_forms,
6759                                        const nt_forms_struct *user_forms,
6760                                        uint32_t num_user_forms,
6761                                        union spoolss_FormInfo **info_p,
6762                                        uint32_t *count)
6763 {
6764         union spoolss_FormInfo *info;
6765         WERROR result = WERR_OK;
6766         int i;
6767
6768         *count = num_builtin_forms + num_user_forms;
6769
6770         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6771         W_ERROR_HAVE_NO_MEMORY(info);
6772
6773         /* construct the list of form structures */
6774         for (i=0; i<num_builtin_forms; i++) {
6775                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6776                 result = fill_form_info_1(info, &info[i].info1,
6777                                           &builtin_forms[i]);
6778                 if (!W_ERROR_IS_OK(result)) {
6779                         goto out;
6780                 }
6781         }
6782
6783         for (i=0; i<num_user_forms; i++) {
6784                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6785                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6786                                           &user_forms[i]);
6787                 if (!W_ERROR_IS_OK(result)) {
6788                         goto out;
6789                 }
6790         }
6791
6792  out:
6793         if (!W_ERROR_IS_OK(result)) {
6794                 TALLOC_FREE(info);
6795                 *count = 0;
6796                 return result;
6797         }
6798
6799         *info_p = info;
6800
6801         return WERR_OK;
6802 }
6803
6804 /****************************************************************
6805  _spoolss_EnumForms
6806 ****************************************************************/
6807
6808 WERROR _spoolss_EnumForms(pipes_struct *p,
6809                           struct spoolss_EnumForms *r)
6810 {
6811         WERROR result;
6812         nt_forms_struct *user_forms = NULL;
6813         nt_forms_struct *builtin_forms = NULL;
6814         uint32_t num_user_forms;
6815         uint32_t num_builtin_forms;
6816
6817         *r->out.count = 0;
6818         *r->out.needed = 0;
6819         *r->out.info = NULL;
6820
6821         /* that's an [in out] buffer */
6822
6823         if (!r->in.buffer && (r->in.offered != 0) ) {
6824                 return WERR_INVALID_PARAM;
6825         }
6826
6827         DEBUG(4,("_spoolss_EnumForms\n"));
6828         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6829         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6830
6831         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6832         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6833         num_user_forms = get_ntforms(&user_forms);
6834         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6835
6836         if (num_user_forms + num_builtin_forms == 0) {
6837                 SAFE_FREE(builtin_forms);
6838                 SAFE_FREE(user_forms);
6839                 return WERR_NO_MORE_ITEMS;
6840         }
6841
6842         switch (r->in.level) {
6843         case 1:
6844                 result = spoolss_enumforms_level1(p->mem_ctx,
6845                                                   builtin_forms,
6846                                                   num_builtin_forms,
6847                                                   user_forms,
6848                                                   num_user_forms,
6849                                                   r->out.info,
6850                                                   r->out.count);
6851                 break;
6852         default:
6853                 result = WERR_UNKNOWN_LEVEL;
6854                 break;
6855         }
6856
6857         SAFE_FREE(user_forms);
6858         SAFE_FREE(builtin_forms);
6859
6860         if (!W_ERROR_IS_OK(result)) {
6861                 return result;
6862         }
6863
6864         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6865                                                      spoolss_EnumForms, NULL,
6866                                                      *r->out.info, r->in.level,
6867                                                      *r->out.count);
6868         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6869         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6870
6871         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6872 }
6873
6874 /****************************************************************
6875 ****************************************************************/
6876
6877 static WERROR find_form_byname(const char *name,
6878                                nt_forms_struct *form)
6879 {
6880         nt_forms_struct *list = NULL;
6881         int num_forms = 0, i = 0;
6882
6883         if (get_a_builtin_ntform_by_string(name, form)) {
6884                 return WERR_OK;
6885         }
6886
6887         num_forms = get_ntforms(&list);
6888         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6889
6890         if (num_forms == 0) {
6891                 return WERR_BADFID;
6892         }
6893
6894         /* Check if the requested name is in the list of form structures */
6895         for (i = 0; i < num_forms; i++) {
6896
6897                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6898
6899                 if (strequal(name, list[i].name)) {
6900                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6901                         *form = list[i];
6902                         SAFE_FREE(list);
6903                         return WERR_OK;
6904                 }
6905         }
6906
6907         SAFE_FREE(list);
6908
6909         return WERR_BADFID;
6910 }
6911
6912 /****************************************************************
6913  _spoolss_GetForm
6914 ****************************************************************/
6915
6916 WERROR _spoolss_GetForm(pipes_struct *p,
6917                         struct spoolss_GetForm *r)
6918 {
6919         WERROR result;
6920         nt_forms_struct form;
6921
6922         /* that's an [in out] buffer */
6923
6924         if (!r->in.buffer && (r->in.offered != 0)) {
6925                 return WERR_INVALID_PARAM;
6926         }
6927
6928         DEBUG(4,("_spoolss_GetForm\n"));
6929         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6930         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6931
6932         result = find_form_byname(r->in.form_name, &form);
6933         if (!W_ERROR_IS_OK(result)) {
6934                 TALLOC_FREE(r->out.info);
6935                 return result;
6936         }
6937
6938         switch (r->in.level) {
6939         case 1:
6940                 result = fill_form_info_1(p->mem_ctx,
6941                                           &r->out.info->info1,
6942                                           &form);
6943                 break;
6944
6945         default:
6946                 result = WERR_UNKNOWN_LEVEL;
6947                 break;
6948         }
6949
6950         if (!W_ERROR_IS_OK(result)) {
6951                 TALLOC_FREE(r->out.info);
6952                 return result;
6953         }
6954
6955         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6956                                                r->out.info, r->in.level);
6957         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6958
6959         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6960 }
6961
6962 /****************************************************************************
6963 ****************************************************************************/
6964
6965 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6966                           struct spoolss_PortInfo1 *r,
6967                           const char *name)
6968 {
6969         r->port_name = talloc_strdup(mem_ctx, name);
6970         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6971
6972         return WERR_OK;
6973 }
6974
6975 /****************************************************************************
6976  TODO: This probably needs distinguish between TCP/IP and Local ports
6977  somehow.
6978 ****************************************************************************/
6979
6980 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6981                           struct spoolss_PortInfo2 *r,
6982                           const char *name)
6983 {
6984         r->port_name = talloc_strdup(mem_ctx, name);
6985         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6986
6987         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6988         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6989
6990         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6991         W_ERROR_HAVE_NO_MEMORY(r->description);
6992
6993         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6994         r->reserved = 0;
6995
6996         return WERR_OK;
6997 }
6998
6999
7000 /****************************************************************************
7001  wrapper around the enumer ports command
7002 ****************************************************************************/
7003
7004 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7005 {
7006         char *cmd = lp_enumports_cmd();
7007         char **qlines = NULL;
7008         char *command = NULL;
7009         int numlines;
7010         int ret;
7011         int fd;
7012
7013         *count = 0;
7014         *lines = NULL;
7015
7016         /* if no hook then just fill in the default port */
7017
7018         if ( !*cmd ) {
7019                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7020                         return WERR_NOMEM;
7021                 }
7022                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7023                         TALLOC_FREE(qlines);
7024                         return WERR_NOMEM;
7025                 }
7026                 qlines[1] = NULL;
7027                 numlines = 1;
7028         }
7029         else {
7030                 /* we have a valid enumport command */
7031
7032                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7033                 if (!command) {
7034                         return WERR_NOMEM;
7035                 }
7036
7037                 DEBUG(10,("Running [%s]\n", command));
7038                 ret = smbrun(command, &fd);
7039                 DEBUG(10,("Returned [%d]\n", ret));
7040                 TALLOC_FREE(command);
7041                 if (ret != 0) {
7042                         if (fd != -1) {
7043                                 close(fd);
7044                         }
7045                         return WERR_ACCESS_DENIED;
7046                 }
7047
7048                 numlines = 0;
7049                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7050                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7051                 close(fd);
7052         }
7053
7054         *count = numlines;
7055         *lines = qlines;
7056
7057         return WERR_OK;
7058 }
7059
7060 /****************************************************************************
7061  enumports level 1.
7062 ****************************************************************************/
7063
7064 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7065                                 union spoolss_PortInfo **info_p,
7066                                 uint32_t *count)
7067 {
7068         union spoolss_PortInfo *info = NULL;
7069         int i=0;
7070         WERROR result = WERR_OK;
7071         char **qlines = NULL;
7072         int numlines = 0;
7073
7074         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7075         if (!W_ERROR_IS_OK(result)) {
7076                 goto out;
7077         }
7078
7079         if (numlines) {
7080                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7081                 if (!info) {
7082                         DEBUG(10,("Returning WERR_NOMEM\n"));
7083                         result = WERR_NOMEM;
7084                         goto out;
7085                 }
7086
7087                 for (i=0; i<numlines; i++) {
7088                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7089                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7090                         if (!W_ERROR_IS_OK(result)) {
7091                                 goto out;
7092                         }
7093                 }
7094         }
7095         TALLOC_FREE(qlines);
7096
7097 out:
7098         if (!W_ERROR_IS_OK(result)) {
7099                 TALLOC_FREE(info);
7100                 TALLOC_FREE(qlines);
7101                 *count = 0;
7102                 *info_p = NULL;
7103                 return result;
7104         }
7105
7106         *info_p = info;
7107         *count = numlines;
7108
7109         return WERR_OK;
7110 }
7111
7112 /****************************************************************************
7113  enumports level 2.
7114 ****************************************************************************/
7115
7116 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7117                                 union spoolss_PortInfo **info_p,
7118                                 uint32_t *count)
7119 {
7120         union spoolss_PortInfo *info = NULL;
7121         int i=0;
7122         WERROR result = WERR_OK;
7123         char **qlines = NULL;
7124         int numlines = 0;
7125
7126         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7127         if (!W_ERROR_IS_OK(result)) {
7128                 goto out;
7129         }
7130
7131         if (numlines) {
7132                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7133                 if (!info) {
7134                         DEBUG(10,("Returning WERR_NOMEM\n"));
7135                         result = WERR_NOMEM;
7136                         goto out;
7137                 }
7138
7139                 for (i=0; i<numlines; i++) {
7140                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7141                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7142                         if (!W_ERROR_IS_OK(result)) {
7143                                 goto out;
7144                         }
7145                 }
7146         }
7147         TALLOC_FREE(qlines);
7148
7149 out:
7150         if (!W_ERROR_IS_OK(result)) {
7151                 TALLOC_FREE(info);
7152                 TALLOC_FREE(qlines);
7153                 *count = 0;
7154                 *info_p = NULL;
7155                 return result;
7156         }
7157
7158         *info_p = info;
7159         *count = numlines;
7160
7161         return WERR_OK;
7162 }
7163
7164 /****************************************************************
7165  _spoolss_EnumPorts
7166 ****************************************************************/
7167
7168 WERROR _spoolss_EnumPorts(pipes_struct *p,
7169                           struct spoolss_EnumPorts *r)
7170 {
7171         WERROR result;
7172
7173         /* that's an [in out] buffer */
7174
7175         if (!r->in.buffer && (r->in.offered != 0)) {
7176                 return WERR_INVALID_PARAM;
7177         }
7178
7179         DEBUG(4,("_spoolss_EnumPorts\n"));
7180
7181         *r->out.count = 0;
7182         *r->out.needed = 0;
7183         *r->out.info = NULL;
7184
7185         switch (r->in.level) {
7186         case 1:
7187                 result = enumports_level_1(p->mem_ctx, r->out.info,
7188                                            r->out.count);
7189                 break;
7190         case 2:
7191                 result = enumports_level_2(p->mem_ctx, r->out.info,
7192                                            r->out.count);
7193                 break;
7194         default:
7195                 return WERR_UNKNOWN_LEVEL;
7196         }
7197
7198         if (!W_ERROR_IS_OK(result)) {
7199                 return result;
7200         }
7201
7202         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7203                                                      spoolss_EnumPorts, NULL,
7204                                                      *r->out.info, r->in.level,
7205                                                      *r->out.count);
7206         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7207         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7208
7209         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7210 }
7211
7212 /****************************************************************************
7213 ****************************************************************************/
7214
7215 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7216                                            const char *server,
7217                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7218                                            struct spoolss_DeviceMode *devmode,
7219                                            struct security_descriptor *sec_desc,
7220                                            struct spoolss_UserLevelCtr *user_ctr,
7221                                            struct policy_handle *handle)
7222 {
7223         NT_PRINTER_INFO_LEVEL *printer = NULL;
7224         fstring name;
7225         int     snum;
7226         WERROR err = WERR_OK;
7227
7228         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7229                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7230                 return WERR_NOMEM;
7231         }
7232
7233         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7234         if (!convert_printer_info(info_ctr, printer)) {
7235                 free_a_printer(&printer, 2);
7236                 return WERR_NOMEM;
7237         }
7238
7239         /* samba does not have a concept of local, non-shared printers yet, so
7240          * make sure we always setup sharename - gd */
7241         if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7242                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7243                         "no sharename has been set, setting printername %s as sharename\n",
7244                         printer->info_2->printername));
7245                 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7246         }
7247
7248         /* check to see if the printer already exists */
7249
7250         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7251                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7252                         printer->info_2->sharename));
7253                 free_a_printer(&printer, 2);
7254                 return WERR_PRINTER_ALREADY_EXISTS;
7255         }
7256
7257         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7258                 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7259                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7260                                 printer->info_2->printername));
7261                         free_a_printer(&printer, 2);
7262                         return WERR_PRINTER_ALREADY_EXISTS;
7263                 }
7264         }
7265
7266         /* validate printer info struct */
7267         if (!info_ctr->info.info2->printername ||
7268             strlen(info_ctr->info.info2->printername) == 0) {
7269                 free_a_printer(&printer,2);
7270                 return WERR_INVALID_PRINTER_NAME;
7271         }
7272         if (!info_ctr->info.info2->portname ||
7273             strlen(info_ctr->info.info2->portname) == 0) {
7274                 free_a_printer(&printer,2);
7275                 return WERR_UNKNOWN_PORT;
7276         }
7277         if (!info_ctr->info.info2->drivername ||
7278             strlen(info_ctr->info.info2->drivername) == 0) {
7279                 free_a_printer(&printer,2);
7280                 return WERR_UNKNOWN_PRINTER_DRIVER;
7281         }
7282         if (!info_ctr->info.info2->printprocessor ||
7283             strlen(info_ctr->info.info2->printprocessor) == 0) {
7284                 free_a_printer(&printer,2);
7285                 return WERR_UNKNOWN_PRINTPROCESSOR;
7286         }
7287
7288         /* FIXME!!!  smbd should check to see if the driver is installed before
7289            trying to add a printer like this  --jerry */
7290
7291         if (*lp_addprinter_cmd() ) {
7292                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7293                                        printer) ) {
7294                         free_a_printer(&printer,2);
7295                         return WERR_ACCESS_DENIED;
7296                 }
7297         } else {
7298                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7299                         "smb.conf parameter \"addprinter command\" is defined. This"
7300                         "parameter must exist for this call to succeed\n",
7301                         printer->info_2->sharename ));
7302         }
7303
7304         /* use our primary netbios name since get_a_printer() will convert
7305            it to what the client expects on a case by case basis */
7306
7307         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7308              printer->info_2->sharename);
7309
7310
7311         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7312                 free_a_printer(&printer,2);
7313                 return WERR_ACCESS_DENIED;
7314         }
7315
7316         /* you must be a printer admin to add a new printer */
7317         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7318                 free_a_printer(&printer,2);
7319                 return WERR_ACCESS_DENIED;
7320         }
7321
7322         /*
7323          * Do sanity check on the requested changes for Samba.
7324          */
7325
7326         if (!check_printer_ok(printer->info_2, snum)) {
7327                 free_a_printer(&printer,2);
7328                 return WERR_INVALID_PARAM;
7329         }
7330
7331         /*
7332          * When a printer is created, the drivername bound to the printer is used
7333          * to lookup previously saved driver initialization info, which is then
7334          * bound to the new printer, simulating what happens in the Windows arch.
7335          */
7336
7337         if (!devmode)
7338         {
7339                 set_driver_init(printer, 2);
7340         }
7341         else
7342         {
7343                 /* A valid devmode was included, convert and link it
7344                 */
7345                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7346
7347                 if (!convert_devicemode(printer->info_2->printername, devmode,
7348                                         &printer->info_2->devmode)) {
7349                         return  WERR_NOMEM;
7350                 }
7351         }
7352
7353         /* write the ASCII on disk */
7354         err = mod_a_printer(printer, 2);
7355         if (!W_ERROR_IS_OK(err)) {
7356                 free_a_printer(&printer,2);
7357                 return err;
7358         }
7359
7360         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7361                 /* Handle open failed - remove addition. */
7362                 del_a_printer(printer->info_2->sharename);
7363                 free_a_printer(&printer,2);
7364                 ZERO_STRUCTP(handle);
7365                 return WERR_ACCESS_DENIED;
7366         }
7367
7368         update_c_setprinter(false);
7369         free_a_printer(&printer,2);
7370
7371         return WERR_OK;
7372 }
7373
7374 /****************************************************************
7375  _spoolss_AddPrinterEx
7376 ****************************************************************/
7377
7378 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7379                              struct spoolss_AddPrinterEx *r)
7380 {
7381         switch (r->in.info_ctr->level) {
7382         case 1:
7383                 /* we don't handle yet */
7384                 /* but I know what to do ... */
7385                 return WERR_UNKNOWN_LEVEL;
7386         case 2:
7387                 return spoolss_addprinterex_level_2(p, r->in.server,
7388                                                     r->in.info_ctr,
7389                                                     r->in.devmode_ctr->devmode,
7390                                                     r->in.secdesc_ctr->sd,
7391                                                     r->in.userlevel_ctr,
7392                                                     r->out.handle);
7393         default:
7394                 return WERR_UNKNOWN_LEVEL;
7395         }
7396 }
7397
7398 /****************************************************************
7399  _spoolss_AddPrinter
7400 ****************************************************************/
7401
7402 WERROR _spoolss_AddPrinter(pipes_struct *p,
7403                            struct spoolss_AddPrinter *r)
7404 {
7405         struct spoolss_AddPrinterEx a;
7406         struct spoolss_UserLevelCtr userlevel_ctr;
7407
7408         ZERO_STRUCT(userlevel_ctr);
7409
7410         userlevel_ctr.level = 1;
7411
7412         a.in.server             = r->in.server;
7413         a.in.info_ctr           = r->in.info_ctr;
7414         a.in.devmode_ctr        = r->in.devmode_ctr;
7415         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7416         a.in.userlevel_ctr      = &userlevel_ctr;
7417         a.out.handle            = r->out.handle;
7418
7419         return _spoolss_AddPrinterEx(p, &a);
7420 }
7421
7422 /****************************************************************
7423  _spoolss_AddPrinterDriverEx
7424 ****************************************************************/
7425
7426 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7427                                    struct spoolss_AddPrinterDriverEx *r)
7428 {
7429         WERROR err = WERR_OK;
7430         char *driver_name = NULL;
7431         uint32_t version;
7432         const char *fn;
7433
7434         switch (p->hdr_req.opnum) {
7435                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7436                         fn = "_spoolss_AddPrinterDriver";
7437                         break;
7438                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7439                         fn = "_spoolss_AddPrinterDriverEx";
7440                         break;
7441                 default:
7442                         return WERR_INVALID_PARAM;
7443         }
7444
7445         /*
7446          * we only support the semantics of AddPrinterDriver()
7447          * i.e. only copy files that are newer than existing ones
7448          */
7449
7450         if (r->in.flags == 0) {
7451                 return WERR_INVALID_PARAM;
7452         }
7453
7454         if (r->in.flags != APD_COPY_NEW_FILES) {
7455                 return WERR_ACCESS_DENIED;
7456         }
7457
7458         /* FIXME */
7459         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7460                 /* Clever hack from Martin Zielinski <mz@seh.de>
7461                  * to allow downgrade from level 8 (Vista).
7462                  */
7463                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7464                         r->in.info_ctr->level));
7465                 return WERR_UNKNOWN_LEVEL;
7466         }
7467
7468         DEBUG(5,("Cleaning driver's information\n"));
7469         err = clean_up_driver_struct(p, r->in.info_ctr);
7470         if (!W_ERROR_IS_OK(err))
7471                 goto done;
7472
7473         DEBUG(5,("Moving driver to final destination\n"));
7474         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7475                                                               &err)) ) {
7476                 goto done;
7477         }
7478
7479         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7480                 err = WERR_ACCESS_DENIED;
7481                 goto done;
7482         }
7483
7484         /*
7485          * I think this is where he DrvUpgradePrinter() hook would be
7486          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7487          * server.  Right now, we just need to send ourselves a message
7488          * to update each printer bound to this driver.   --jerry
7489          */
7490
7491         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7492                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7493                         fn, driver_name));
7494         }
7495
7496         /*
7497          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7498          * decide if the driver init data should be deleted. The rules are:
7499          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7500          *  2) delete init data only if there is no 2k/Xp driver
7501          *  3) always delete init data
7502          * The generalized rule is always use init data from the highest order driver.
7503          * It is necessary to follow the driver install by an initialization step to
7504          * finish off this process.
7505         */
7506
7507         switch (version) {
7508                 /*
7509                  * 9x printer driver - never delete init data
7510                 */
7511                 case 0:
7512                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7513                                 fn, driver_name));
7514                         break;
7515
7516                 /*
7517                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7518                  * there is no 2k/Xp driver init data for this driver name.
7519                 */
7520                 case 2:
7521                 {
7522                         struct spoolss_DriverInfo8 *driver1;
7523
7524                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
7525                                 /*
7526                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7527                                 */
7528                                 if (!del_driver_init(driver_name))
7529                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7530                                                 fn, driver_name));
7531                         } else {
7532                                 /*
7533                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7534                                 */
7535                                 free_a_printer_driver(driver1);
7536                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7537                                         fn, driver_name));
7538                         }
7539                 }
7540                 break;
7541
7542                 /*
7543                  * 2k or Xp printer driver - always delete init data
7544                 */
7545                 case 3:
7546                         if (!del_driver_init(driver_name))
7547                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7548                                         fn, driver_name));
7549                         break;
7550
7551                 default:
7552                         DEBUG(0,("%s: invalid level=%d\n", fn,
7553                                 r->in.info_ctr->level));
7554                         break;
7555         }
7556
7557
7558 done:
7559         return err;
7560 }
7561
7562 /****************************************************************
7563  _spoolss_AddPrinterDriver
7564 ****************************************************************/
7565
7566 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7567                                  struct spoolss_AddPrinterDriver *r)
7568 {
7569         struct spoolss_AddPrinterDriverEx a;
7570
7571         switch (r->in.info_ctr->level) {
7572         case 2:
7573         case 3:
7574         case 4:
7575         case 5:
7576                 break;
7577         default:
7578                 return WERR_UNKNOWN_LEVEL;
7579         }
7580
7581         a.in.servername         = r->in.servername;
7582         a.in.info_ctr           = r->in.info_ctr;
7583         a.in.flags              = APD_COPY_NEW_FILES;
7584
7585         return _spoolss_AddPrinterDriverEx(p, &a);
7586 }
7587
7588 /****************************************************************************
7589 ****************************************************************************/
7590
7591 struct _spoolss_paths {
7592         int type;
7593         const char *share;
7594         const char *dir;
7595 };
7596
7597 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7598
7599 static const struct _spoolss_paths spoolss_paths[]= {
7600         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7601         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7602 };
7603
7604 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7605                                           const char *servername,
7606                                           const char *environment,
7607                                           int component,
7608                                           char **path)
7609 {
7610         const char *pservername = NULL;
7611         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7612         const char *short_archi;
7613
7614         *path = NULL;
7615
7616         /* environment may be empty */
7617         if (environment && strlen(environment)) {
7618                 long_archi = environment;
7619         }
7620
7621         /* servername may be empty */
7622         if (servername && strlen(servername)) {
7623                 pservername = canon_servername(servername);
7624
7625                 if (!is_myname_or_ipaddr(pservername)) {
7626                         return WERR_INVALID_PARAM;
7627                 }
7628         }
7629
7630         if (!(short_archi = get_short_archi(long_archi))) {
7631                 return WERR_INVALID_ENVIRONMENT;
7632         }
7633
7634         switch (component) {
7635         case SPOOLSS_PRTPROCS_PATH:
7636         case SPOOLSS_DRIVER_PATH:
7637                 if (pservername) {
7638                         *path = talloc_asprintf(mem_ctx,
7639                                         "\\\\%s\\%s\\%s",
7640                                         pservername,
7641                                         spoolss_paths[component].share,
7642                                         short_archi);
7643                 } else {
7644                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7645                                         SPOOLSS_DEFAULT_SERVER_PATH,
7646                                         spoolss_paths[component].dir,
7647                                         short_archi);
7648                 }
7649                 break;
7650         default:
7651                 return WERR_INVALID_PARAM;
7652         }
7653
7654         if (!*path) {
7655                 return WERR_NOMEM;
7656         }
7657
7658         return WERR_OK;
7659 }
7660
7661 /****************************************************************************
7662 ****************************************************************************/
7663
7664 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7665                                           const char *servername,
7666                                           const char *environment,
7667                                           struct spoolss_DriverDirectoryInfo1 *r)
7668 {
7669         WERROR werr;
7670         char *path = NULL;
7671
7672         werr = compose_spoolss_server_path(mem_ctx,
7673                                            servername,
7674                                            environment,
7675                                            SPOOLSS_DRIVER_PATH,
7676                                            &path);
7677         if (!W_ERROR_IS_OK(werr)) {
7678                 return werr;
7679         }
7680
7681         DEBUG(4,("printer driver directory: [%s]\n", path));
7682
7683         r->directory_name = path;
7684
7685         return WERR_OK;
7686 }
7687
7688 /****************************************************************
7689  _spoolss_GetPrinterDriverDirectory
7690 ****************************************************************/
7691
7692 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7693                                           struct spoolss_GetPrinterDriverDirectory *r)
7694 {
7695         WERROR werror;
7696
7697         /* that's an [in out] buffer */
7698
7699         if (!r->in.buffer && (r->in.offered != 0)) {
7700                 return WERR_INVALID_PARAM;
7701         }
7702
7703         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7704                 r->in.level));
7705
7706         *r->out.needed = 0;
7707
7708         /* r->in.level is ignored */
7709
7710         werror = getprinterdriverdir_level_1(p->mem_ctx,
7711                                              r->in.server,
7712                                              r->in.environment,
7713                                              &r->out.info->info1);
7714         if (!W_ERROR_IS_OK(werror)) {
7715                 TALLOC_FREE(r->out.info);
7716                 return werror;
7717         }
7718
7719         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7720                                                r->out.info, r->in.level);
7721         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7722
7723         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7724 }
7725
7726 /****************************************************************
7727  _spoolss_EnumPrinterData
7728 ****************************************************************/
7729
7730 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7731                                 struct spoolss_EnumPrinterData *r)
7732 {
7733         WERROR result;
7734         struct spoolss_EnumPrinterDataEx r2;
7735         uint32_t count;
7736         struct spoolss_PrinterEnumValues *info, *val = NULL;
7737         uint32_t needed;
7738
7739         r2.in.handle    = r->in.handle;
7740         r2.in.key_name  = "PrinterDriverData";
7741         r2.in.offered   = 0;
7742         r2.out.count    = &count;
7743         r2.out.info     = &info;
7744         r2.out.needed   = &needed;
7745
7746         result = _spoolss_EnumPrinterDataEx(p, &r2);
7747         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7748                 r2.in.offered = needed;
7749                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7750         }
7751         if (!W_ERROR_IS_OK(result)) {
7752                 return result;
7753         }
7754
7755         /*
7756          * The NT machine wants to know the biggest size of value and data
7757          *
7758          * cf: MSDN EnumPrinterData remark section
7759          */
7760
7761         if (!r->in.value_offered && !r->in.data_offered) {
7762                 uint32_t biggest_valuesize = 0;
7763                 uint32_t biggest_datasize = 0;
7764                 int i, name_length;
7765
7766                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7767
7768                 for (i=0; i<count; i++) {
7769
7770                         name_length = strlen(info[i].value_name);
7771                         if (strlen(info[i].value_name) > biggest_valuesize) {
7772                                 biggest_valuesize = name_length;
7773                         }
7774
7775                         if (info[i].data_length > biggest_datasize) {
7776                                 biggest_datasize = info[i].data_length;
7777                         }
7778
7779                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7780                                 biggest_datasize));
7781                 }
7782
7783                 /* the value is an UNICODE string but real_value_size is the length
7784                    in bytes including the trailing 0 */
7785
7786                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7787                 *r->out.data_needed  = biggest_datasize;
7788
7789                 DEBUG(6,("final values: [%d], [%d]\n",
7790                         *r->out.value_needed, *r->out.data_needed));
7791
7792                 return WERR_OK;
7793         }
7794
7795         if (r->in.enum_index < count) {
7796                 val = &info[r->in.enum_index];
7797         }
7798
7799         if (val == NULL) {
7800                 /* out_value should default to "" or else NT4 has
7801                    problems unmarshalling the response */
7802
7803                 if (r->in.value_offered) {
7804                         *r->out.value_needed = 1;
7805                         r->out.value_name = talloc_strdup(r, "");
7806                         if (!r->out.value_name) {
7807                                 return WERR_NOMEM;
7808                         }
7809                 } else {
7810                         r->out.value_name = NULL;
7811                         *r->out.value_needed = 0;
7812                 }
7813
7814                 /* the data is counted in bytes */
7815
7816                 *r->out.data_needed = r->in.data_offered;
7817
7818                 result = WERR_NO_MORE_ITEMS;
7819         } else {
7820                 /*
7821                  * the value is:
7822                  * - counted in bytes in the request
7823                  * - counted in UNICODE chars in the max reply
7824                  * - counted in bytes in the real size
7825                  *
7826                  * take a pause *before* coding not *during* coding
7827                  */
7828
7829                 /* name */
7830                 if (r->in.value_offered) {
7831                         r->out.value_name = talloc_strdup(r, val->value_name);
7832                         if (!r->out.value_name) {
7833                                 return WERR_NOMEM;
7834                         }
7835                         *r->out.value_needed = val->value_name_len;
7836                 } else {
7837                         r->out.value_name = NULL;
7838                         *r->out.value_needed = 0;
7839                 }
7840
7841                 /* type */
7842
7843                 *r->out.type = val->type;
7844
7845                 /* data - counted in bytes */
7846
7847                 /*
7848                  * See the section "Dynamically Typed Query Parameters"
7849                  * in MS-RPRN.
7850                  */
7851
7852                 if (r->out.data && val->data && val->data->data &&
7853                                 val->data_length && r->in.data_offered) {
7854                         memcpy(r->out.data, val->data->data,
7855                                 MIN(val->data_length,r->in.data_offered));
7856                 }
7857
7858                 *r->out.data_needed = val->data_length;
7859
7860                 result = WERR_OK;
7861         }
7862
7863         return result;
7864 }
7865
7866 /****************************************************************
7867  _spoolss_SetPrinterData
7868 ****************************************************************/
7869
7870 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7871                                struct spoolss_SetPrinterData *r)
7872 {
7873         struct spoolss_SetPrinterDataEx r2;
7874
7875         r2.in.handle            = r->in.handle;
7876         r2.in.key_name          = "PrinterDriverData";
7877         r2.in.value_name        = r->in.value_name;
7878         r2.in.type              = r->in.type;
7879         r2.in.data              = r->in.data;
7880         r2.in.offered           = r->in.offered;
7881
7882         return _spoolss_SetPrinterDataEx(p, &r2);
7883 }
7884
7885 /****************************************************************
7886  _spoolss_ResetPrinter
7887 ****************************************************************/
7888
7889 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7890                              struct spoolss_ResetPrinter *r)
7891 {
7892         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7893         int             snum;
7894
7895         DEBUG(5,("_spoolss_ResetPrinter\n"));
7896
7897         /*
7898          * All we do is to check to see if the handle and queue is valid.
7899          * This call really doesn't mean anything to us because we only
7900          * support RAW printing.   --jerry
7901          */
7902
7903         if (!Printer) {
7904                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7905                         OUR_HANDLE(r->in.handle)));
7906                 return WERR_BADFID;
7907         }
7908
7909         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7910                 return WERR_BADFID;
7911
7912
7913         /* blindly return success */
7914         return WERR_OK;
7915 }
7916
7917 /****************************************************************
7918  _spoolss_DeletePrinterData
7919 ****************************************************************/
7920
7921 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7922                                   struct spoolss_DeletePrinterData *r)
7923 {
7924         struct spoolss_DeletePrinterDataEx r2;
7925
7926         r2.in.handle            = r->in.handle;
7927         r2.in.key_name          = "PrinterDriverData";
7928         r2.in.value_name        = r->in.value_name;
7929
7930         return _spoolss_DeletePrinterDataEx(p, &r2);
7931 }
7932
7933 /****************************************************************
7934  _spoolss_AddForm
7935 ****************************************************************/
7936
7937 WERROR _spoolss_AddForm(pipes_struct *p,
7938                         struct spoolss_AddForm *r)
7939 {
7940         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7941         nt_forms_struct tmpForm;
7942         int snum = -1;
7943         WERROR status = WERR_OK;
7944         NT_PRINTER_INFO_LEVEL *printer = NULL;
7945         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7946
7947         int count=0;
7948         nt_forms_struct *list=NULL;
7949         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7950         int i;
7951
7952         DEBUG(5,("_spoolss_AddForm\n"));
7953
7954         if (!Printer) {
7955                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7956                         OUR_HANDLE(r->in.handle)));
7957                 return WERR_BADFID;
7958         }
7959
7960
7961         /* forms can be added on printer or on the print server handle */
7962
7963         if ( Printer->printer_type == SPLHND_PRINTER )
7964         {
7965                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7966                         return WERR_BADFID;
7967
7968                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7969                 if (!W_ERROR_IS_OK(status))
7970                         goto done;
7971         }
7972
7973         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7974            and not a printer admin, then fail */
7975
7976         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7977              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7978              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7979                                           NULL, NULL,
7980                                           p->server_info->ptok,
7981                                           lp_printer_admin(snum))) {
7982                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7983                 status = WERR_ACCESS_DENIED;
7984                 goto done;
7985         }
7986
7987         switch (form->flags) {
7988         case SPOOLSS_FORM_USER:
7989         case SPOOLSS_FORM_BUILTIN:
7990         case SPOOLSS_FORM_PRINTER:
7991                 break;
7992         default:
7993                 status = WERR_INVALID_PARAM;
7994                 goto done;
7995         }
7996
7997         /* can't add if builtin */
7998
7999         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8000                 status = WERR_FILE_EXISTS;
8001                 goto done;
8002         }
8003
8004         count = get_ntforms(&list);
8005
8006         for (i=0; i < count; i++) {
8007                 if (strequal(form->form_name, list[i].name)) {
8008                         status = WERR_FILE_EXISTS;
8009                         goto done;
8010                 }
8011         }
8012
8013         if(!add_a_form(&list, form, &count)) {
8014                 status =  WERR_NOMEM;
8015                 goto done;
8016         }
8017
8018         become_root();
8019         write_ntforms(&list, count);
8020         unbecome_root();
8021
8022         /*
8023          * ChangeID must always be set if this is a printer
8024          */
8025
8026         if ( Printer->printer_type == SPLHND_PRINTER )
8027                 status = mod_a_printer(printer, 2);
8028
8029 done:
8030         if ( printer )
8031                 free_a_printer(&printer, 2);
8032         SAFE_FREE(list);
8033
8034         return status;
8035 }
8036
8037 /****************************************************************
8038  _spoolss_DeleteForm
8039 ****************************************************************/
8040
8041 WERROR _spoolss_DeleteForm(pipes_struct *p,
8042                            struct spoolss_DeleteForm *r)
8043 {
8044         const char *form_name = r->in.form_name;
8045         nt_forms_struct tmpForm;
8046         int count=0;
8047         nt_forms_struct *list=NULL;
8048         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8049         int snum = -1;
8050         WERROR status = WERR_OK;
8051         NT_PRINTER_INFO_LEVEL *printer = NULL;
8052         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8053         bool ret = false;
8054
8055         DEBUG(5,("_spoolss_DeleteForm\n"));
8056
8057         if (!Printer) {
8058                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8059                         OUR_HANDLE(r->in.handle)));
8060                 return WERR_BADFID;
8061         }
8062
8063         /* forms can be deleted on printer of on the print server handle */
8064
8065         if ( Printer->printer_type == SPLHND_PRINTER )
8066         {
8067                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8068                         return WERR_BADFID;
8069
8070                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8071                 if (!W_ERROR_IS_OK(status))
8072                         goto done;
8073         }
8074
8075         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8076              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8077              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8078                                           NULL, NULL,
8079                                           p->server_info->ptok,
8080                                           lp_printer_admin(snum))) {
8081                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8082                 return WERR_ACCESS_DENIED;
8083         }
8084
8085
8086         /* can't delete if builtin */
8087
8088         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8089                 status = WERR_INVALID_PARAM;
8090                 goto done;
8091         }
8092
8093         count = get_ntforms(&list);
8094
8095         become_root();
8096         ret = delete_a_form(&list, form_name, &count, &status);
8097         unbecome_root();
8098         if (ret == false) {
8099                 goto done;
8100         }
8101
8102         /*
8103          * ChangeID must always be set if this is a printer
8104          */
8105
8106         if ( Printer->printer_type == SPLHND_PRINTER )
8107                 status = mod_a_printer(printer, 2);
8108
8109 done:
8110         if ( printer )
8111                 free_a_printer(&printer, 2);
8112         SAFE_FREE(list);
8113
8114         return status;
8115 }
8116
8117 /****************************************************************
8118  _spoolss_SetForm
8119 ****************************************************************/
8120
8121 WERROR _spoolss_SetForm(pipes_struct *p,
8122                         struct spoolss_SetForm *r)
8123 {
8124         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8125         nt_forms_struct tmpForm;
8126         int snum = -1;
8127         WERROR status = WERR_OK;
8128         NT_PRINTER_INFO_LEVEL *printer = NULL;
8129         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8130
8131         int count=0;
8132         nt_forms_struct *list=NULL;
8133         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8134
8135         DEBUG(5,("_spoolss_SetForm\n"));
8136
8137         if (!Printer) {
8138                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8139                         OUR_HANDLE(r->in.handle)));
8140                 return WERR_BADFID;
8141         }
8142
8143         /* forms can be modified on printer of on the print server handle */
8144
8145         if ( Printer->printer_type == SPLHND_PRINTER )
8146         {
8147                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8148                         return WERR_BADFID;
8149
8150                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8151                 if (!W_ERROR_IS_OK(status))
8152                         goto done;
8153         }
8154
8155         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8156            and not a printer admin, then fail */
8157
8158         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8159              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8160              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8161                                           NULL, NULL,
8162                                           p->server_info->ptok,
8163                                           lp_printer_admin(snum))) {
8164                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8165                 status = WERR_ACCESS_DENIED;
8166                 goto done;
8167         }
8168
8169         /* can't set if builtin */
8170         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8171                 status = WERR_INVALID_PARAM;
8172                 goto done;
8173         }
8174
8175         count = get_ntforms(&list);
8176         update_a_form(&list, form, count);
8177         become_root();
8178         write_ntforms(&list, count);
8179         unbecome_root();
8180
8181         /*
8182          * ChangeID must always be set if this is a printer
8183          */
8184
8185         if ( Printer->printer_type == SPLHND_PRINTER )
8186                 status = mod_a_printer(printer, 2);
8187
8188
8189 done:
8190         if ( printer )
8191                 free_a_printer(&printer, 2);
8192         SAFE_FREE(list);
8193
8194         return status;
8195 }
8196
8197 /****************************************************************************
8198  fill_print_processor1
8199 ****************************************************************************/
8200
8201 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8202                                     struct spoolss_PrintProcessorInfo1 *r,
8203                                     const char *print_processor_name)
8204 {
8205         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8206         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8207
8208         return WERR_OK;
8209 }
8210
8211 /****************************************************************************
8212  enumprintprocessors level 1.
8213 ****************************************************************************/
8214
8215 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8216                                           union spoolss_PrintProcessorInfo **info_p,
8217                                           uint32_t *count)
8218 {
8219         union spoolss_PrintProcessorInfo *info;
8220         WERROR result;
8221
8222         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8223         W_ERROR_HAVE_NO_MEMORY(info);
8224
8225         *count = 1;
8226
8227         result = fill_print_processor1(info, &info[0].info1, "winprint");
8228         if (!W_ERROR_IS_OK(result)) {
8229                 goto out;
8230         }
8231
8232  out:
8233         if (!W_ERROR_IS_OK(result)) {
8234                 TALLOC_FREE(info);
8235                 *count = 0;
8236                 return result;
8237         }
8238
8239         *info_p = info;
8240
8241         return WERR_OK;
8242 }
8243
8244 /****************************************************************
8245  _spoolss_EnumPrintProcessors
8246 ****************************************************************/
8247
8248 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8249                                     struct spoolss_EnumPrintProcessors *r)
8250 {
8251         WERROR result;
8252
8253         /* that's an [in out] buffer */
8254
8255         if (!r->in.buffer && (r->in.offered != 0)) {
8256                 return WERR_INVALID_PARAM;
8257         }
8258
8259         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8260
8261         /*
8262          * Enumerate the print processors ...
8263          *
8264          * Just reply with "winprint", to keep NT happy
8265          * and I can use my nice printer checker.
8266          */
8267
8268         *r->out.count = 0;
8269         *r->out.needed = 0;
8270         *r->out.info = NULL;
8271
8272         switch (r->in.level) {
8273         case 1:
8274                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8275                                                      r->out.count);
8276                 break;
8277         default:
8278                 return WERR_UNKNOWN_LEVEL;
8279         }
8280
8281         if (!W_ERROR_IS_OK(result)) {
8282                 return result;
8283         }
8284
8285         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8286                                                      spoolss_EnumPrintProcessors, NULL,
8287                                                      *r->out.info, r->in.level,
8288                                                      *r->out.count);
8289         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8290         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8291
8292         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8293 }
8294
8295 /****************************************************************************
8296  fill_printprocdatatype1
8297 ****************************************************************************/
8298
8299 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8300                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8301                                       const char *name_array)
8302 {
8303         r->name_array = talloc_strdup(mem_ctx, name_array);
8304         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8305
8306         return WERR_OK;
8307 }
8308
8309 /****************************************************************************
8310  enumprintprocdatatypes level 1.
8311 ****************************************************************************/
8312
8313 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8314                                              union spoolss_PrintProcDataTypesInfo **info_p,
8315                                              uint32_t *count)
8316 {
8317         WERROR result;
8318         union spoolss_PrintProcDataTypesInfo *info;
8319
8320         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8321         W_ERROR_HAVE_NO_MEMORY(info);
8322
8323         *count = 1;
8324
8325         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8326         if (!W_ERROR_IS_OK(result)) {
8327                 goto out;
8328         }
8329
8330  out:
8331         if (!W_ERROR_IS_OK(result)) {
8332                 TALLOC_FREE(info);
8333                 *count = 0;
8334                 return result;
8335         }
8336
8337         *info_p = info;
8338
8339         return WERR_OK;
8340 }
8341
8342 /****************************************************************
8343  _spoolss_EnumPrintProcDataTypes
8344 ****************************************************************/
8345
8346 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8347                                        struct spoolss_EnumPrintProcDataTypes *r)
8348 {
8349         WERROR result;
8350
8351         /* that's an [in out] buffer */
8352
8353         if (!r->in.buffer && (r->in.offered != 0)) {
8354                 return WERR_INVALID_PARAM;
8355         }
8356
8357         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8358
8359         *r->out.count = 0;
8360         *r->out.needed = 0;
8361         *r->out.info = NULL;
8362
8363         switch (r->in.level) {
8364         case 1:
8365                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8366                                                         r->out.count);
8367                 break;
8368         default:
8369                 return WERR_UNKNOWN_LEVEL;
8370         }
8371
8372         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8373                                                      spoolss_EnumPrintProcDataTypes, NULL,
8374                                                      *r->out.info, r->in.level,
8375                                                      *r->out.count);
8376         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8377         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8378
8379         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8380 }
8381
8382 /****************************************************************************
8383  fill_monitor_1
8384 ****************************************************************************/
8385
8386 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8387                              struct spoolss_MonitorInfo1 *r,
8388                              const char *monitor_name)
8389 {
8390         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8391         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8392
8393         return WERR_OK;
8394 }
8395
8396 /****************************************************************************
8397  fill_monitor_2
8398 ****************************************************************************/
8399
8400 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8401                              struct spoolss_MonitorInfo2 *r,
8402                              const char *monitor_name,
8403                              const char *environment,
8404                              const char *dll_name)
8405 {
8406         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8407         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8408         r->environment                  = talloc_strdup(mem_ctx, environment);
8409         W_ERROR_HAVE_NO_MEMORY(r->environment);
8410         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8411         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8412
8413         return WERR_OK;
8414 }
8415
8416 /****************************************************************************
8417  enumprintmonitors level 1.
8418 ****************************************************************************/
8419
8420 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8421                                         union spoolss_MonitorInfo **info_p,
8422                                         uint32_t *count)
8423 {
8424         union spoolss_MonitorInfo *info;
8425         WERROR result = WERR_OK;
8426
8427         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8428         W_ERROR_HAVE_NO_MEMORY(info);
8429
8430         *count = 2;
8431
8432         result = fill_monitor_1(info, &info[0].info1,
8433                                 SPL_LOCAL_PORT);
8434         if (!W_ERROR_IS_OK(result)) {
8435                 goto out;
8436         }
8437
8438         result = fill_monitor_1(info, &info[1].info1,
8439                                 SPL_TCPIP_PORT);
8440         if (!W_ERROR_IS_OK(result)) {
8441                 goto out;
8442         }
8443
8444 out:
8445         if (!W_ERROR_IS_OK(result)) {
8446                 TALLOC_FREE(info);
8447                 *count = 0;
8448                 return result;
8449         }
8450
8451         *info_p = info;
8452
8453         return WERR_OK;
8454 }
8455
8456 /****************************************************************************
8457  enumprintmonitors level 2.
8458 ****************************************************************************/
8459
8460 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8461                                         union spoolss_MonitorInfo **info_p,
8462                                         uint32_t *count)
8463 {
8464         union spoolss_MonitorInfo *info;
8465         WERROR result = WERR_OK;
8466
8467         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8468         W_ERROR_HAVE_NO_MEMORY(info);
8469
8470         *count = 2;
8471
8472         result = fill_monitor_2(info, &info[0].info2,
8473                                 SPL_LOCAL_PORT,
8474                                 "Windows NT X86", /* FIXME */
8475                                 "localmon.dll");
8476         if (!W_ERROR_IS_OK(result)) {
8477                 goto out;
8478         }
8479
8480         result = fill_monitor_2(info, &info[1].info2,
8481                                 SPL_TCPIP_PORT,
8482                                 "Windows NT X86", /* FIXME */
8483                                 "tcpmon.dll");
8484         if (!W_ERROR_IS_OK(result)) {
8485                 goto out;
8486         }
8487
8488 out:
8489         if (!W_ERROR_IS_OK(result)) {
8490                 TALLOC_FREE(info);
8491                 *count = 0;
8492                 return result;
8493         }
8494
8495         *info_p = info;
8496
8497         return WERR_OK;
8498 }
8499
8500 /****************************************************************
8501  _spoolss_EnumMonitors
8502 ****************************************************************/
8503
8504 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8505                              struct spoolss_EnumMonitors *r)
8506 {
8507         WERROR result;
8508
8509         /* that's an [in out] buffer */
8510
8511         if (!r->in.buffer && (r->in.offered != 0)) {
8512                 return WERR_INVALID_PARAM;
8513         }
8514
8515         DEBUG(5,("_spoolss_EnumMonitors\n"));
8516
8517         /*
8518          * Enumerate the print monitors ...
8519          *
8520          * Just reply with "Local Port", to keep NT happy
8521          * and I can use my nice printer checker.
8522          */
8523
8524         *r->out.count = 0;
8525         *r->out.needed = 0;
8526         *r->out.info = NULL;
8527
8528         switch (r->in.level) {
8529         case 1:
8530                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8531                                                    r->out.count);
8532                 break;
8533         case 2:
8534                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8535                                                    r->out.count);
8536                 break;
8537         default:
8538                 return WERR_UNKNOWN_LEVEL;
8539         }
8540
8541         if (!W_ERROR_IS_OK(result)) {
8542                 return result;
8543         }
8544
8545         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8546                                                      spoolss_EnumMonitors, NULL,
8547                                                      *r->out.info, r->in.level,
8548                                                      *r->out.count);
8549         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8550         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8551
8552         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8553 }
8554
8555 /****************************************************************************
8556 ****************************************************************************/
8557
8558 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8559                              const print_queue_struct *queue,
8560                              int count, int snum,
8561                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8562                              uint32_t jobid,
8563                              struct spoolss_JobInfo1 *r)
8564 {
8565         int i = 0;
8566         bool found = false;
8567
8568         for (i=0; i<count; i++) {
8569                 if (queue[i].job == (int)jobid) {
8570                         found = true;
8571                         break;
8572                 }
8573         }
8574
8575         if (found == false) {
8576                 /* NT treats not found as bad param... yet another bad choice */
8577                 return WERR_INVALID_PARAM;
8578         }
8579
8580         return fill_job_info1(mem_ctx,
8581                               r,
8582                               &queue[i],
8583                               i,
8584                               snum,
8585                               ntprinter);
8586 }
8587
8588 /****************************************************************************
8589 ****************************************************************************/
8590
8591 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8592                              const print_queue_struct *queue,
8593                              int count, int snum,
8594                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8595                              uint32_t jobid,
8596                              struct spoolss_JobInfo2 *r)
8597 {
8598         int i = 0;
8599         bool found = false;
8600         struct spoolss_DeviceMode *devmode;
8601         NT_DEVICEMODE *nt_devmode;
8602         WERROR result;
8603
8604         for (i=0; i<count; i++) {
8605                 if (queue[i].job == (int)jobid) {
8606                         found = true;
8607                         break;
8608                 }
8609         }
8610
8611         if (found == false) {
8612                 /* NT treats not found as bad param... yet another bad
8613                    choice */
8614                 return WERR_INVALID_PARAM;
8615         }
8616
8617         /*
8618          * if the print job does not have a DEVMODE associated with it,
8619          * just use the one for the printer. A NULL devicemode is not
8620          *  a failure condition
8621          */
8622
8623         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8624         if (nt_devmode) {
8625                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8626                 W_ERROR_HAVE_NO_MEMORY(devmode);
8627                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8628                 if (!W_ERROR_IS_OK(result)) {
8629                         return result;
8630                 }
8631         } else {
8632                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8633                 W_ERROR_HAVE_NO_MEMORY(devmode);
8634         }
8635
8636         return fill_job_info2(mem_ctx,
8637                               r,
8638                               &queue[i],
8639                               i,
8640                               snum,
8641                               ntprinter,
8642                               devmode);
8643 }
8644
8645 /****************************************************************
8646  _spoolss_GetJob
8647 ****************************************************************/
8648
8649 WERROR _spoolss_GetJob(pipes_struct *p,
8650                        struct spoolss_GetJob *r)
8651 {
8652         WERROR result = WERR_OK;
8653         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8654         int snum;
8655         int count;
8656         print_queue_struct      *queue = NULL;
8657         print_status_struct prt_status;
8658
8659         /* that's an [in out] buffer */
8660
8661         if (!r->in.buffer && (r->in.offered != 0)) {
8662                 return WERR_INVALID_PARAM;
8663         }
8664
8665         DEBUG(5,("_spoolss_GetJob\n"));
8666
8667         *r->out.needed = 0;
8668
8669         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8670                 return WERR_BADFID;
8671         }
8672
8673         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8674         if (!W_ERROR_IS_OK(result)) {
8675                 return result;
8676         }
8677
8678         count = print_queue_status(snum, &queue, &prt_status);
8679
8680         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8681                      count, prt_status.status, prt_status.message));
8682
8683         switch (r->in.level) {
8684         case 1:
8685                 result = getjob_level_1(p->mem_ctx,
8686                                         queue, count, snum, ntprinter,
8687                                         r->in.job_id, &r->out.info->info1);
8688                 break;
8689         case 2:
8690                 result = getjob_level_2(p->mem_ctx,
8691                                         queue, count, snum, ntprinter,
8692                                         r->in.job_id, &r->out.info->info2);
8693                 break;
8694         default:
8695                 result = WERR_UNKNOWN_LEVEL;
8696                 break;
8697         }
8698
8699         SAFE_FREE(queue);
8700         free_a_printer(&ntprinter, 2);
8701
8702         if (!W_ERROR_IS_OK(result)) {
8703                 TALLOC_FREE(r->out.info);
8704                 return result;
8705         }
8706
8707         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8708                                                r->out.info, r->in.level);
8709         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8710
8711         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8712 }
8713
8714 /****************************************************************
8715  _spoolss_GetPrinterDataEx
8716 ****************************************************************/
8717
8718 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8719                                  struct spoolss_GetPrinterDataEx *r)
8720 {
8721
8722         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8723         struct regval_blob              *val = NULL;
8724         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8725         int                     snum = 0;
8726         WERROR result = WERR_OK;
8727         DATA_BLOB blob;
8728
8729         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8730
8731         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8732                 r->in.key_name, r->in.value_name));
8733
8734         /* in case of problem, return some default values */
8735
8736         *r->out.needed  = 0;
8737         *r->out.type    = REG_NONE;
8738
8739         if (!Printer) {
8740                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8741                         OUR_HANDLE(r->in.handle)));
8742                 result = WERR_BADFID;
8743                 goto done;
8744         }
8745
8746         /* Is the handle to a printer or to the server? */
8747
8748         if (Printer->printer_type == SPLHND_SERVER) {
8749
8750                 union spoolss_PrinterData data;
8751
8752                 result = getprinterdata_printer_server(p->mem_ctx,
8753                                                        r->in.value_name,
8754                                                        r->out.type,
8755                                                        &data);
8756                 if (!W_ERROR_IS_OK(result)) {
8757                         goto done;
8758                 }
8759
8760                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8761                                                   *r->out.type, &data);
8762                 if (!W_ERROR_IS_OK(result)) {
8763                         goto done;
8764                 }
8765
8766                 *r->out.needed = blob.length;
8767
8768                 if (r->in.offered >= *r->out.needed) {
8769                         memcpy(r->out.data, blob.data, blob.length);
8770                 }
8771
8772                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8773         }
8774
8775         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8776                 result = WERR_BADFID;
8777                 goto done;
8778         }
8779
8780         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8781         if (!W_ERROR_IS_OK(result)) {
8782                 goto done;
8783         }
8784
8785         /* check to see if the keyname is valid */
8786         if (!strlen(r->in.key_name)) {
8787                 result = WERR_INVALID_PARAM;
8788                 goto done;
8789         }
8790
8791         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8792
8793         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8794             strequal(r->in.value_name, "ChangeId")) {
8795                 *r->out.type = REG_DWORD;
8796                 *r->out.needed = 4;
8797                 if (r->in.offered >= *r->out.needed) {
8798                         SIVAL(r->out.data, 0, printer->info_2->changeid);
8799                         result = WERR_OK;
8800                 }
8801                 goto done;
8802         }
8803
8804         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8805                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8806                         "Invalid keyname [%s]\n", r->in.key_name ));
8807                 result = WERR_BADFILE;
8808                 goto done;
8809         }
8810
8811         val = get_printer_data(printer->info_2,
8812                                r->in.key_name, r->in.value_name);
8813         if (!val) {
8814                 result = WERR_BADFILE;
8815                 goto done;
8816         }
8817
8818         *r->out.needed = regval_size(val);
8819         *r->out.type = regval_type(val);
8820
8821         if (r->in.offered >= *r->out.needed) {
8822                 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8823         }
8824  done:
8825         if (printer) {
8826                 free_a_printer(&printer, 2);
8827         }
8828
8829         if (!W_ERROR_IS_OK(result)) {
8830                 return result;
8831         }
8832
8833         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8834         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8835
8836         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8837 }
8838
8839 /****************************************************************
8840  _spoolss_SetPrinterDataEx
8841 ****************************************************************/
8842
8843 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8844                                  struct spoolss_SetPrinterDataEx *r)
8845 {
8846         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8847         int                     snum = 0;
8848         WERROR                  result = WERR_OK;
8849         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8850         char                    *oid_string;
8851
8852         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8853
8854         /* From MSDN documentation of SetPrinterDataEx: pass request to
8855            SetPrinterData if key is "PrinterDriverData" */
8856
8857         if (!Printer) {
8858                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8859                         OUR_HANDLE(r->in.handle)));
8860                 return WERR_BADFID;
8861         }
8862
8863         if (Printer->printer_type == SPLHND_SERVER) {
8864                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8865                         "Not implemented for server handles yet\n"));
8866                 return WERR_INVALID_PARAM;
8867         }
8868
8869         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8870                 return WERR_BADFID;
8871         }
8872
8873         /*
8874          * Access check : NT returns "access denied" if you make a
8875          * SetPrinterData call without the necessary privildge.
8876          * we were originally returning OK if nothing changed
8877          * which made Win2k issue **a lot** of SetPrinterData
8878          * when connecting to a printer  --jerry
8879          */
8880
8881         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8882                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8883                         "change denied by handle access permissions\n"));
8884                 return WERR_ACCESS_DENIED;
8885         }
8886
8887         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8888         if (!W_ERROR_IS_OK(result)) {
8889                 return result;
8890         }
8891
8892         /* check for OID in valuename */
8893
8894         oid_string = strchr(r->in.value_name, ',');
8895         if (oid_string) {
8896                 *oid_string = '\0';
8897                 oid_string++;
8898         }
8899
8900         /*
8901          * When client side code sets a magic printer data key, detect it and save
8902          * the current printer data and the magic key's data (its the DEVMODE) for
8903          * future printer/driver initializations.
8904          */
8905         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8906                 /* Set devmode and printer initialization info */
8907                 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
8908
8909                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8910
8911                 goto done;
8912         }
8913
8914         /* save the registry data */
8915
8916         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8917                                     r->in.type, r->in.data, r->in.offered);
8918
8919         if (W_ERROR_IS_OK(result)) {
8920                 /* save the OID if one was specified */
8921                 if (oid_string) {
8922                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8923                                 r->in.key_name, SPOOL_OID_KEY);
8924                         if (!str) {
8925                                 result = WERR_NOMEM;
8926                                 goto done;
8927                         }
8928
8929                         /*
8930                          * I'm not checking the status here on purpose.  Don't know
8931                          * if this is right, but I'm returning the status from the
8932                          * previous set_printer_dataex() call.  I have no idea if
8933                          * this is right.    --jerry
8934                          */
8935
8936                         set_printer_dataex(printer, str, r->in.value_name,
8937                                            REG_SZ, (uint8_t *)oid_string,
8938                                            strlen(oid_string)+1);
8939                 }
8940
8941                 result = mod_a_printer(printer, 2);
8942         }
8943
8944  done:
8945         free_a_printer(&printer, 2);
8946
8947         return result;
8948 }
8949
8950 /****************************************************************
8951  _spoolss_DeletePrinterDataEx
8952 ****************************************************************/
8953
8954 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8955                                     struct spoolss_DeletePrinterDataEx *r)
8956 {
8957         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8958         int             snum=0;
8959         WERROR          status = WERR_OK;
8960         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8961
8962         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8963
8964         if (!Printer) {
8965                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8966                         "Invalid handle (%s:%u:%u).\n",
8967                         OUR_HANDLE(r->in.handle)));
8968                 return WERR_BADFID;
8969         }
8970
8971         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8972                 return WERR_BADFID;
8973
8974         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8975                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8976                         "printer properties change denied by handle\n"));
8977                 return WERR_ACCESS_DENIED;
8978         }
8979
8980         if (!r->in.value_name || !r->in.key_name) {
8981                 return WERR_NOMEM;
8982         }
8983
8984         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8985         if (!W_ERROR_IS_OK(status))
8986                 return status;
8987
8988         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8989
8990         if ( W_ERROR_IS_OK(status) )
8991                 mod_a_printer( printer, 2 );
8992
8993         free_a_printer(&printer, 2);
8994
8995         return status;
8996 }
8997
8998 /****************************************************************
8999  _spoolss_EnumPrinterKey
9000 ****************************************************************/
9001
9002 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9003                                struct spoolss_EnumPrinterKey *r)
9004 {
9005         fstring         *keynames = NULL;
9006         int             num_keys;
9007         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9008         NT_PRINTER_DATA *data;
9009         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9010         int             snum = 0;
9011         WERROR          result = WERR_BADFILE;
9012         int i;
9013         const char **array = NULL;
9014         DATA_BLOB blob;
9015
9016         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9017
9018         if (!Printer) {
9019                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9020                         OUR_HANDLE(r->in.handle)));
9021                 return WERR_BADFID;
9022         }
9023
9024         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9025                 return WERR_BADFID;
9026         }
9027
9028         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9029         if (!W_ERROR_IS_OK(result)) {
9030                 return result;
9031         }
9032
9033         /* get the list of subkey names */
9034
9035         data = printer->info_2->data;
9036
9037         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9038         if (num_keys == -1) {
9039                 result = WERR_BADFILE;
9040                 goto done;
9041         }
9042
9043         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9044         if (!array) {
9045                 result = WERR_NOMEM;
9046                 goto done;
9047         }
9048
9049         if (!num_keys) {
9050                 array[0] = talloc_strdup(array, "");
9051                 if (!array[0]) {
9052                         result = WERR_NOMEM;
9053                         goto done;
9054                 }
9055         }
9056
9057         for (i=0; i < num_keys; i++) {
9058
9059                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9060                         keynames[i]));
9061
9062                 array[i] = talloc_strdup(array, keynames[i]);
9063                 if (!array[i]) {
9064                         result = WERR_NOMEM;
9065                         goto done;
9066                 }
9067         }
9068
9069         if (!push_reg_multi_sz(p->mem_ctx, NULL, &blob, array)) {
9070                 result = WERR_NOMEM;
9071                 goto done;
9072         }
9073
9074         *r->out._ndr_size = r->in.offered / 2;
9075         *r->out.needed = blob.length;
9076
9077         if (r->in.offered < *r->out.needed) {
9078                 result = WERR_MORE_DATA;
9079         } else {
9080                 result = WERR_OK;
9081                 r->out.key_buffer->string_array = array;
9082         }
9083
9084  done:
9085         if (!W_ERROR_IS_OK(result)) {
9086                 TALLOC_FREE(array);
9087                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9088                         *r->out.needed = 0;
9089                 }
9090         }
9091
9092         free_a_printer(&printer, 2);
9093         SAFE_FREE(keynames);
9094
9095         return result;
9096 }
9097
9098 /****************************************************************
9099  _spoolss_DeletePrinterKey
9100 ****************************************************************/
9101
9102 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9103                                  struct spoolss_DeletePrinterKey *r)
9104 {
9105         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9106         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9107         int                     snum=0;
9108         WERROR                  status;
9109
9110         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9111
9112         if (!Printer) {
9113                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9114                         OUR_HANDLE(r->in.handle)));
9115                 return WERR_BADFID;
9116         }
9117
9118         /* if keyname == NULL, return error */
9119
9120         if ( !r->in.key_name )
9121                 return WERR_INVALID_PARAM;
9122
9123         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9124                 return WERR_BADFID;
9125
9126         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9127                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9128                         "printer properties change denied by handle\n"));
9129                 return WERR_ACCESS_DENIED;
9130         }
9131
9132         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9133         if (!W_ERROR_IS_OK(status))
9134                 return status;
9135
9136         /* delete the key and all subneys */
9137
9138         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9139
9140         if ( W_ERROR_IS_OK(status) )
9141                 status = mod_a_printer(printer, 2);
9142
9143         free_a_printer( &printer, 2 );
9144
9145         return status;
9146 }
9147
9148 /****************************************************************
9149 ****************************************************************/
9150
9151 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9152                                                    struct regval_blob *v,
9153                                                    struct spoolss_PrinterEnumValues *r)
9154 {
9155         r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9156         W_ERROR_HAVE_NO_MEMORY(r->data);
9157
9158         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9159         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9160
9161         r->value_name_len = strlen_m_term(regval_name(v)) * 2;
9162
9163         r->type         = regval_type(v);
9164         r->data_length  = regval_size(v);
9165
9166         if (r->data_length) {
9167                 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9168         }
9169
9170         return WERR_OK;
9171 }
9172
9173 /****************************************************************
9174  _spoolss_EnumPrinterDataEx
9175 ****************************************************************/
9176
9177 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9178                                   struct spoolss_EnumPrinterDataEx *r)
9179 {
9180         uint32_t        count = 0;
9181         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9182         struct spoolss_PrinterEnumValues *info = NULL;
9183         NT_PRINTER_DATA         *p_data;
9184         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9185         int             snum;
9186         WERROR          result;
9187         int             key_index;
9188         int             i;
9189
9190         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9191
9192         *r->out.count = 0;
9193         *r->out.needed = 0;
9194         *r->out.info = NULL;
9195
9196         if (!Printer) {
9197                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9198                         OUR_HANDLE(r->in.handle)));
9199                 return WERR_BADFID;
9200         }
9201
9202         /*
9203          * first check for a keyname of NULL or "".  Win2k seems to send
9204          * this a lot and we should send back WERR_INVALID_PARAM
9205          * no need to spend time looking up the printer in this case.
9206          * --jerry
9207          */
9208
9209         if (!strlen(r->in.key_name)) {
9210                 result = WERR_INVALID_PARAM;
9211                 goto done;
9212         }
9213
9214         /* get the printer off of disk */
9215
9216         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9217                 return WERR_BADFID;
9218         }
9219
9220         ZERO_STRUCT(printer);
9221         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9222         if (!W_ERROR_IS_OK(result)) {
9223                 return result;
9224         }
9225
9226         /* now look for a match on the key name */
9227
9228         p_data = printer->info_2->data;
9229
9230         key_index = lookup_printerkey(p_data, r->in.key_name);
9231         if (key_index == -1) {
9232                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9233                         r->in.key_name));
9234                 result = WERR_INVALID_PARAM;
9235                 goto done;
9236         }
9237
9238         /* allocate the memory for the array of pointers -- if necessary */
9239
9240         count = regval_ctr_numvals(p_data->keys[key_index].values);
9241         if (!count) {
9242                 result = WERR_OK; /* ??? */
9243                 goto done;
9244         }
9245
9246         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9247                                  struct spoolss_PrinterEnumValues,
9248                                  count);
9249         if (!info) {
9250                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9251                 result = WERR_NOMEM;
9252                 goto done;
9253         }
9254
9255         /*
9256          * loop through all params and build the array to pass
9257          * back to the  client
9258          */
9259
9260         for (i=0; i < count; i++) {
9261
9262                 struct regval_blob      *val;
9263
9264                 /* lookup the registry value */
9265
9266                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9267
9268                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9269
9270                 /* copy the data */
9271
9272                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9273                 if (!W_ERROR_IS_OK(result)) {
9274                         goto done;
9275                 }
9276         }
9277
9278 #if 0 /* FIXME - gd */
9279         /* housekeeping information in the reply */
9280
9281         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9282          * the hand marshalled container size is a multiple
9283          * of 4 bytes for RPC alignment.
9284          */
9285
9286         if (needed % 4) {
9287                 needed += 4-(needed % 4);
9288         }
9289 #endif
9290         *r->out.count   = count;
9291         *r->out.info    = info;
9292
9293  done:
9294
9295         if (printer) {
9296                 free_a_printer(&printer, 2);
9297         }
9298
9299         if (!W_ERROR_IS_OK(result)) {
9300                 return result;
9301         }
9302
9303         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9304                                                spoolss_EnumPrinterDataEx, NULL,
9305                                                *r->out.info,
9306                                                *r->out.count);
9307         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9308         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9309
9310         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9311 }
9312
9313 /****************************************************************************
9314 ****************************************************************************/
9315
9316 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9317                                                  const char *servername,
9318                                                  const char *environment,
9319                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9320 {
9321         WERROR werr;
9322         char *path = NULL;
9323
9324         werr = compose_spoolss_server_path(mem_ctx,
9325                                            servername,
9326                                            environment,
9327                                            SPOOLSS_PRTPROCS_PATH,
9328                                            &path);
9329         if (!W_ERROR_IS_OK(werr)) {
9330                 return werr;
9331         }
9332
9333         DEBUG(4,("print processor directory: [%s]\n", path));
9334
9335         r->directory_name = path;
9336
9337         return WERR_OK;
9338 }
9339
9340 /****************************************************************
9341  _spoolss_GetPrintProcessorDirectory
9342 ****************************************************************/
9343
9344 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9345                                            struct spoolss_GetPrintProcessorDirectory *r)
9346 {
9347         WERROR result;
9348
9349         /* that's an [in out] buffer */
9350
9351         if (!r->in.buffer && (r->in.offered != 0)) {
9352                 return WERR_INVALID_PARAM;
9353         }
9354
9355         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9356                 r->in.level));
9357
9358         *r->out.needed = 0;
9359
9360         /* r->in.level is ignored */
9361
9362         /* We always should reply with a local print processor directory so that
9363          * users are not forced to have a [prnproc$] share on the Samba spoolss
9364          * server - Guenther */
9365
9366         result = getprintprocessordirectory_level_1(p->mem_ctx,
9367                                                     NULL, /* r->in.server */
9368                                                     r->in.environment,
9369                                                     &r->out.info->info1);
9370         if (!W_ERROR_IS_OK(result)) {
9371                 TALLOC_FREE(r->out.info);
9372                 return result;
9373         }
9374
9375         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9376                                                r->out.info, r->in.level);
9377         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9378
9379         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9380 }
9381
9382 /*******************************************************************
9383  ********************************************************************/
9384
9385 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9386                                const char *dllname)
9387 {
9388         enum ndr_err_code ndr_err;
9389         struct spoolss_MonitorUi ui;
9390
9391         ui.dll_name = dllname;
9392
9393         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9394                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9395         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9396                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9397         }
9398         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9399 }
9400
9401 /*******************************************************************
9402  Streams the monitor UI DLL name in UNICODE
9403 *******************************************************************/
9404
9405 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9406                                NT_USER_TOKEN *token, DATA_BLOB *in,
9407                                DATA_BLOB *out, uint32_t *needed)
9408 {
9409         const char *dllname = "tcpmonui.dll";
9410
9411         *needed = (strlen(dllname)+1) * 2;
9412
9413         if (out->length < *needed) {
9414                 return WERR_INSUFFICIENT_BUFFER;
9415         }
9416
9417         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9418                 return WERR_NOMEM;
9419         }
9420
9421         return WERR_OK;
9422 }
9423
9424 /*******************************************************************
9425  ********************************************************************/
9426
9427 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9428                              struct spoolss_PortData1 *port1,
9429                              const DATA_BLOB *buf)
9430 {
9431         enum ndr_err_code ndr_err;
9432         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9433                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9434         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9435                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9436         }
9437         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9438 }
9439
9440 /*******************************************************************
9441  ********************************************************************/
9442
9443 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9444                              struct spoolss_PortData2 *port2,
9445                              const DATA_BLOB *buf)
9446 {
9447         enum ndr_err_code ndr_err;
9448         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9449                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9450         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9451                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9452         }
9453         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9454 }
9455
9456 /*******************************************************************
9457  Create a new TCP/IP port
9458 *******************************************************************/
9459
9460 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9461                              NT_USER_TOKEN *token, DATA_BLOB *in,
9462                              DATA_BLOB *out, uint32_t *needed)
9463 {
9464         struct spoolss_PortData1 port1;
9465         struct spoolss_PortData2 port2;
9466         char *device_uri = NULL;
9467         uint32_t version;
9468
9469         const char *portname;
9470         const char *hostaddress;
9471         const char *queue;
9472         uint32_t port_number;
9473         uint32_t protocol;
9474
9475         /* peek for spoolss_PortData version */
9476
9477         if (!in || (in->length < (128 + 4))) {
9478                 return WERR_GENERAL_FAILURE;
9479         }
9480
9481         version = IVAL(in->data, 128);
9482
9483         switch (version) {
9484                 case 1:
9485                         ZERO_STRUCT(port1);
9486
9487                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9488                                 return WERR_NOMEM;
9489                         }
9490
9491                         portname        = port1.portname;
9492                         hostaddress     = port1.hostaddress;
9493                         queue           = port1.queue;
9494                         protocol        = port1.protocol;
9495                         port_number     = port1.port_number;
9496
9497                         break;
9498                 case 2:
9499                         ZERO_STRUCT(port2);
9500
9501                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9502                                 return WERR_NOMEM;
9503                         }
9504
9505                         portname        = port2.portname;
9506                         hostaddress     = port2.hostaddress;
9507                         queue           = port2.queue;
9508                         protocol        = port2.protocol;
9509                         port_number     = port2.port_number;
9510
9511                         break;
9512                 default:
9513                         DEBUG(1,("xcvtcp_addport: "
9514                                 "unknown version of port_data: %d\n", version));
9515                         return WERR_UNKNOWN_PORT;
9516         }
9517
9518         /* create the device URI and call the add_port_hook() */
9519
9520         switch (protocol) {
9521         case PROTOCOL_RAWTCP_TYPE:
9522                 device_uri = talloc_asprintf(mem_ctx,
9523                                 "socket://%s:%d/", hostaddress,
9524                                 port_number);
9525                 break;
9526
9527         case PROTOCOL_LPR_TYPE:
9528                 device_uri = talloc_asprintf(mem_ctx,
9529                         "lpr://%s/%s", hostaddress, queue );
9530                 break;
9531
9532         default:
9533                 return WERR_UNKNOWN_PORT;
9534         }
9535
9536         if (!device_uri) {
9537                 return WERR_NOMEM;
9538         }
9539
9540         return add_port_hook(mem_ctx, token, portname, device_uri);
9541 }
9542
9543 /*******************************************************************
9544 *******************************************************************/
9545
9546 struct xcv_api_table xcvtcp_cmds[] = {
9547         { "MonitorUI",  xcvtcp_monitorui },
9548         { "AddPort",    xcvtcp_addport},
9549         { NULL,         NULL }
9550 };
9551
9552 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9553                                      NT_USER_TOKEN *token, const char *command,
9554                                      DATA_BLOB *inbuf,
9555                                      DATA_BLOB *outbuf,
9556                                      uint32_t *needed )
9557 {
9558         int i;
9559
9560         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9561
9562         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9563                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9564                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9565         }
9566
9567         return WERR_BADFUNC;
9568 }
9569
9570 /*******************************************************************
9571 *******************************************************************/
9572 #if 0   /* don't support management using the "Local Port" monitor */
9573
9574 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9575                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9576                                  DATA_BLOB *out, uint32_t *needed)
9577 {
9578         const char *dllname = "localui.dll";
9579
9580         *needed = (strlen(dllname)+1) * 2;
9581
9582         if (out->length < *needed) {
9583                 return WERR_INSUFFICIENT_BUFFER;
9584         }
9585
9586         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9587                 return WERR_NOMEM;
9588         }
9589
9590         return WERR_OK;
9591 }
9592
9593 /*******************************************************************
9594 *******************************************************************/
9595
9596 struct xcv_api_table xcvlocal_cmds[] = {
9597         { "MonitorUI",  xcvlocal_monitorui },
9598         { NULL,         NULL }
9599 };
9600 #else
9601 struct xcv_api_table xcvlocal_cmds[] = {
9602         { NULL,         NULL }
9603 };
9604 #endif
9605
9606
9607
9608 /*******************************************************************
9609 *******************************************************************/
9610
9611 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9612                                        NT_USER_TOKEN *token, const char *command,
9613                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9614                                        uint32_t *needed)
9615 {
9616         int i;
9617
9618         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9619
9620         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9621                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9622                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9623         }
9624         return WERR_BADFUNC;
9625 }
9626
9627 /****************************************************************
9628  _spoolss_XcvData
9629 ****************************************************************/
9630
9631 WERROR _spoolss_XcvData(pipes_struct *p,
9632                         struct spoolss_XcvData *r)
9633 {
9634         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9635         DATA_BLOB out_data = data_blob_null;
9636         WERROR werror;
9637
9638         if (!Printer) {
9639                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9640                         OUR_HANDLE(r->in.handle)));
9641                 return WERR_BADFID;
9642         }
9643
9644         /* Has to be a handle to the TCP/IP port monitor */
9645
9646         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9647                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9648                 return WERR_BADFID;
9649         }
9650
9651         /* requires administrative access to the server */
9652
9653         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9654                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9655                 return WERR_ACCESS_DENIED;
9656         }
9657
9658         /* Allocate the outgoing buffer */
9659
9660         if (r->in.out_data_size) {
9661                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9662                 if (out_data.data == NULL) {
9663                         return WERR_NOMEM;
9664                 }
9665         }
9666
9667         switch ( Printer->printer_type ) {
9668         case SPLHND_PORTMON_TCP:
9669                 werror = process_xcvtcp_command(p->mem_ctx,
9670                                                 p->server_info->ptok,
9671                                                 r->in.function_name,
9672                                                 &r->in.in_data, &out_data,
9673                                                 r->out.needed);
9674                 break;
9675         case SPLHND_PORTMON_LOCAL:
9676                 werror = process_xcvlocal_command(p->mem_ctx,
9677                                                   p->server_info->ptok,
9678                                                   r->in.function_name,
9679                                                   &r->in.in_data, &out_data,
9680                                                   r->out.needed);
9681                 break;
9682         default:
9683                 werror = WERR_INVALID_PRINT_MONITOR;
9684         }
9685
9686         if (!W_ERROR_IS_OK(werror)) {
9687                 return werror;
9688         }
9689
9690         *r->out.status_code = 0;
9691
9692         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9693                 memcpy(r->out.out_data, out_data.data,
9694                         MIN(r->in.out_data_size, out_data.length));
9695         }
9696
9697         return WERR_OK;
9698 }
9699
9700 /****************************************************************
9701  _spoolss_AddPrintProcessor
9702 ****************************************************************/
9703
9704 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9705                                   struct spoolss_AddPrintProcessor *r)
9706 {
9707         /* for now, just indicate success and ignore the add.  We'll
9708            automatically set the winprint processor for printer
9709            entries later.  Used to debug the LexMark Optra S 1855 PCL
9710            driver --jerry */
9711
9712         return WERR_OK;
9713 }
9714
9715 /****************************************************************
9716  _spoolss_AddPort
9717 ****************************************************************/
9718
9719 WERROR _spoolss_AddPort(pipes_struct *p,
9720                         struct spoolss_AddPort *r)
9721 {
9722         /* do what w2k3 does */
9723
9724         return WERR_NOT_SUPPORTED;
9725 }
9726
9727 /****************************************************************
9728  _spoolss_GetPrinterDriver
9729 ****************************************************************/
9730
9731 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9732                                  struct spoolss_GetPrinterDriver *r)
9733 {
9734         p->rng_fault_state = true;
9735         return WERR_NOT_SUPPORTED;
9736 }
9737
9738 /****************************************************************
9739  _spoolss_ReadPrinter
9740 ****************************************************************/
9741
9742 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9743                             struct spoolss_ReadPrinter *r)
9744 {
9745         p->rng_fault_state = true;
9746         return WERR_NOT_SUPPORTED;
9747 }
9748
9749 /****************************************************************
9750  _spoolss_WaitForPrinterChange
9751 ****************************************************************/
9752
9753 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9754                                      struct spoolss_WaitForPrinterChange *r)
9755 {
9756         p->rng_fault_state = true;
9757         return WERR_NOT_SUPPORTED;
9758 }
9759
9760 /****************************************************************
9761  _spoolss_ConfigurePort
9762 ****************************************************************/
9763
9764 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9765                               struct spoolss_ConfigurePort *r)
9766 {
9767         p->rng_fault_state = true;
9768         return WERR_NOT_SUPPORTED;
9769 }
9770
9771 /****************************************************************
9772  _spoolss_DeletePort
9773 ****************************************************************/
9774
9775 WERROR _spoolss_DeletePort(pipes_struct *p,
9776                            struct spoolss_DeletePort *r)
9777 {
9778         p->rng_fault_state = true;
9779         return WERR_NOT_SUPPORTED;
9780 }
9781
9782 /****************************************************************
9783  _spoolss_CreatePrinterIC
9784 ****************************************************************/
9785
9786 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9787                                 struct spoolss_CreatePrinterIC *r)
9788 {
9789         p->rng_fault_state = true;
9790         return WERR_NOT_SUPPORTED;
9791 }
9792
9793 /****************************************************************
9794  _spoolss_PlayGDIScriptOnPrinterIC
9795 ****************************************************************/
9796
9797 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9798                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9799 {
9800         p->rng_fault_state = true;
9801         return WERR_NOT_SUPPORTED;
9802 }
9803
9804 /****************************************************************
9805  _spoolss_DeletePrinterIC
9806 ****************************************************************/
9807
9808 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9809                                 struct spoolss_DeletePrinterIC *r)
9810 {
9811         p->rng_fault_state = true;
9812         return WERR_NOT_SUPPORTED;
9813 }
9814
9815 /****************************************************************
9816  _spoolss_AddPrinterConnection
9817 ****************************************************************/
9818
9819 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9820                                      struct spoolss_AddPrinterConnection *r)
9821 {
9822         p->rng_fault_state = true;
9823         return WERR_NOT_SUPPORTED;
9824 }
9825
9826 /****************************************************************
9827  _spoolss_DeletePrinterConnection
9828 ****************************************************************/
9829
9830 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9831                                         struct spoolss_DeletePrinterConnection *r)
9832 {
9833         p->rng_fault_state = true;
9834         return WERR_NOT_SUPPORTED;
9835 }
9836
9837 /****************************************************************
9838  _spoolss_PrinterMessageBox
9839 ****************************************************************/
9840
9841 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9842                                   struct spoolss_PrinterMessageBox *r)
9843 {
9844         p->rng_fault_state = true;
9845         return WERR_NOT_SUPPORTED;
9846 }
9847
9848 /****************************************************************
9849  _spoolss_AddMonitor
9850 ****************************************************************/
9851
9852 WERROR _spoolss_AddMonitor(pipes_struct *p,
9853                            struct spoolss_AddMonitor *r)
9854 {
9855         p->rng_fault_state = true;
9856         return WERR_NOT_SUPPORTED;
9857 }
9858
9859 /****************************************************************
9860  _spoolss_DeleteMonitor
9861 ****************************************************************/
9862
9863 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9864                               struct spoolss_DeleteMonitor *r)
9865 {
9866         p->rng_fault_state = true;
9867         return WERR_NOT_SUPPORTED;
9868 }
9869
9870 /****************************************************************
9871  _spoolss_DeletePrintProcessor
9872 ****************************************************************/
9873
9874 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9875                                      struct spoolss_DeletePrintProcessor *r)
9876 {
9877         p->rng_fault_state = true;
9878         return WERR_NOT_SUPPORTED;
9879 }
9880
9881 /****************************************************************
9882  _spoolss_AddPrintProvidor
9883 ****************************************************************/
9884
9885 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9886                                  struct spoolss_AddPrintProvidor *r)
9887 {
9888         p->rng_fault_state = true;
9889         return WERR_NOT_SUPPORTED;
9890 }
9891
9892 /****************************************************************
9893  _spoolss_DeletePrintProvidor
9894 ****************************************************************/
9895
9896 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9897                                     struct spoolss_DeletePrintProvidor *r)
9898 {
9899         p->rng_fault_state = true;
9900         return WERR_NOT_SUPPORTED;
9901 }
9902
9903 /****************************************************************
9904  _spoolss_FindFirstPrinterChangeNotification
9905 ****************************************************************/
9906
9907 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9908                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9909 {
9910         p->rng_fault_state = true;
9911         return WERR_NOT_SUPPORTED;
9912 }
9913
9914 /****************************************************************
9915  _spoolss_FindNextPrinterChangeNotification
9916 ****************************************************************/
9917
9918 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9919                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9920 {
9921         p->rng_fault_state = true;
9922         return WERR_NOT_SUPPORTED;
9923 }
9924
9925 /****************************************************************
9926  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9927 ****************************************************************/
9928
9929 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9930                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9931 {
9932         p->rng_fault_state = true;
9933         return WERR_NOT_SUPPORTED;
9934 }
9935
9936 /****************************************************************
9937  _spoolss_ReplyOpenPrinter
9938 ****************************************************************/
9939
9940 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9941                                  struct spoolss_ReplyOpenPrinter *r)
9942 {
9943         p->rng_fault_state = true;
9944         return WERR_NOT_SUPPORTED;
9945 }
9946
9947 /****************************************************************
9948  _spoolss_RouterReplyPrinter
9949 ****************************************************************/
9950
9951 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9952                                    struct spoolss_RouterReplyPrinter *r)
9953 {
9954         p->rng_fault_state = true;
9955         return WERR_NOT_SUPPORTED;
9956 }
9957
9958 /****************************************************************
9959  _spoolss_ReplyClosePrinter
9960 ****************************************************************/
9961
9962 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9963                                   struct spoolss_ReplyClosePrinter *r)
9964 {
9965         p->rng_fault_state = true;
9966         return WERR_NOT_SUPPORTED;
9967 }
9968
9969 /****************************************************************
9970  _spoolss_AddPortEx
9971 ****************************************************************/
9972
9973 WERROR _spoolss_AddPortEx(pipes_struct *p,
9974                           struct spoolss_AddPortEx *r)
9975 {
9976         p->rng_fault_state = true;
9977         return WERR_NOT_SUPPORTED;
9978 }
9979
9980 /****************************************************************
9981  _spoolss_RouterFindFirstPrinterChangeNotification
9982 ****************************************************************/
9983
9984 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9985                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9986 {
9987         p->rng_fault_state = true;
9988         return WERR_NOT_SUPPORTED;
9989 }
9990
9991 /****************************************************************
9992  _spoolss_SpoolerInit
9993 ****************************************************************/
9994
9995 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9996                             struct spoolss_SpoolerInit *r)
9997 {
9998         p->rng_fault_state = true;
9999         return WERR_NOT_SUPPORTED;
10000 }
10001
10002 /****************************************************************
10003  _spoolss_ResetPrinterEx
10004 ****************************************************************/
10005
10006 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10007                                struct spoolss_ResetPrinterEx *r)
10008 {
10009         p->rng_fault_state = true;
10010         return WERR_NOT_SUPPORTED;
10011 }
10012
10013 /****************************************************************
10014  _spoolss_RouterReplyPrinterEx
10015 ****************************************************************/
10016
10017 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10018                                      struct spoolss_RouterReplyPrinterEx *r)
10019 {
10020         p->rng_fault_state = true;
10021         return WERR_NOT_SUPPORTED;
10022 }
10023
10024 /****************************************************************
10025  _spoolss_44
10026 ****************************************************************/
10027
10028 WERROR _spoolss_44(pipes_struct *p,
10029                    struct spoolss_44 *r)
10030 {
10031         p->rng_fault_state = true;
10032         return WERR_NOT_SUPPORTED;
10033 }
10034
10035 /****************************************************************
10036  _spoolss_47
10037 ****************************************************************/
10038
10039 WERROR _spoolss_47(pipes_struct *p,
10040                    struct spoolss_47 *r)
10041 {
10042         p->rng_fault_state = true;
10043         return WERR_NOT_SUPPORTED;
10044 }
10045
10046 /****************************************************************
10047  _spoolss_4a
10048 ****************************************************************/
10049
10050 WERROR _spoolss_4a(pipes_struct *p,
10051                    struct spoolss_4a *r)
10052 {
10053         p->rng_fault_state = true;
10054         return WERR_NOT_SUPPORTED;
10055 }
10056
10057 /****************************************************************
10058  _spoolss_4b
10059 ****************************************************************/
10060
10061 WERROR _spoolss_4b(pipes_struct *p,
10062                    struct spoolss_4b *r)
10063 {
10064         p->rng_fault_state = true;
10065         return WERR_NOT_SUPPORTED;
10066 }
10067
10068 /****************************************************************
10069  _spoolss_4c
10070 ****************************************************************/
10071
10072 WERROR _spoolss_4c(pipes_struct *p,
10073                    struct spoolss_4c *r)
10074 {
10075         p->rng_fault_state = true;
10076         return WERR_NOT_SUPPORTED;
10077 }
10078
10079 /****************************************************************
10080  _spoolss_53
10081 ****************************************************************/
10082
10083 WERROR _spoolss_53(pipes_struct *p,
10084                    struct spoolss_53 *r)
10085 {
10086         p->rng_fault_state = true;
10087         return WERR_NOT_SUPPORTED;
10088 }
10089
10090 /****************************************************************
10091  _spoolss_55
10092 ****************************************************************/
10093
10094 WERROR _spoolss_55(pipes_struct *p,
10095                    struct spoolss_55 *r)
10096 {
10097         p->rng_fault_state = true;
10098         return WERR_NOT_SUPPORTED;
10099 }
10100
10101 /****************************************************************
10102  _spoolss_56
10103 ****************************************************************/
10104
10105 WERROR _spoolss_56(pipes_struct *p,
10106                    struct spoolss_56 *r)
10107 {
10108         p->rng_fault_state = true;
10109         return WERR_NOT_SUPPORTED;
10110 }
10111
10112 /****************************************************************
10113  _spoolss_57
10114 ****************************************************************/
10115
10116 WERROR _spoolss_57(pipes_struct *p,
10117                    struct spoolss_57 *r)
10118 {
10119         p->rng_fault_state = true;
10120         return WERR_NOT_SUPPORTED;
10121 }
10122
10123 /****************************************************************
10124  _spoolss_5a
10125 ****************************************************************/
10126
10127 WERROR _spoolss_5a(pipes_struct *p,
10128                    struct spoolss_5a *r)
10129 {
10130         p->rng_fault_state = true;
10131         return WERR_NOT_SUPPORTED;
10132 }
10133
10134 /****************************************************************
10135  _spoolss_5b
10136 ****************************************************************/
10137
10138 WERROR _spoolss_5b(pipes_struct *p,
10139                    struct spoolss_5b *r)
10140 {
10141         p->rng_fault_state = true;
10142         return WERR_NOT_SUPPORTED;
10143 }
10144
10145 /****************************************************************
10146  _spoolss_5c
10147 ****************************************************************/
10148
10149 WERROR _spoolss_5c(pipes_struct *p,
10150                    struct spoolss_5c *r)
10151 {
10152         p->rng_fault_state = true;
10153         return WERR_NOT_SUPPORTED;
10154 }
10155
10156 /****************************************************************
10157  _spoolss_5d
10158 ****************************************************************/
10159
10160 WERROR _spoolss_5d(pipes_struct *p,
10161                    struct spoolss_5d *r)
10162 {
10163         p->rng_fault_state = true;
10164         return WERR_NOT_SUPPORTED;
10165 }
10166
10167 /****************************************************************
10168  _spoolss_5e
10169 ****************************************************************/
10170
10171 WERROR _spoolss_5e(pipes_struct *p,
10172                    struct spoolss_5e *r)
10173 {
10174         p->rng_fault_state = true;
10175         return WERR_NOT_SUPPORTED;
10176 }
10177
10178 /****************************************************************
10179  _spoolss_5f
10180 ****************************************************************/
10181
10182 WERROR _spoolss_5f(pipes_struct *p,
10183                    struct spoolss_5f *r)
10184 {
10185         p->rng_fault_state = true;
10186         return WERR_NOT_SUPPORTED;
10187 }
10188
10189 /****************************************************************
10190  _spoolss_60
10191 ****************************************************************/
10192
10193 WERROR _spoolss_60(pipes_struct *p,
10194                    struct spoolss_60 *r)
10195 {
10196         p->rng_fault_state = true;
10197         return WERR_NOT_SUPPORTED;
10198 }
10199
10200 /****************************************************************
10201  _spoolss_61
10202 ****************************************************************/
10203
10204 WERROR _spoolss_61(pipes_struct *p,
10205                    struct spoolss_61 *r)
10206 {
10207         p->rng_fault_state = true;
10208         return WERR_NOT_SUPPORTED;
10209 }
10210
10211 /****************************************************************
10212  _spoolss_62
10213 ****************************************************************/
10214
10215 WERROR _spoolss_62(pipes_struct *p,
10216                    struct spoolss_62 *r)
10217 {
10218         p->rng_fault_state = true;
10219         return WERR_NOT_SUPPORTED;
10220 }
10221
10222 /****************************************************************
10223  _spoolss_63
10224 ****************************************************************/
10225
10226 WERROR _spoolss_63(pipes_struct *p,
10227                    struct spoolss_63 *r)
10228 {
10229         p->rng_fault_state = true;
10230         return WERR_NOT_SUPPORTED;
10231 }
10232
10233 /****************************************************************
10234  _spoolss_64
10235 ****************************************************************/
10236
10237 WERROR _spoolss_64(pipes_struct *p,
10238                    struct spoolss_64 *r)
10239 {
10240         p->rng_fault_state = true;
10241         return WERR_NOT_SUPPORTED;
10242 }
10243
10244 /****************************************************************
10245  _spoolss_65
10246 ****************************************************************/
10247
10248 WERROR _spoolss_65(pipes_struct *p,
10249                    struct spoolss_65 *r)
10250 {
10251         p->rng_fault_state = true;
10252         return WERR_NOT_SUPPORTED;
10253 }
10254
10255 /****************************************************************
10256  _spoolss_GetCorePrinterDrivers
10257 ****************************************************************/
10258
10259 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10260                                       struct spoolss_GetCorePrinterDrivers *r)
10261 {
10262         p->rng_fault_state = true;
10263         return WERR_NOT_SUPPORTED;
10264 }
10265
10266 /****************************************************************
10267  _spoolss_67
10268 ****************************************************************/
10269
10270 WERROR _spoolss_67(pipes_struct *p,
10271                    struct spoolss_67 *r)
10272 {
10273         p->rng_fault_state = true;
10274         return WERR_NOT_SUPPORTED;
10275 }
10276
10277 /****************************************************************
10278  _spoolss_GetPrinterDriverPackagePath
10279 ****************************************************************/
10280
10281 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10282                                             struct spoolss_GetPrinterDriverPackagePath *r)
10283 {
10284         p->rng_fault_state = true;
10285         return WERR_NOT_SUPPORTED;
10286 }
10287
10288 /****************************************************************
10289  _spoolss_69
10290 ****************************************************************/
10291
10292 WERROR _spoolss_69(pipes_struct *p,
10293                    struct spoolss_69 *r)
10294 {
10295         p->rng_fault_state = true;
10296         return WERR_NOT_SUPPORTED;
10297 }
10298
10299 /****************************************************************
10300  _spoolss_6a
10301 ****************************************************************/
10302
10303 WERROR _spoolss_6a(pipes_struct *p,
10304                    struct spoolss_6a *r)
10305 {
10306         p->rng_fault_state = true;
10307         return WERR_NOT_SUPPORTED;
10308 }
10309
10310 /****************************************************************
10311  _spoolss_6b
10312 ****************************************************************/
10313
10314 WERROR _spoolss_6b(pipes_struct *p,
10315                    struct spoolss_6b *r)
10316 {
10317         p->rng_fault_state = true;
10318         return WERR_NOT_SUPPORTED;
10319 }
10320
10321 /****************************************************************
10322  _spoolss_6c
10323 ****************************************************************/
10324
10325 WERROR _spoolss_6c(pipes_struct *p,
10326                    struct spoolss_6c *r)
10327 {
10328         p->rng_fault_state = true;
10329         return WERR_NOT_SUPPORTED;
10330 }
10331
10332 /****************************************************************
10333  _spoolss_6d
10334 ****************************************************************/
10335
10336 WERROR _spoolss_6d(pipes_struct *p,
10337                    struct spoolss_6d *r)
10338 {
10339         p->rng_fault_state = true;
10340         return WERR_NOT_SUPPORTED;
10341 }