s3-spoolss: Fix GetPrinter level 101.
[gd/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.
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
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33         ((info)?ndr_size_##fn(info, level, ic, 0):0)
34
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
37
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
42
43
44 extern userdom_struct current_user_info;
45
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
48
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
52
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
55
56 static Printer_entry *printers_list;
57
58 typedef struct _counter_printer_0 {
59         struct _counter_printer_0 *next;
60         struct _counter_printer_0 *prev;
61
62         int snum;
63         uint32_t counter;
64 } counter_printer_0;
65
66 static counter_printer_0 *counter_list;
67
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
70
71
72 /* in printing/nt_printing.c */
73
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
75
76 /* API table for Xcv Monitor functions */
77
78 struct xcv_api_table {
79         const char *name;
80         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
81 };
82
83 /********************************************************************
84  * Canonicalize servername.
85  ********************************************************************/
86
87 static const char *canon_servername(const char *servername)
88 {
89         const char *pservername = servername;
90         while (*pservername == '\\') {
91                 pservername++;
92         }
93         return pservername;
94 }
95
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
98 {
99         switch (v) {
100         case LPQ_QUEUED:
101                 return 0;
102         case LPQ_PAUSED:
103                 return JOB_STATUS_PAUSED;
104         case LPQ_SPOOLING:
105                 return JOB_STATUS_SPOOLING;
106         case LPQ_PRINTING:
107                 return JOB_STATUS_PRINTING;
108         case LPQ_ERROR:
109                 return JOB_STATUS_ERROR;
110         case LPQ_DELETING:
111                 return JOB_STATUS_DELETING;
112         case LPQ_OFFLINE:
113                 return JOB_STATUS_OFFLINE;
114         case LPQ_PAPEROUT:
115                 return JOB_STATUS_PAPEROUT;
116         case LPQ_PRINTED:
117                 return JOB_STATUS_PRINTED;
118         case LPQ_DELETED:
119                 return JOB_STATUS_DELETED;
120         case LPQ_BLOCKED:
121                 return JOB_STATUS_BLOCKED_DEVQ;
122         case LPQ_USER_INTERVENTION:
123                 return JOB_STATUS_USER_INTERVENTION;
124         }
125         return 0;
126 }
127
128 static int nt_printq_status(int v)
129 {
130         switch (v) {
131         case LPQ_PAUSED:
132                 return PRINTER_STATUS_PAUSED;
133         case LPQ_QUEUED:
134         case LPQ_SPOOLING:
135         case LPQ_PRINTING:
136                 return 0;
137         }
138         return 0;
139 }
140
141 /***************************************************************************
142  Disconnect from the client
143 ****************************************************************************/
144
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
146 {
147         WERROR result;
148         NTSTATUS status;
149
150         /*
151          * Tell the specific printing tdb we no longer want messages for this printer
152          * by deregistering our PID.
153          */
154
155         if (!print_notify_deregister_pid(snum))
156                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
157
158         /* weird if the test succeds !!! */
159         if (smb_connections==0) {
160                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161                 return;
162         }
163
164         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
165                                                   handle,
166                                                   &result);
167         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169                         win_errstr(result)));
170
171         /* if it's the last connection, deconnect the IPC$ share */
172         if (smb_connections==1) {
173
174                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
176
177                 messaging_deregister(smbd_messaging_context(),
178                                      MSG_PRINTER_NOTIFY2, NULL);
179
180                 /* Tell the connections db we're no longer interested in
181                  * printer notify messages. */
182
183                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
184         }
185
186         smb_connections--;
187 }
188
189 /****************************************************************************
190  Functions to free a printer entry datastruct.
191 ****************************************************************************/
192
193 static int printer_entry_destructor(Printer_entry *Printer)
194 {
195         if (Printer->notify.client_connected == true) {
196                 int snum = -1;
197
198                 if ( Printer->printer_type == SPLHND_SERVER) {
199                         snum = -1;
200                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201                 } else if (Printer->printer_type == SPLHND_PRINTER) {
202                         snum = print_queue_snum(Printer->sharename);
203                         if (snum != -1)
204                                 srv_spoolss_replycloseprinter(snum,
205                                                 &Printer->notify.client_hnd);
206                 }
207         }
208
209         Printer->notify.flags=0;
210         Printer->notify.options=0;
211         Printer->notify.localmachine[0]='\0';
212         Printer->notify.printerlocal=0;
213         TALLOC_FREE(Printer->notify.option);
214         Printer->notify.client_connected = false;
215
216         free_nt_devicemode( &Printer->nt_devmode );
217         free_a_printer( &Printer->printer_info, 2 );
218
219         /* Remove from the internal list. */
220         DLIST_REMOVE(printers_list, Printer);
221         return 0;
222 }
223
224 /****************************************************************************
225   find printer index by handle
226 ****************************************************************************/
227
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229                                                 struct policy_handle *hnd)
230 {
231         Printer_entry *find_printer = NULL;
232
233         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
235                 return NULL;
236         }
237
238         return find_printer;
239 }
240
241 /****************************************************************************
242  Close printer index by handle.
243 ****************************************************************************/
244
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
246 {
247         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
248
249         if (!Printer) {
250                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
251                         OUR_HANDLE(hnd)));
252                 return false;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return true;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
265 {
266         char *cmd = lp_deleteprinter_cmd();
267         char *command = NULL;
268         int ret;
269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
270         bool is_print_op = false;
271
272         /* can't fail if we don't try */
273
274         if ( !*cmd )
275                 return WERR_OK;
276
277         command = talloc_asprintf(ctx,
278                         "%s \"%s\"",
279                         cmd, sharename);
280         if (!command) {
281                 return WERR_NOMEM;
282         }
283         if ( token )
284                 is_print_op = user_has_privileges( token, &se_printop );
285
286         DEBUG(10,("Running [%s]\n", command));
287
288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290         if ( is_print_op )
291                 become_root();
292
293         if ( (ret = smbrun(command, NULL)) == 0 ) {
294                 /* Tell everyone we updated smb.conf. */
295                 message_send_all(smbd_messaging_context(),
296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
297         }
298
299         if ( is_print_op )
300                 unbecome_root();
301
302         /********** END SePrintOperatorPrivlege BLOCK **********/
303
304         DEBUGADD(10,("returned [%d]\n", ret));
305
306         TALLOC_FREE(command);
307
308         if (ret != 0)
309                 return WERR_BADFID; /* What to return here? */
310
311         /* go ahead and re-read the services immediately */
312         become_root();
313         reload_services(false);
314         unbecome_root();
315
316         if ( lp_servicenumber( sharename )  < 0 )
317                 return WERR_ACCESS_DENIED;
318
319         return WERR_OK;
320 }
321
322 /****************************************************************************
323  Delete a printer given a handle.
324 ****************************************************************************/
325
326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
327 {
328         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
329
330         if (!Printer) {
331                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
332                         OUR_HANDLE(hnd)));
333                 return WERR_BADFID;
334         }
335
336         /*
337          * It turns out that Windows allows delete printer on a handle
338          * opened by an admin user, then used on a pipe handle created
339          * by an anonymous user..... but they're working on security.... riiight !
340          * JRA.
341          */
342
343         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345                 return WERR_ACCESS_DENIED;
346         }
347
348         /* this does not need a become root since the access check has been
349            done on the handle already */
350
351         if (del_a_printer( Printer->sharename ) != 0) {
352                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
353                 return WERR_BADFID;
354         }
355
356         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357                                    Printer->sharename );
358 }
359
360 /****************************************************************************
361  Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
363
364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
365                              int *number, struct share_params **params)
366 {
367         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
368
369         if (!Printer) {
370                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
371                         OUR_HANDLE(hnd)));
372                 return false;
373         }
374
375         switch (Printer->printer_type) {
376                 case SPLHND_PRINTER:
377                         DEBUG(4,("short name:%s\n", Printer->sharename));
378                         *number = print_queue_snum(Printer->sharename);
379                         return (*number != -1);
380                 case SPLHND_SERVER:
381                         return false;
382                 default:
383                         return false;
384         }
385 }
386
387 /****************************************************************************
388  Set printer handle type.
389  Check if it's \\server or \\server\printer
390 ****************************************************************************/
391
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
393 {
394         DEBUG(3,("Setting printer type=%s\n", handlename));
395
396         if ( strlen(handlename) < 3 ) {
397                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
398                 return false;
399         }
400
401         /* it's a print server */
402         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403                 DEBUGADD(4,("Printer is a print server\n"));
404                 Printer->printer_type = SPLHND_SERVER;
405         }
406         /* it's a printer (set_printer_hnd_name() will handle port monitors */
407         else {
408                 DEBUGADD(4,("Printer is a printer\n"));
409                 Printer->printer_type = SPLHND_PRINTER;
410         }
411
412         return true;
413 }
414
415 /****************************************************************************
416  Set printer handle name..  Accept names like \\server, \\server\printer,
417  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
418  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419  XcvDataPort() interface.
420 ****************************************************************************/
421
422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
423 {
424         int snum;
425         int n_services=lp_numservices();
426         char *aprinter, *printername;
427         const char *servername;
428         fstring sname;
429         bool found = false;
430         NT_PRINTER_INFO_LEVEL *printer = NULL;
431         WERROR result;
432
433         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
434                 (unsigned long)strlen(handlename)));
435
436         aprinter = CONST_DISCARD(char *, handlename);
437         if ( *handlename == '\\' ) {
438                 servername = canon_servername(handlename);
439                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
440                         *aprinter = '\0';
441                         aprinter++;
442                 }
443         } else {
444                 servername = global_myname();
445         }
446
447         /* save the servername to fill in replies on this handle */
448
449         if ( !is_myname_or_ipaddr( servername ) )
450                 return false;
451
452         fstrcpy( Printer->servername, servername );
453
454         if ( Printer->printer_type == SPLHND_SERVER )
455                 return true;
456
457         if ( Printer->printer_type != SPLHND_PRINTER )
458                 return false;
459
460         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
461
462         /* check for the Port Monitor Interface */
463
464         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
465                 Printer->printer_type = SPLHND_PORTMON_TCP;
466                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
467                 found = true;
468         }
469         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
470                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
471                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
472                 found = true;
473         }
474
475         /* Search all sharenames first as this is easier than pulling
476            the printer_info_2 off of disk. Don't use find_service() since
477            that calls out to map_username() */
478
479         /* do another loop to look for printernames */
480
481         for (snum=0; !found && snum<n_services; snum++) {
482
483                 /* no point going on if this is not a printer */
484
485                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
486                         continue;
487
488                 fstrcpy(sname, lp_servicename(snum));
489                 if ( strequal( aprinter, sname ) ) {
490                         found = true;
491                         break;
492                 }
493
494                 /* no point looking up the printer object if
495                    we aren't allowing printername != sharename */
496
497                 if ( lp_force_printername(snum) )
498                         continue;
499
500                 fstrcpy(sname, lp_servicename(snum));
501
502                 printer = NULL;
503
504                 /* This call doesn't fill in the location or comment from
505                  * a CUPS server for efficiency with large numbers of printers.
506                  * JRA.
507                  */
508
509                 result = get_a_printer_search( NULL, &printer, 2, sname );
510                 if ( !W_ERROR_IS_OK(result) ) {
511                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512                                 sname, win_errstr(result)));
513                         continue;
514                 }
515
516                 /* printername is always returned as \\server\printername */
517                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519                                 printer->info_2->printername));
520                         free_a_printer( &printer, 2);
521                         continue;
522                 }
523
524                 printername++;
525
526                 if ( strequal(printername, aprinter) ) {
527                         free_a_printer( &printer, 2);
528                         found = true;
529                         break;
530                 }
531
532                 DEBUGADD(10, ("printername: %s\n", printername));
533
534                 free_a_printer( &printer, 2);
535         }
536
537         free_a_printer( &printer, 2);
538
539         if ( !found ) {
540                 DEBUGADD(4,("Printer not found\n"));
541                 return false;
542         }
543
544         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
545
546         fstrcpy(Printer->sharename, sname);
547
548         return true;
549 }
550
551 /****************************************************************************
552  Find first available printer slot. creates a printer handle for you.
553  ****************************************************************************/
554
555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
556                              const char *name, uint32_t access_granted)
557 {
558         Printer_entry *new_printer;
559
560         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
561
562         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
563         if (new_printer == NULL) {
564                 return false;
565         }
566         talloc_set_destructor(new_printer, printer_entry_destructor);
567
568         if (!create_policy_hnd(p, hnd, new_printer)) {
569                 TALLOC_FREE(new_printer);
570                 return false;
571         }
572
573         /* Add to the internal list. */
574         DLIST_ADD(printers_list, new_printer);
575
576         new_printer->notify.option=NULL;
577
578         if (!set_printer_hnd_printertype(new_printer, name)) {
579                 close_printer_handle(p, hnd);
580                 return false;
581         }
582
583         if (!set_printer_hnd_name(new_printer, name)) {
584                 close_printer_handle(p, hnd);
585                 return false;
586         }
587
588         new_printer->access_granted = access_granted;
589
590         DEBUG(5, ("%d printer handles active\n",
591                   (int)num_pipe_handles(p->pipe_handles)));
592
593         return true;
594 }
595
596 /***************************************************************************
597  check to see if the client motify handle is monitoring the notification
598  given by (notify_type, notify_field).
599  **************************************************************************/
600
601 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
602                                       uint16_t notify_field)
603 {
604         return true;
605 }
606
607 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
608                                 uint16_t notify_field)
609 {
610         struct spoolss_NotifyOption *option = p->notify.option;
611         uint32_t i, j;
612
613         /*
614          * Flags should always be zero when the change notify
615          * is registered by the client's spooler.  A user Win32 app
616          * might use the flags though instead of the NOTIFY_OPTION_INFO
617          * --jerry
618          */
619
620         if (!option) {
621                 return false;
622         }
623
624         if (p->notify.flags)
625                 return is_monitoring_event_flags(
626                         p->notify.flags, notify_type, notify_field);
627
628         for (i = 0; i < option->count; i++) {
629
630                 /* Check match for notify_type */
631
632                 if (option->types[i].type != notify_type)
633                         continue;
634
635                 /* Check match for field */
636
637                 for (j = 0; j < option->types[i].count; j++) {
638                         if (option->types[i].fields[j].field == notify_field) {
639                                 return true;
640                         }
641                 }
642         }
643
644         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
645                    p->servername, p->sharename, notify_type, notify_field));
646
647         return false;
648 }
649
650 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
651         _data->data.integer[0] = _integer; \
652         _data->data.integer[1] = 0;
653
654
655 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
656         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
657         if (!_data->data.string.string) {\
658                 _data->data.string.size = 0; \
659         } \
660         _data->data.string.size = strlen_m_term(_p) * 2;
661
662 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
663         _data->data.devmode.devmode = _devmode;
664
665 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
666         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
667         if (!_data->data.sd.sd) { \
668                 _data->data.sd.sd_size = 0; \
669         } \
670         _data->data.sd.sd_size = _size;
671
672 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
673                                    struct tm *t,
674                                    const char **pp,
675                                    uint32_t *plen)
676 {
677         struct spoolss_Time st;
678         uint32_t len = 16;
679         char *p;
680
681         if (!init_systemtime(&st, t)) {
682                 return;
683         }
684
685         p = talloc_array(mem_ctx, char, len);
686         if (!p) {
687                 return;
688         }
689
690         /*
691          * Systemtime must be linearized as a set of UINT16's.
692          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
693          */
694
695         SSVAL(p, 0, st.year);
696         SSVAL(p, 2, st.month);
697         SSVAL(p, 4, st.day_of_week);
698         SSVAL(p, 6, st.day);
699         SSVAL(p, 8, st.hour);
700         SSVAL(p, 10, st.minute);
701         SSVAL(p, 12, st.second);
702         SSVAL(p, 14, st.millisecond);
703
704         *pp = p;
705         *plen = len;
706 }
707
708 /* Convert a notification message to a struct spoolss_Notify */
709
710 static void notify_one_value(struct spoolss_notify_msg *msg,
711                              struct spoolss_Notify *data,
712                              TALLOC_CTX *mem_ctx)
713 {
714         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
715 }
716
717 static void notify_string(struct spoolss_notify_msg *msg,
718                           struct spoolss_Notify *data,
719                           TALLOC_CTX *mem_ctx)
720 {
721         /* The length of the message includes the trailing \0 */
722
723         data->data.string.size = msg->len * 2;
724         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
725         if (!data->data.string.string) {
726                 data->data.string.size = 0;
727                 return;
728         }
729 }
730
731 static void notify_system_time(struct spoolss_notify_msg *msg,
732                                struct spoolss_Notify *data,
733                                TALLOC_CTX *mem_ctx)
734 {
735         data->data.string.string = NULL;
736         data->data.string.size = 0;
737
738         if (msg->len != sizeof(time_t)) {
739                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
740                           msg->len));
741                 return;
742         }
743
744         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
745                                &data->data.string.string,
746                                &data->data.string.size);
747 }
748
749 struct notify2_message_table {
750         const char *name;
751         void (*fn)(struct spoolss_notify_msg *msg,
752                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
753 };
754
755 static struct notify2_message_table printer_notify_table[] = {
756         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
757         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
758         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
759         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
760         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
761         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
762         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
763         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
764         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
765         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
766         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
767         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
768         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
769         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
770         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
771         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
772         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
773         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
774         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
775 };
776
777 static struct notify2_message_table job_notify_table[] = {
778         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
779         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
780         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
781         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
782         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
783         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
784         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
785         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
786         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
787         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
788         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
789         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
790         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
791         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
792         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
793         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
794         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
795         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
796         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
797         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
798         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
799         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
800         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
801         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
802 };
803
804
805 /***********************************************************************
806  Allocate talloc context for container object
807  **********************************************************************/
808
809 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
810 {
811         if ( !ctr )
812                 return;
813
814         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
815
816         return;
817 }
818
819 /***********************************************************************
820  release all allocated memory and zero out structure
821  **********************************************************************/
822
823 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
824 {
825         if ( !ctr )
826                 return;
827
828         if ( ctr->ctx )
829                 talloc_destroy(ctr->ctx);
830
831         ZERO_STRUCTP(ctr);
832
833         return;
834 }
835
836 /***********************************************************************
837  **********************************************************************/
838
839 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
840 {
841         if ( !ctr )
842                 return NULL;
843
844         return ctr->ctx;
845 }
846
847 /***********************************************************************
848  **********************************************************************/
849
850 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
851 {
852         if ( !ctr || !ctr->msg_groups )
853                 return NULL;
854
855         if ( idx >= ctr->num_groups )
856                 return NULL;
857
858         return &ctr->msg_groups[idx];
859
860 }
861
862 /***********************************************************************
863  How many groups of change messages do we have ?
864  **********************************************************************/
865
866 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
867 {
868         if ( !ctr )
869                 return 0;
870
871         return ctr->num_groups;
872 }
873
874 /***********************************************************************
875  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
876  **********************************************************************/
877
878 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
879 {
880         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
881         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
882         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
883         int                             i, new_slot;
884
885         if ( !ctr || !msg )
886                 return 0;
887
888         /* loop over all groups looking for a matching printer name */
889
890         for ( i=0; i<ctr->num_groups; i++ ) {
891                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
892                         break;
893         }
894
895         /* add a new group? */
896
897         if ( i == ctr->num_groups ) {
898                 ctr->num_groups++;
899
900                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
901                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
902                         return 0;
903                 }
904                 ctr->msg_groups = groups;
905
906                 /* clear the new entry and set the printer name */
907
908                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
909                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
910         }
911
912         /* add the change messages; 'i' is the correct index now regardless */
913
914         msg_grp = &ctr->msg_groups[i];
915
916         msg_grp->num_msgs++;
917
918         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
919                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
920                 return 0;
921         }
922         msg_grp->msgs = msg_list;
923
924         new_slot = msg_grp->num_msgs-1;
925         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
926
927         /* need to allocate own copy of data */
928
929         if ( msg->len != 0 )
930                 msg_grp->msgs[new_slot].notify.data = (char *)
931                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
932
933         return ctr->num_groups;
934 }
935
936 /***********************************************************************
937  Send a change notication message on all handles which have a call
938  back registered
939  **********************************************************************/
940
941 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
942 {
943         Printer_entry            *p;
944         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
945         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
946         SPOOLSS_NOTIFY_MSG       *messages;
947         int                      sending_msg_count;
948
949         if ( !msg_group ) {
950                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
951                 return;
952         }
953
954         messages = msg_group->msgs;
955
956         if ( !messages ) {
957                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
958                 return;
959         }
960
961         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
962
963         /* loop over all printers */
964
965         for (p = printers_list; p; p = p->next) {
966                 struct spoolss_Notify *notifies;
967                 uint32_t count = 0;
968                 uint32_t id;
969                 int     i;
970
971                 /* Is there notification on this handle? */
972
973                 if ( !p->notify.client_connected )
974                         continue;
975
976                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
977
978                 /* For this printer?  Print servers always receive
979                    notifications. */
980
981                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
982                     ( !strequal(msg_group->printername, p->sharename) ) )
983                         continue;
984
985                 DEBUG(10,("Our printer\n"));
986
987                 /* allocate the max entries possible */
988
989                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
990                 if (!notifies) {
991                         return;
992                 }
993
994                 /* build the array of change notifications */
995
996                 sending_msg_count = 0;
997
998                 for ( i=0; i<msg_group->num_msgs; i++ ) {
999                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1000
1001                         /* Are we monitoring this event? */
1002
1003                         if (!is_monitoring_event(p, msg->type, msg->field))
1004                                 continue;
1005
1006                         sending_msg_count++;
1007
1008
1009                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1010                                 msg->type, msg->field, p->sharename));
1011
1012                         /*
1013                          * if the is a printer notification handle and not a job notification
1014                          * type, then set the id to 0.  Other wise just use what was specified
1015                          * in the message.
1016                          *
1017                          * When registering change notification on a print server handle
1018                          * we always need to send back the id (snum) matching the printer
1019                          * for which the change took place.  For change notify registered
1020                          * on a printer handle, this does not matter and the id should be 0.
1021                          *
1022                          * --jerry
1023                          */
1024
1025                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1026                                 id = 0;
1027                         else
1028                                 id = msg->id;
1029
1030
1031                         /* Convert unix jobid to smb jobid */
1032
1033                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1034                                 id = sysjob_to_jobid(msg->id);
1035
1036                                 if (id == -1) {
1037                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1038                                         goto done;
1039                                 }
1040                         }
1041
1042                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1043
1044                         switch(msg->type) {
1045                         case PRINTER_NOTIFY_TYPE:
1046                                 if ( printer_notify_table[msg->field].fn )
1047                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1048                                 break;
1049
1050                         case JOB_NOTIFY_TYPE:
1051                                 if ( job_notify_table[msg->field].fn )
1052                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1053                                 break;
1054
1055                         default:
1056                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1057                                 goto done;
1058                         }
1059
1060                         count++;
1061                 }
1062
1063                 if ( sending_msg_count ) {
1064                         NTSTATUS status;
1065                         WERROR werr;
1066                         union spoolss_ReplyPrinterInfo info;
1067                         struct spoolss_NotifyInfo info0;
1068                         uint32_t reply_result;
1069
1070                         info0.version   = 0x2;
1071                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1072                         info0.count     = count;
1073                         info0.notifies  = notifies;
1074
1075                         info.info0 = &info0;
1076
1077                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1078                                                                      &p->notify.client_hnd,
1079                                                                      p->notify.change, /* color */
1080                                                                      p->notify.flags,
1081                                                                      &reply_result,
1082                                                                      0, /* reply_type, must be 0 */
1083                                                                      info,
1084                                                                      &werr);
1085                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1086                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1087                                         notify_cli_pipe->srv_name_slash,
1088                                         win_errstr(werr)));
1089                         }
1090                         switch (reply_result) {
1091                                 case 0:
1092                                         break;
1093                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1094                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1095                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1096                                         break;
1097                                 default:
1098                                         break;
1099                         }
1100                 }
1101         }
1102
1103 done:
1104         DEBUG(8,("send_notify2_changes: Exit...\n"));
1105         return;
1106 }
1107
1108 /***********************************************************************
1109  **********************************************************************/
1110
1111 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1112 {
1113
1114         uint32_t tv_sec, tv_usec;
1115         size_t offset = 0;
1116
1117         /* Unpack message */
1118
1119         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1120                              msg->printer);
1121
1122         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1123                                 &tv_sec, &tv_usec,
1124                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1125
1126         if (msg->len == 0)
1127                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1128                            &msg->notify.value[0], &msg->notify.value[1]);
1129         else
1130                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1131                            &msg->len, &msg->notify.data);
1132
1133         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1134                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1135
1136         tv->tv_sec = tv_sec;
1137         tv->tv_usec = tv_usec;
1138
1139         if (msg->len == 0)
1140                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1141                           msg->notify.value[1]));
1142         else
1143                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1144
1145         return true;
1146 }
1147
1148 /********************************************************************
1149  Receive a notify2 message list
1150  ********************************************************************/
1151
1152 static void receive_notify2_message_list(struct messaging_context *msg,
1153                                          void *private_data,
1154                                          uint32_t msg_type,
1155                                          struct server_id server_id,
1156                                          DATA_BLOB *data)
1157 {
1158         size_t                  msg_count, i;
1159         char                    *buf = (char *)data->data;
1160         char                    *msg_ptr;
1161         size_t                  msg_len;
1162         SPOOLSS_NOTIFY_MSG      notify;
1163         SPOOLSS_NOTIFY_MSG_CTR  messages;
1164         int                     num_groups;
1165
1166         if (data->length < 4) {
1167                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1168                 return;
1169         }
1170
1171         msg_count = IVAL(buf, 0);
1172         msg_ptr = buf + 4;
1173
1174         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1175
1176         if (msg_count == 0) {
1177                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1178                 return;
1179         }
1180
1181         /* initialize the container */
1182
1183         ZERO_STRUCT( messages );
1184         notify_msg_ctr_init( &messages );
1185
1186         /*
1187          * build message groups for each printer identified
1188          * in a change_notify msg.  Remember that a PCN message
1189          * includes the handle returned for the srv_spoolss_replyopenprinter()
1190          * call.  Therefore messages are grouped according to printer handle.
1191          */
1192
1193         for ( i=0; i<msg_count; i++ ) {
1194                 struct timeval msg_tv;
1195
1196                 if (msg_ptr + 4 - buf > data->length) {
1197                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1198                         return;
1199                 }
1200
1201                 msg_len = IVAL(msg_ptr,0);
1202                 msg_ptr += 4;
1203
1204                 if (msg_ptr + msg_len - buf > data->length) {
1205                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1206                         return;
1207                 }
1208
1209                 /* unpack messages */
1210
1211                 ZERO_STRUCT( notify );
1212                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1213                 msg_ptr += msg_len;
1214
1215                 /* add to correct list in container */
1216
1217                 notify_msg_ctr_addmsg( &messages, &notify );
1218
1219                 /* free memory that might have been allocated by notify2_unpack_msg() */
1220
1221                 if ( notify.len != 0 )
1222                         SAFE_FREE( notify.notify.data );
1223         }
1224
1225         /* process each group of messages */
1226
1227         num_groups = notify_msg_ctr_numgroups( &messages );
1228         for ( i=0; i<num_groups; i++ )
1229                 send_notify2_changes( &messages, i );
1230
1231
1232         /* cleanup */
1233
1234         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1235                 (uint32_t)msg_count ));
1236
1237         notify_msg_ctr_destroy( &messages );
1238
1239         return;
1240 }
1241
1242 /********************************************************************
1243  Send a message to ourself about new driver being installed
1244  so we can upgrade the information for each printer bound to this
1245  driver
1246  ********************************************************************/
1247
1248 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1249 {
1250         int len = strlen(drivername);
1251
1252         if (!len)
1253                 return false;
1254
1255         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1256                 drivername));
1257
1258         messaging_send_buf(smbd_messaging_context(), procid_self(),
1259                            MSG_PRINTER_DRVUPGRADE,
1260                            (uint8_t *)drivername, len+1);
1261
1262         return true;
1263 }
1264
1265 /**********************************************************************
1266  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1267  over all printers, upgrading ones as necessary
1268  **********************************************************************/
1269
1270 void do_drv_upgrade_printer(struct messaging_context *msg,
1271                             void *private_data,
1272                             uint32_t msg_type,
1273                             struct server_id server_id,
1274                             DATA_BLOB *data)
1275 {
1276         fstring drivername;
1277         int snum;
1278         int n_services = lp_numservices();
1279         size_t len;
1280
1281         len = MIN(data->length,sizeof(drivername)-1);
1282         strncpy(drivername, (const char *)data->data, len);
1283
1284         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1285
1286         /* Iterate the printer list */
1287
1288         for (snum=0; snum<n_services; snum++)
1289         {
1290                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1291                 {
1292                         WERROR result;
1293                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1294
1295                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1296                         if (!W_ERROR_IS_OK(result))
1297                                 continue;
1298
1299                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1300                         {
1301                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1302
1303                                 /* all we care about currently is the change_id */
1304
1305                                 result = mod_a_printer(printer, 2);
1306                                 if (!W_ERROR_IS_OK(result)) {
1307                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1308                                                 win_errstr(result)));
1309                                 }
1310                         }
1311
1312                         free_a_printer(&printer, 2);
1313                 }
1314         }
1315
1316         /* all done */
1317 }
1318
1319 /********************************************************************
1320  Update the cache for all printq's with a registered client
1321  connection
1322  ********************************************************************/
1323
1324 void update_monitored_printq_cache( void )
1325 {
1326         Printer_entry *printer = printers_list;
1327         int snum;
1328
1329         /* loop through all printers and update the cache where
1330            client_connected == true */
1331         while ( printer )
1332         {
1333                 if ( (printer->printer_type == SPLHND_PRINTER)
1334                         && printer->notify.client_connected )
1335                 {
1336                         snum = print_queue_snum(printer->sharename);
1337                         print_queue_status( snum, NULL, NULL );
1338                 }
1339
1340                 printer = printer->next;
1341         }
1342
1343         return;
1344 }
1345 /********************************************************************
1346  Send a message to ourself about new driver being installed
1347  so we can upgrade the information for each printer bound to this
1348  driver
1349  ********************************************************************/
1350
1351 static bool srv_spoolss_reset_printerdata(char* drivername)
1352 {
1353         int len = strlen(drivername);
1354
1355         if (!len)
1356                 return false;
1357
1358         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1359                 drivername));
1360
1361         messaging_send_buf(smbd_messaging_context(), procid_self(),
1362                            MSG_PRINTERDATA_INIT_RESET,
1363                            (uint8_t *)drivername, len+1);
1364
1365         return true;
1366 }
1367
1368 /**********************************************************************
1369  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1370  over all printers, resetting printer data as neessary
1371  **********************************************************************/
1372
1373 void reset_all_printerdata(struct messaging_context *msg,
1374                            void *private_data,
1375                            uint32_t msg_type,
1376                            struct server_id server_id,
1377                            DATA_BLOB *data)
1378 {
1379         fstring drivername;
1380         int snum;
1381         int n_services = lp_numservices();
1382         size_t len;
1383
1384         len = MIN( data->length, sizeof(drivername)-1 );
1385         strncpy( drivername, (const char *)data->data, len );
1386
1387         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1388
1389         /* Iterate the printer list */
1390
1391         for ( snum=0; snum<n_services; snum++ )
1392         {
1393                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1394                 {
1395                         WERROR result;
1396                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1397
1398                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1399                         if ( !W_ERROR_IS_OK(result) )
1400                                 continue;
1401
1402                         /*
1403                          * if the printer is bound to the driver,
1404                          * then reset to the new driver initdata
1405                          */
1406
1407                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1408                         {
1409                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1410
1411                                 if ( !set_driver_init(printer, 2) ) {
1412                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1413                                                 printer->info_2->printername, printer->info_2->drivername));
1414                                 }
1415
1416                                 result = mod_a_printer( printer, 2 );
1417                                 if ( !W_ERROR_IS_OK(result) ) {
1418                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1419                                                 get_dos_error_msg(result)));
1420                                 }
1421                         }
1422
1423                         free_a_printer( &printer, 2 );
1424                 }
1425         }
1426
1427         /* all done */
1428
1429         return;
1430 }
1431
1432 /****************************************************************
1433  _spoolss_OpenPrinter
1434 ****************************************************************/
1435
1436 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1437                             struct spoolss_OpenPrinter *r)
1438 {
1439         struct spoolss_OpenPrinterEx e;
1440         WERROR werr;
1441
1442         ZERO_STRUCT(e.in.userlevel);
1443
1444         e.in.printername        = r->in.printername;
1445         e.in.datatype           = r->in.datatype;
1446         e.in.devmode_ctr        = r->in.devmode_ctr;
1447         e.in.access_mask        = r->in.access_mask;
1448         e.in.level              = 0;
1449
1450         e.out.handle            = r->out.handle;
1451
1452         werr = _spoolss_OpenPrinterEx(p, &e);
1453
1454         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1455                 /* OpenPrinterEx returns this for a bad
1456                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1457                  * instead.
1458                  */
1459                 werr = WERR_INVALID_PRINTER_NAME;
1460         }
1461
1462         return werr;
1463 }
1464
1465 /********************************************************************
1466  ********************************************************************/
1467
1468 bool convert_devicemode(const char *printername,
1469                         const struct spoolss_DeviceMode *devmode,
1470                         NT_DEVICEMODE **pp_nt_devmode)
1471 {
1472         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1473
1474         /*
1475          * Ensure nt_devmode is a valid pointer
1476          * as we will be overwriting it.
1477          */
1478
1479         if (nt_devmode == NULL) {
1480                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1481                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1482                         return false;
1483         }
1484
1485         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1486         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1487
1488         nt_devmode->specversion         = devmode->specversion;
1489         nt_devmode->driverversion       = devmode->driverversion;
1490         nt_devmode->size                = devmode->size;
1491         nt_devmode->fields              = devmode->fields;
1492         nt_devmode->orientation         = devmode->orientation;
1493         nt_devmode->papersize           = devmode->papersize;
1494         nt_devmode->paperlength         = devmode->paperlength;
1495         nt_devmode->paperwidth          = devmode->paperwidth;
1496         nt_devmode->scale               = devmode->scale;
1497         nt_devmode->copies              = devmode->copies;
1498         nt_devmode->defaultsource       = devmode->defaultsource;
1499         nt_devmode->printquality        = devmode->printquality;
1500         nt_devmode->color               = devmode->color;
1501         nt_devmode->duplex              = devmode->duplex;
1502         nt_devmode->yresolution         = devmode->yresolution;
1503         nt_devmode->ttoption            = devmode->ttoption;
1504         nt_devmode->collate             = devmode->collate;
1505
1506         nt_devmode->logpixels           = devmode->logpixels;
1507         nt_devmode->bitsperpel          = devmode->bitsperpel;
1508         nt_devmode->pelswidth           = devmode->pelswidth;
1509         nt_devmode->pelsheight          = devmode->pelsheight;
1510         nt_devmode->displayflags        = devmode->displayflags;
1511         nt_devmode->displayfrequency    = devmode->displayfrequency;
1512         nt_devmode->icmmethod           = devmode->icmmethod;
1513         nt_devmode->icmintent           = devmode->icmintent;
1514         nt_devmode->mediatype           = devmode->mediatype;
1515         nt_devmode->dithertype          = devmode->dithertype;
1516         nt_devmode->reserved1           = devmode->reserved1;
1517         nt_devmode->reserved2           = devmode->reserved2;
1518         nt_devmode->panningwidth        = devmode->panningwidth;
1519         nt_devmode->panningheight       = devmode->panningheight;
1520
1521         /*
1522          * Only change private and driverextra if the incoming devmode
1523          * has a new one. JRA.
1524          */
1525
1526         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1527                 SAFE_FREE(nt_devmode->nt_dev_private);
1528                 nt_devmode->driverextra = devmode->__driverextra_length;
1529                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1530                         return false;
1531                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1532         }
1533
1534         *pp_nt_devmode = nt_devmode;
1535
1536         return true;
1537 }
1538
1539 /****************************************************************
1540  _spoolss_OpenPrinterEx
1541 ****************************************************************/
1542
1543 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1544                               struct spoolss_OpenPrinterEx *r)
1545 {
1546         int snum;
1547         Printer_entry *Printer=NULL;
1548
1549         if (!r->in.printername) {
1550                 return WERR_INVALID_PARAM;
1551         }
1552
1553         /* some sanity check because you can open a printer or a print server */
1554         /* aka: \\server\printer or \\server */
1555
1556         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1557
1558         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1559                 ZERO_STRUCTP(r->out.handle);
1560                 return WERR_INVALID_PARAM;
1561         }
1562
1563         Printer = find_printer_index_by_hnd(p, r->out.handle);
1564         if ( !Printer ) {
1565                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1566                         "handle we created for printer %s\n", r->in.printername));
1567                 close_printer_handle(p, r->out.handle);
1568                 ZERO_STRUCTP(r->out.handle);
1569                 return WERR_INVALID_PARAM;
1570         }
1571
1572         /*
1573          * First case: the user is opening the print server:
1574          *
1575          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1576          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1577          *
1578          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1579          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1580          * or if the user is listed in the smb.conf printer admin parameter.
1581          *
1582          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1583          * client view printer folder, but does not show the MSAPW.
1584          *
1585          * Note: this test needs code to check access rights here too. Jeremy
1586          * could you look at this?
1587          *
1588          * Second case: the user is opening a printer:
1589          * NT doesn't let us connect to a printer if the connecting user
1590          * doesn't have print permission.
1591          *
1592          * Third case: user is opening a Port Monitor
1593          * access checks same as opening a handle to the print server.
1594          */
1595
1596         switch (Printer->printer_type )
1597         {
1598         case SPLHND_SERVER:
1599         case SPLHND_PORTMON_TCP:
1600         case SPLHND_PORTMON_LOCAL:
1601                 /* Printserver handles use global struct... */
1602
1603                 snum = -1;
1604
1605                 /* Map standard access rights to object specific access rights */
1606
1607                 se_map_standard(&r->in.access_mask,
1608                                 &printserver_std_mapping);
1609
1610                 /* Deny any object specific bits that don't apply to print
1611                    servers (i.e printer and job specific bits) */
1612
1613                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1614
1615                 if (r->in.access_mask &
1616                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1617                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1618                         close_printer_handle(p, r->out.handle);
1619                         ZERO_STRUCTP(r->out.handle);
1620                         return WERR_ACCESS_DENIED;
1621                 }
1622
1623                 /* Allow admin access */
1624
1625                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1626                 {
1627                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1628
1629                         if (!lp_ms_add_printer_wizard()) {
1630                                 close_printer_handle(p, r->out.handle);
1631                                 ZERO_STRUCTP(r->out.handle);
1632                                 return WERR_ACCESS_DENIED;
1633                         }
1634
1635                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1636                            and not a printer admin, then fail */
1637
1638                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1639                             !user_has_privileges(p->server_info->ptok,
1640                                                  &se_printop ) &&
1641                             !token_contains_name_in_list(
1642                                     uidtoname(p->server_info->utok.uid),
1643                                     NULL, NULL,
1644                                     p->server_info->ptok,
1645                                     lp_printer_admin(snum))) {
1646                                 close_printer_handle(p, r->out.handle);
1647                                 ZERO_STRUCTP(r->out.handle);
1648                                 return WERR_ACCESS_DENIED;
1649                         }
1650
1651                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1652                 }
1653                 else
1654                 {
1655                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1656                 }
1657
1658                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1659                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1660
1661                 /* We fall through to return WERR_OK */
1662                 break;
1663
1664         case SPLHND_PRINTER:
1665                 /* NT doesn't let us connect to a printer if the connecting user
1666                    doesn't have print permission.  */
1667
1668                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1669                         close_printer_handle(p, r->out.handle);
1670                         ZERO_STRUCTP(r->out.handle);
1671                         return WERR_BADFID;
1672                 }
1673
1674                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1675
1676                 /* map an empty access mask to the minimum access mask */
1677                 if (r->in.access_mask == 0x0)
1678                         r->in.access_mask = PRINTER_ACCESS_USE;
1679
1680                 /*
1681                  * If we are not serving the printer driver for this printer,
1682                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1683                  * will keep NT clients happy  --jerry
1684                  */
1685
1686                 if (lp_use_client_driver(snum)
1687                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1688                 {
1689                         r->in.access_mask = PRINTER_ACCESS_USE;
1690                 }
1691
1692                 /* check smb.conf parameters and the the sec_desc */
1693
1694                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1695                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1696                         ZERO_STRUCTP(r->out.handle);
1697                         return WERR_ACCESS_DENIED;
1698                 }
1699
1700                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1701                                    p->server_info->ptok, snum) ||
1702                     !print_access_check(p->server_info, snum,
1703                                         r->in.access_mask)) {
1704                         DEBUG(3, ("access DENIED for printer open\n"));
1705                         close_printer_handle(p, r->out.handle);
1706                         ZERO_STRUCTP(r->out.handle);
1707                         return WERR_ACCESS_DENIED;
1708                 }
1709
1710                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1711                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1712                         close_printer_handle(p, r->out.handle);
1713                         ZERO_STRUCTP(r->out.handle);
1714                         return WERR_ACCESS_DENIED;
1715                 }
1716
1717                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1718                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1719                 else
1720                         r->in.access_mask = PRINTER_ACCESS_USE;
1721
1722                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1723                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1724
1725                 break;
1726
1727         default:
1728                 /* sanity check to prevent programmer error */
1729                 ZERO_STRUCTP(r->out.handle);
1730                 return WERR_BADFID;
1731         }
1732
1733         Printer->access_granted = r->in.access_mask;
1734
1735         /*
1736          * If the client sent a devmode in the OpenPrinter() call, then
1737          * save it here in case we get a job submission on this handle
1738          */
1739
1740          if ((Printer->printer_type != SPLHND_SERVER) &&
1741              r->in.devmode_ctr.devmode) {
1742                 convert_devicemode(Printer->sharename,
1743                                    r->in.devmode_ctr.devmode,
1744                                    &Printer->nt_devmode);
1745          }
1746
1747 #if 0   /* JERRY -- I'm doubtful this is really effective */
1748         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1749            optimization in Windows 2000 clients  --jerry */
1750
1751         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1752                 && (RA_WIN2K == get_remote_arch()) )
1753         {
1754                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1755                 sys_usleep( 500000 );
1756         }
1757 #endif
1758
1759         return WERR_OK;
1760 }
1761
1762 /****************************************************************************
1763 ****************************************************************************/
1764
1765 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1766                                               NT_PRINTER_INFO_LEVEL_2 *d)
1767 {
1768         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1769
1770         if (!r || !d) {
1771                 return false;
1772         }
1773
1774         d->attributes           = r->attributes;
1775         d->priority             = r->priority;
1776         d->default_priority     = r->defaultpriority;
1777         d->starttime            = r->starttime;
1778         d->untiltime            = r->untiltime;
1779         d->status               = r->status;
1780         d->cjobs                = r->cjobs;
1781
1782         fstrcpy(d->servername,  r->servername);
1783         fstrcpy(d->printername, r->printername);
1784         fstrcpy(d->sharename,   r->sharename);
1785         fstrcpy(d->portname,    r->portname);
1786         fstrcpy(d->drivername,  r->drivername);
1787         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1788         fstrcpy(d->location,    r->location);
1789         fstrcpy(d->sepfile,     r->sepfile);
1790         fstrcpy(d->printprocessor, r->printprocessor);
1791         fstrcpy(d->datatype,    r->datatype);
1792         fstrcpy(d->parameters,  r->parameters);
1793
1794         return true;
1795 }
1796
1797 /****************************************************************************
1798 ****************************************************************************/
1799
1800 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1801                                  NT_PRINTER_INFO_LEVEL *printer)
1802 {
1803         bool ret;
1804
1805         switch (info_ctr->level) {
1806         case 2:
1807                 /* allocate memory if needed.  Messy because
1808                    convert_printer_info is used to update an existing
1809                    printer or build a new one */
1810
1811                 if (!printer->info_2) {
1812                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1813                         if (!printer->info_2) {
1814                                 DEBUG(0,("convert_printer_info: "
1815                                         "talloc() failed!\n"));
1816                                 return false;
1817                         }
1818                 }
1819
1820                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1821                                                         printer->info_2);
1822                 printer->info_2->setuptime = time(NULL);
1823                 return ret;
1824         }
1825
1826         return false;
1827 }
1828
1829 /****************************************************************
1830  _spoolss_ClosePrinter
1831 ****************************************************************/
1832
1833 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1834                              struct spoolss_ClosePrinter *r)
1835 {
1836         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1837
1838         if (Printer && Printer->document_started) {
1839                 struct spoolss_EndDocPrinter e;
1840
1841                 e.in.handle = r->in.handle;
1842
1843                 _spoolss_EndDocPrinter(p, &e);
1844         }
1845
1846         if (!close_printer_handle(p, r->in.handle))
1847                 return WERR_BADFID;
1848
1849         /* clear the returned printer handle.  Observed behavior
1850            from Win2k server.  Don't think this really matters.
1851            Previous code just copied the value of the closed
1852            handle.    --jerry */
1853
1854         ZERO_STRUCTP(r->out.handle);
1855
1856         return WERR_OK;
1857 }
1858
1859 /****************************************************************
1860  _spoolss_DeletePrinter
1861 ****************************************************************/
1862
1863 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1864                               struct spoolss_DeletePrinter *r)
1865 {
1866         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1867         WERROR result;
1868
1869         if (Printer && Printer->document_started) {
1870                 struct spoolss_EndDocPrinter e;
1871
1872                 e.in.handle = r->in.handle;
1873
1874                 _spoolss_EndDocPrinter(p, &e);
1875         }
1876
1877         result = delete_printer_handle(p, r->in.handle);
1878
1879         update_c_setprinter(false);
1880
1881         return result;
1882 }
1883
1884 /*******************************************************************
1885  * static function to lookup the version id corresponding to an
1886  * long architecture string
1887  ******************************************************************/
1888
1889 static const struct print_architecture_table_node archi_table[]= {
1890
1891         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1892         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1893         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1894         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1895         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1896         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1897         {"Windows x64",          SPL_ARCH_X64,          3 },
1898         {NULL,                   "",            -1 }
1899 };
1900
1901 static int get_version_id(const char *arch)
1902 {
1903         int i;
1904
1905         for (i=0; archi_table[i].long_archi != NULL; i++)
1906         {
1907                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1908                         return (archi_table[i].version);
1909         }
1910
1911         return -1;
1912 }
1913
1914 /****************************************************************
1915  _spoolss_DeletePrinterDriver
1916 ****************************************************************/
1917
1918 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1919                                     struct spoolss_DeletePrinterDriver *r)
1920 {
1921
1922         union spoolss_DriverInfo *info = NULL;
1923         union spoolss_DriverInfo *info_win2k = NULL;
1924         int                             version;
1925         WERROR                          status;
1926         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1927         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1928
1929         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1930            and not a printer admin, then fail */
1931
1932         if ( (p->server_info->utok.uid != sec_initial_uid())
1933                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1934                 && !token_contains_name_in_list(
1935                         uidtoname(p->server_info->utok.uid), NULL,
1936                         NULL, p->server_info->ptok,
1937                         lp_printer_admin(-1)) )
1938         {
1939                 return WERR_ACCESS_DENIED;
1940         }
1941
1942         /* check that we have a valid driver name first */
1943
1944         if ((version = get_version_id(r->in.architecture)) == -1)
1945                 return WERR_INVALID_ENVIRONMENT;
1946
1947         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
1948                                                 r->in.architecture,
1949                                                 version)))
1950         {
1951                 /* try for Win2k driver if "Windows NT x86" */
1952
1953                 if ( version == 2 ) {
1954                         version = 3;
1955                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1956                                                                 &info, 3,
1957                                                                 r->in.driver,
1958                                                                 r->in.architecture,
1959                                                                 version))) {
1960                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1961                                 goto done;
1962                         }
1963                 }
1964                 /* otherwise it was a failure */
1965                 else {
1966                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1967                         goto done;
1968                 }
1969
1970         }
1971
1972         if (printer_driver_in_use(&info->info3)) {
1973                 status = WERR_PRINTER_DRIVER_IN_USE;
1974                 goto done;
1975         }
1976
1977         if ( version == 2 )
1978         {
1979                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1980                                                        &info_win2k, 3,
1981                                                        r->in.driver,
1982                                                        r->in.architecture, 3)))
1983                 {
1984                         /* if we get to here, we now have 2 driver info structures to remove */
1985                         /* remove the Win2k driver first*/
1986
1987                         status_win2k = delete_printer_driver(
1988                                 p, &info_win2k->info3, 3, false);
1989                         free_a_printer_driver(info_win2k);
1990
1991                         /* this should not have failed---if it did, report to client */
1992                         if ( !W_ERROR_IS_OK(status_win2k) )
1993                         {
1994                                 status = status_win2k;
1995                                 goto done;
1996                         }
1997                 }
1998         }
1999
2000         status = delete_printer_driver(p, &info->info3, version, false);
2001
2002         /* if at least one of the deletes succeeded return OK */
2003
2004         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2005                 status = WERR_OK;
2006
2007 done:
2008         free_a_printer_driver(info);
2009
2010         return status;
2011 }
2012
2013 /****************************************************************
2014  _spoolss_DeletePrinterDriverEx
2015 ****************************************************************/
2016
2017 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2018                                       struct spoolss_DeletePrinterDriverEx *r)
2019 {
2020         union spoolss_DriverInfo        *info = NULL;
2021         union spoolss_DriverInfo        *info_win2k = NULL;
2022         int                             version;
2023         bool                            delete_files;
2024         WERROR                          status;
2025         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2026         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2027
2028         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2029            and not a printer admin, then fail */
2030
2031         if ( (p->server_info->utok.uid != sec_initial_uid())
2032                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2033                 && !token_contains_name_in_list(
2034                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2035                         p->server_info->ptok, lp_printer_admin(-1)) )
2036         {
2037                 return WERR_ACCESS_DENIED;
2038         }
2039
2040         /* check that we have a valid driver name first */
2041         if ((version = get_version_id(r->in.architecture)) == -1) {
2042                 /* this is what NT returns */
2043                 return WERR_INVALID_ENVIRONMENT;
2044         }
2045
2046         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2047                 version = r->in.version;
2048
2049         status = get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
2050                                       r->in.architecture, version);
2051
2052         if ( !W_ERROR_IS_OK(status) )
2053         {
2054                 /*
2055                  * if the client asked for a specific version,
2056                  * or this is something other than Windows NT x86,
2057                  * then we've failed
2058                  */
2059
2060                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2061                         goto done;
2062
2063                 /* try for Win2k driver if "Windows NT x86" */
2064
2065                 version = 3;
2066                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
2067                                                         r->in.architecture,
2068                                                         version))) {
2069                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2070                         goto done;
2071                 }
2072         }
2073
2074         if ( printer_driver_in_use(&info->info3) ) {
2075                 status = WERR_PRINTER_DRIVER_IN_USE;
2076                 goto done;
2077         }
2078
2079         /*
2080          * we have a couple of cases to consider.
2081          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2082          *     then the delete should fail if **any** files overlap with
2083          *     other drivers
2084          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2085          *     non-overlapping files
2086          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2087          *     is set, the do not delete any files
2088          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2089          */
2090
2091         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2092
2093         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2094
2095         if ( delete_files && printer_driver_files_in_use(info, &info->info3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2096                 /* no idea of the correct error here */
2097                 status = WERR_ACCESS_DENIED;
2098                 goto done;
2099         }
2100
2101
2102         /* also check for W32X86/3 if necessary; maybe we already have? */
2103
2104         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2105                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k, 3,
2106                                                        r->in.driver,
2107                                                        r->in.architecture, 3)))
2108                 {
2109
2110                         if ( delete_files && printer_driver_files_in_use(info, &info_win2k->info3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2111                                 /* no idea of the correct error here */
2112                                 free_a_printer_driver(info_win2k);
2113                                 status = WERR_ACCESS_DENIED;
2114                                 goto done;
2115                         }
2116
2117                         /* if we get to here, we now have 2 driver info structures to remove */
2118                         /* remove the Win2k driver first*/
2119
2120                         status_win2k = delete_printer_driver(
2121                                 p, &info_win2k->info3, 3, delete_files);
2122                         free_a_printer_driver(info_win2k);
2123
2124                         /* this should not have failed---if it did, report to client */
2125
2126                         if ( !W_ERROR_IS_OK(status_win2k) )
2127                                 goto done;
2128                 }
2129         }
2130
2131         status = delete_printer_driver(p, &info->info3, version, delete_files);
2132
2133         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2134                 status = WERR_OK;
2135 done:
2136         free_a_printer_driver(info);
2137
2138         return status;
2139 }
2140
2141
2142 /****************************************************************************
2143  Internal routine for removing printerdata
2144  ***************************************************************************/
2145
2146 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2147 {
2148         return delete_printer_data( printer->info_2, key, value );
2149 }
2150
2151 /****************************************************************************
2152  Internal routine for storing printerdata
2153  ***************************************************************************/
2154
2155 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2156                           const char *key, const char *value,
2157                           uint32_t type, uint8_t *data, int real_len)
2158 {
2159         /* the registry objects enforce uniqueness based on value name */
2160
2161         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2162 }
2163
2164 /********************************************************************
2165  GetPrinterData on a printer server Handle.
2166 ********************************************************************/
2167
2168 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2169                                             const char *value,
2170                                             enum winreg_Type *type,
2171                                             union spoolss_PrinterData *data)
2172 {
2173         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2174
2175         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2176                 *type = REG_DWORD;
2177                 data->value = 0x00;
2178                 return WERR_OK;
2179         }
2180
2181         if (!StrCaseCmp(value, "BeepEnabled")) {
2182                 *type = REG_DWORD;
2183                 data->value = 0x00;
2184                 return WERR_OK;
2185         }
2186
2187         if (!StrCaseCmp(value, "EventLog")) {
2188                 *type = REG_DWORD;
2189                 /* formally was 0x1b */
2190                 data->value = 0x00;
2191                 return WERR_OK;
2192         }
2193
2194         if (!StrCaseCmp(value, "NetPopup")) {
2195                 *type = REG_DWORD;
2196                 data->value = 0x00;
2197                 return WERR_OK;
2198         }
2199
2200         if (!StrCaseCmp(value, "MajorVersion")) {
2201                 *type = REG_DWORD;
2202
2203                 /* Windows NT 4.0 seems to not allow uploading of drivers
2204                    to a server that reports 0x3 as the MajorVersion.
2205                    need to investigate more how Win2k gets around this .
2206                    -- jerry */
2207
2208                 if (RA_WINNT == get_remote_arch()) {
2209                         data->value = 0x02;
2210                 } else {
2211                         data->value = 0x03;
2212                 }
2213
2214                 return WERR_OK;
2215         }
2216
2217         if (!StrCaseCmp(value, "MinorVersion")) {
2218                 *type = REG_DWORD;
2219                 data->value = 0x00;
2220                 return WERR_OK;
2221         }
2222
2223         /* REG_BINARY
2224          *  uint32_t size        = 0x114
2225          *  uint32_t major       = 5
2226          *  uint32_t minor       = [0|1]
2227          *  uint32_t build       = [2195|2600]
2228          *  extra unicode string = e.g. "Service Pack 3"
2229          */
2230         if (!StrCaseCmp(value, "OSVersion")) {
2231                 DATA_BLOB blob;
2232                 enum ndr_err_code ndr_err;
2233                 struct spoolss_OSVersion os;
2234
2235                 os.major                = 5;    /* Windows 2000 == 5.0 */
2236                 os.minor                = 0;
2237                 os.build                = 2195; /* build */
2238                 os.extra_string         = "";   /* leave extra string empty */
2239
2240                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2241                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2242                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2243                         return WERR_GENERAL_FAILURE;
2244                 }
2245
2246                 *type = REG_BINARY;
2247                 data->binary = blob;
2248
2249                 return WERR_OK;
2250         }
2251
2252
2253         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2254                 *type = REG_SZ;
2255
2256                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2257                 W_ERROR_HAVE_NO_MEMORY(data->string);
2258
2259                 return WERR_OK;
2260         }
2261
2262         if (!StrCaseCmp(value, "Architecture")) {
2263                 *type = REG_SZ;
2264
2265                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2266                 W_ERROR_HAVE_NO_MEMORY(data->string);
2267
2268                 return WERR_OK;
2269         }
2270
2271         if (!StrCaseCmp(value, "DsPresent")) {
2272                 *type = REG_DWORD;
2273
2274                 /* only show the publish check box if we are a
2275                    member of a AD domain */
2276
2277                 if (lp_security() == SEC_ADS) {
2278                         data->value = 0x01;
2279                 } else {
2280                         data->value = 0x00;
2281                 }
2282                 return WERR_OK;
2283         }
2284
2285         if (!StrCaseCmp(value, "DNSMachineName")) {
2286                 const char *hostname = get_mydnsfullname();
2287
2288                 if (!hostname) {
2289                         return WERR_BADFILE;
2290                 }
2291
2292                 *type = REG_SZ;
2293                 data->string = talloc_strdup(mem_ctx, hostname);
2294                 W_ERROR_HAVE_NO_MEMORY(data->string);
2295
2296                 return WERR_OK;
2297         }
2298
2299         return WERR_INVALID_PARAM;
2300 }
2301
2302 /****************************************************************
2303  _spoolss_GetPrinterData
2304 ****************************************************************/
2305
2306 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2307                                struct spoolss_GetPrinterData *r)
2308 {
2309         WERROR result;
2310         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2311         NT_PRINTER_INFO_LEVEL *printer = NULL;
2312         int snum = 0;
2313
2314         /*
2315          * Reminder: when it's a string, the length is in BYTES
2316          * even if UNICODE is negociated.
2317          *
2318          * JFM, 4/19/1999
2319          */
2320
2321         /* in case of problem, return some default values */
2322
2323         *r->out.needed  = 0;
2324         *r->out.type    = 0;
2325
2326         DEBUG(4,("_spoolss_GetPrinterData\n"));
2327
2328         if (!Printer) {
2329                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2330                         OUR_HANDLE(r->in.handle)));
2331                 result = WERR_BADFID;
2332                 goto done;
2333         }
2334
2335         if (Printer->printer_type == SPLHND_SERVER) {
2336                 result = getprinterdata_printer_server(p->mem_ctx,
2337                                                        r->in.value_name,
2338                                                        r->out.type,
2339                                                        r->out.data);
2340         } else {
2341                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2342                         result = WERR_BADFID;
2343                         goto done;
2344                 }
2345
2346                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2347                 if (!W_ERROR_IS_OK(result)) {
2348                         goto done;
2349                 }
2350
2351                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2352
2353                 if (strequal(r->in.value_name, "ChangeId")) {
2354                         *r->out.type = REG_DWORD;
2355                         r->out.data->value = printer->info_2->changeid;
2356                         result = WERR_OK;
2357                 } else {
2358                         struct regval_blob *v;
2359                         DATA_BLOB blob;
2360
2361                         v = get_printer_data(printer->info_2,
2362                                              SPOOL_PRINTERDATA_KEY,
2363                                              r->in.value_name);
2364                         if (!v) {
2365                                 result = WERR_BADFILE;
2366                                 goto done;
2367                         }
2368
2369                         *r->out.type = v->type;
2370
2371                         blob = data_blob_const(v->data_p, v->size);
2372
2373                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2374                                                           r->out.data,
2375                                                           *r->out.type);
2376                 }
2377         }
2378
2379  done:
2380         /* cleanup & exit */
2381
2382         if (printer) {
2383                 free_a_printer(&printer, 2);
2384         }
2385
2386         if (!W_ERROR_IS_OK(result)) {
2387                 return result;
2388         }
2389
2390         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2391         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2392         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2393
2394         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2395 }
2396
2397 /*********************************************************
2398  Connect to the client machine.
2399 **********************************************************/
2400
2401 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2402                         struct sockaddr_storage *client_ss, const char *remote_machine)
2403 {
2404         NTSTATUS ret;
2405         struct cli_state *the_cli;
2406         struct sockaddr_storage rm_addr;
2407
2408         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2409                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2410                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2411                         return false;
2412                 }
2413
2414                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2415                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2416                         return false;
2417                 }
2418         } else {
2419                 char addr[INET6_ADDRSTRLEN];
2420                 rm_addr = *client_ss;
2421                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2422                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2423                         addr));
2424         }
2425
2426         /* setup the connection */
2427
2428         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2429                 &rm_addr, 0, "IPC$", "IPC",
2430                 "", /* username */
2431                 "", /* domain */
2432                 "", /* password */
2433                 0, lp_client_signing(), NULL );
2434
2435         if ( !NT_STATUS_IS_OK( ret ) ) {
2436                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2437                         remote_machine ));
2438                 return false;
2439         }
2440
2441         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2442                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2443                 cli_shutdown(the_cli);
2444                 return false;
2445         }
2446
2447         /*
2448          * Ok - we have an anonymous connection to the IPC$ share.
2449          * Now start the NT Domain stuff :-).
2450          */
2451
2452         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2453         if (!NT_STATUS_IS_OK(ret)) {
2454                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2455                         remote_machine, nt_errstr(ret)));
2456                 cli_shutdown(the_cli);
2457                 return false;
2458         }
2459
2460         return true;
2461 }
2462
2463 /***************************************************************************
2464  Connect to the client.
2465 ****************************************************************************/
2466
2467 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2468                                         uint32_t localprinter, uint32_t type,
2469                                         struct policy_handle *handle,
2470                                         struct sockaddr_storage *client_ss)
2471 {
2472         WERROR result;
2473         NTSTATUS status;
2474
2475         /*
2476          * If it's the first connection, contact the client
2477          * and connect to the IPC$ share anonymously
2478          */
2479         if (smb_connections==0) {
2480                 fstring unix_printer;
2481
2482                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2483
2484                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2485                         return false;
2486
2487                 messaging_register(smbd_messaging_context(), NULL,
2488                                    MSG_PRINTER_NOTIFY2,
2489                                    receive_notify2_message_list);
2490                 /* Tell the connections db we're now interested in printer
2491                  * notify messages. */
2492                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2493         }
2494
2495         /*
2496          * Tell the specific printing tdb we want messages for this printer
2497          * by registering our PID.
2498          */
2499
2500         if (!print_notify_register_pid(snum))
2501                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2502
2503         smb_connections++;
2504
2505         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2506                                                  printer,
2507                                                  localprinter,
2508                                                  type,
2509                                                  0,
2510                                                  NULL,
2511                                                  handle,
2512                                                  &result);
2513         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2514                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2515                         win_errstr(result)));
2516
2517         return (W_ERROR_IS_OK(result));
2518 }
2519
2520 /****************************************************************
2521  ****************************************************************/
2522
2523 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2524                                                              const struct spoolss_NotifyOption *r)
2525 {
2526         struct spoolss_NotifyOption *option;
2527         uint32_t i,k;
2528
2529         if (!r) {
2530                 return NULL;
2531         }
2532
2533         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2534         if (!option) {
2535                 return NULL;
2536         }
2537
2538         *option = *r;
2539
2540         if (!option->count) {
2541                 return option;
2542         }
2543
2544         option->types = talloc_zero_array(option,
2545                 struct spoolss_NotifyOptionType, option->count);
2546         if (!option->types) {
2547                 talloc_free(option);
2548                 return NULL;
2549         }
2550
2551         for (i=0; i < option->count; i++) {
2552                 option->types[i] = r->types[i];
2553
2554                 if (option->types[i].count) {
2555                         option->types[i].fields = talloc_zero_array(option,
2556                                 union spoolss_Field, option->types[i].count);
2557                         if (!option->types[i].fields) {
2558                                 talloc_free(option);
2559                                 return NULL;
2560                         }
2561                         for (k=0; k<option->types[i].count; k++) {
2562                                 option->types[i].fields[k] =
2563                                         r->types[i].fields[k];
2564                         }
2565                 }
2566         }
2567
2568         return option;
2569 }
2570
2571 /****************************************************************
2572  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2573  *
2574  * before replying OK: status=0 a rpc call is made to the workstation
2575  * asking ReplyOpenPrinter
2576  *
2577  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2578  * called from api_spoolss_rffpcnex
2579 ****************************************************************/
2580
2581 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2582                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2583 {
2584         int snum = -1;
2585         struct spoolss_NotifyOption *option = r->in.notify_options;
2586         struct sockaddr_storage client_ss;
2587
2588         /* store the notify value in the printer struct */
2589
2590         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2591
2592         if (!Printer) {
2593                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2594                         "Invalid handle (%s:%u:%u).\n",
2595                         OUR_HANDLE(r->in.handle)));
2596                 return WERR_BADFID;
2597         }
2598
2599         Printer->notify.flags           = r->in.flags;
2600         Printer->notify.options         = r->in.options;
2601         Printer->notify.printerlocal    = r->in.printer_local;
2602
2603         TALLOC_FREE(Printer->notify.option);
2604         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2605
2606         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2607
2608         /* Connect to the client machine and send a ReplyOpenPrinter */
2609
2610         if ( Printer->printer_type == SPLHND_SERVER)
2611                 snum = -1;
2612         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2613                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2614                 return WERR_BADFID;
2615
2616         if (!interpret_string_addr(&client_ss, p->client_address,
2617                                    AI_NUMERICHOST)) {
2618                 return WERR_SERVER_UNAVAILABLE;
2619         }
2620
2621         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2622                                         Printer->notify.printerlocal, 1,
2623                                         &Printer->notify.client_hnd, &client_ss))
2624                 return WERR_SERVER_UNAVAILABLE;
2625
2626         Printer->notify.client_connected = true;
2627
2628         return WERR_OK;
2629 }
2630
2631 /*******************************************************************
2632  * fill a notify_info_data with the servername
2633  ********************************************************************/
2634
2635 void spoolss_notify_server_name(int snum,
2636                                        struct spoolss_Notify *data,
2637                                        print_queue_struct *queue,
2638                                        NT_PRINTER_INFO_LEVEL *printer,
2639                                        TALLOC_CTX *mem_ctx)
2640 {
2641         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2642 }
2643
2644 /*******************************************************************
2645  * fill a notify_info_data with the printername (not including the servername).
2646  ********************************************************************/
2647
2648 void spoolss_notify_printer_name(int snum,
2649                                         struct spoolss_Notify *data,
2650                                         print_queue_struct *queue,
2651                                         NT_PRINTER_INFO_LEVEL *printer,
2652                                         TALLOC_CTX *mem_ctx)
2653 {
2654         /* the notify name should not contain the \\server\ part */
2655         char *p = strrchr(printer->info_2->printername, '\\');
2656
2657         if (!p) {
2658                 p = printer->info_2->printername;
2659         } else {
2660                 p++;
2661         }
2662
2663         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2664 }
2665
2666 /*******************************************************************
2667  * fill a notify_info_data with the servicename
2668  ********************************************************************/
2669
2670 void spoolss_notify_share_name(int snum,
2671                                       struct spoolss_Notify *data,
2672                                       print_queue_struct *queue,
2673                                       NT_PRINTER_INFO_LEVEL *printer,
2674                                       TALLOC_CTX *mem_ctx)
2675 {
2676         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2677 }
2678
2679 /*******************************************************************
2680  * fill a notify_info_data with the port name
2681  ********************************************************************/
2682
2683 void spoolss_notify_port_name(int snum,
2684                                      struct spoolss_Notify *data,
2685                                      print_queue_struct *queue,
2686                                      NT_PRINTER_INFO_LEVEL *printer,
2687                                      TALLOC_CTX *mem_ctx)
2688 {
2689         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2690 }
2691
2692 /*******************************************************************
2693  * fill a notify_info_data with the printername
2694  * but it doesn't exist, have to see what to do
2695  ********************************************************************/
2696
2697 void spoolss_notify_driver_name(int snum,
2698                                        struct spoolss_Notify *data,
2699                                        print_queue_struct *queue,
2700                                        NT_PRINTER_INFO_LEVEL *printer,
2701                                        TALLOC_CTX *mem_ctx)
2702 {
2703         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2704 }
2705
2706 /*******************************************************************
2707  * fill a notify_info_data with the comment
2708  ********************************************************************/
2709
2710 void spoolss_notify_comment(int snum,
2711                                    struct spoolss_Notify *data,
2712                                    print_queue_struct *queue,
2713                                    NT_PRINTER_INFO_LEVEL *printer,
2714                                    TALLOC_CTX *mem_ctx)
2715 {
2716         char *p;
2717
2718         if (*printer->info_2->comment == '\0') {
2719                 p = lp_comment(snum);
2720         } else {
2721                 p = printer->info_2->comment;
2722         }
2723
2724         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2725 }
2726
2727 /*******************************************************************
2728  * fill a notify_info_data with the comment
2729  * location = "Room 1, floor 2, building 3"
2730  ********************************************************************/
2731
2732 void spoolss_notify_location(int snum,
2733                                     struct spoolss_Notify *data,
2734                                     print_queue_struct *queue,
2735                                     NT_PRINTER_INFO_LEVEL *printer,
2736                                     TALLOC_CTX *mem_ctx)
2737 {
2738         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2739 }
2740
2741 /*******************************************************************
2742  * fill a notify_info_data with the device mode
2743  * jfm:xxxx don't to it for know but that's a real problem !!!
2744  ********************************************************************/
2745
2746 static void spoolss_notify_devmode(int snum,
2747                                    struct spoolss_Notify *data,
2748                                    print_queue_struct *queue,
2749                                    NT_PRINTER_INFO_LEVEL *printer,
2750                                    TALLOC_CTX *mem_ctx)
2751 {
2752         /* for a dummy implementation we have to zero the fields */
2753         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2754 }
2755
2756 /*******************************************************************
2757  * fill a notify_info_data with the separator file name
2758  ********************************************************************/
2759
2760 void spoolss_notify_sepfile(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_STRING(data, printer->info_2->sepfile);
2767 }
2768
2769 /*******************************************************************
2770  * fill a notify_info_data with the print processor
2771  * jfm:xxxx return always winprint to indicate we don't do anything to it
2772  ********************************************************************/
2773
2774 void spoolss_notify_print_processor(int snum,
2775                                            struct spoolss_Notify *data,
2776                                            print_queue_struct *queue,
2777                                            NT_PRINTER_INFO_LEVEL *printer,
2778                                            TALLOC_CTX *mem_ctx)
2779 {
2780         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2781 }
2782
2783 /*******************************************************************
2784  * fill a notify_info_data with the print processor options
2785  * jfm:xxxx send an empty string
2786  ********************************************************************/
2787
2788 void spoolss_notify_parameters(int snum,
2789                                       struct spoolss_Notify *data,
2790                                       print_queue_struct *queue,
2791                                       NT_PRINTER_INFO_LEVEL *printer,
2792                                       TALLOC_CTX *mem_ctx)
2793 {
2794         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2795 }
2796
2797 /*******************************************************************
2798  * fill a notify_info_data with the data type
2799  * jfm:xxxx always send RAW as data type
2800  ********************************************************************/
2801
2802 void spoolss_notify_datatype(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_STRING(data, printer->info_2->datatype);
2809 }
2810
2811 /*******************************************************************
2812  * fill a notify_info_data with the security descriptor
2813  * jfm:xxxx send an null pointer to say no security desc
2814  * have to implement security before !
2815  ********************************************************************/
2816
2817 static void spoolss_notify_security_desc(int snum,
2818                                          struct spoolss_Notify *data,
2819                                          print_queue_struct *queue,
2820                                          NT_PRINTER_INFO_LEVEL *printer,
2821                                          TALLOC_CTX *mem_ctx)
2822 {
2823         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2824                                           printer->info_2->secdesc_buf->sd_size,
2825                                           printer->info_2->secdesc_buf->sd);
2826 }
2827
2828 /*******************************************************************
2829  * fill a notify_info_data with the attributes
2830  * jfm:xxxx a samba printer is always shared
2831  ********************************************************************/
2832
2833 void spoolss_notify_attributes(int snum,
2834                                       struct spoolss_Notify *data,
2835                                       print_queue_struct *queue,
2836                                       NT_PRINTER_INFO_LEVEL *printer,
2837                                       TALLOC_CTX *mem_ctx)
2838 {
2839         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2840 }
2841
2842 /*******************************************************************
2843  * fill a notify_info_data with the priority
2844  ********************************************************************/
2845
2846 static void spoolss_notify_priority(int snum,
2847                                     struct spoolss_Notify *data,
2848                                     print_queue_struct *queue,
2849                                     NT_PRINTER_INFO_LEVEL *printer,
2850                                     TALLOC_CTX *mem_ctx)
2851 {
2852         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2853 }
2854
2855 /*******************************************************************
2856  * fill a notify_info_data with the default priority
2857  ********************************************************************/
2858
2859 static void spoolss_notify_default_priority(int snum,
2860                                             struct spoolss_Notify *data,
2861                                             print_queue_struct *queue,
2862                                             NT_PRINTER_INFO_LEVEL *printer,
2863                                             TALLOC_CTX *mem_ctx)
2864 {
2865         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2866 }
2867
2868 /*******************************************************************
2869  * fill a notify_info_data with the start time
2870  ********************************************************************/
2871
2872 static void spoolss_notify_start_time(int snum,
2873                                       struct spoolss_Notify *data,
2874                                       print_queue_struct *queue,
2875                                       NT_PRINTER_INFO_LEVEL *printer,
2876                                       TALLOC_CTX *mem_ctx)
2877 {
2878         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with the until time
2883  ********************************************************************/
2884
2885 static void spoolss_notify_until_time(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_INTEGER(data, printer->info_2->untiltime);
2892 }
2893
2894 /*******************************************************************
2895  * fill a notify_info_data with the status
2896  ********************************************************************/
2897
2898 static void spoolss_notify_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         print_status_struct status;
2905
2906         print_queue_length(snum, &status);
2907         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2908 }
2909
2910 /*******************************************************************
2911  * fill a notify_info_data with the number of jobs queued
2912  ********************************************************************/
2913
2914 void spoolss_notify_cjobs(int snum,
2915                                  struct spoolss_Notify *data,
2916                                  print_queue_struct *queue,
2917                                  NT_PRINTER_INFO_LEVEL *printer,
2918                                  TALLOC_CTX *mem_ctx)
2919 {
2920         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2921 }
2922
2923 /*******************************************************************
2924  * fill a notify_info_data with the average ppm
2925  ********************************************************************/
2926
2927 static void spoolss_notify_average_ppm(int snum,
2928                                        struct spoolss_Notify *data,
2929                                        print_queue_struct *queue,
2930                                        NT_PRINTER_INFO_LEVEL *printer,
2931                                        TALLOC_CTX *mem_ctx)
2932 {
2933         /* always respond 8 pages per minutes */
2934         /* a little hard ! */
2935         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2936 }
2937
2938 /*******************************************************************
2939  * fill a notify_info_data with username
2940  ********************************************************************/
2941
2942 static void spoolss_notify_username(int snum,
2943                                     struct spoolss_Notify *data,
2944                                     print_queue_struct *queue,
2945                                     NT_PRINTER_INFO_LEVEL *printer,
2946                                     TALLOC_CTX *mem_ctx)
2947 {
2948         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2949 }
2950
2951 /*******************************************************************
2952  * fill a notify_info_data with job status
2953  ********************************************************************/
2954
2955 static void spoolss_notify_job_status(int snum,
2956                                       struct spoolss_Notify *data,
2957                                       print_queue_struct *queue,
2958                                       NT_PRINTER_INFO_LEVEL *printer,
2959                                       TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with job name
2966  ********************************************************************/
2967
2968 static void spoolss_notify_job_name(int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     NT_PRINTER_INFO_LEVEL *printer,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with job status
2979  ********************************************************************/
2980
2981 static void spoolss_notify_job_status_string(int snum,
2982                                              struct spoolss_Notify *data,
2983                                              print_queue_struct *queue,
2984                                              NT_PRINTER_INFO_LEVEL *printer,
2985                                              TALLOC_CTX *mem_ctx)
2986 {
2987         /*
2988          * Now we're returning job status codes we just return a "" here. JRA.
2989          */
2990
2991         const char *p = "";
2992
2993 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2994         p = "unknown";
2995
2996         switch (queue->status) {
2997         case LPQ_QUEUED:
2998                 p = "Queued";
2999                 break;
3000         case LPQ_PAUSED:
3001                 p = "";    /* NT provides the paused string */
3002                 break;
3003         case LPQ_SPOOLING:
3004                 p = "Spooling";
3005                 break;
3006         case LPQ_PRINTING:
3007                 p = "Printing";
3008                 break;
3009         }
3010 #endif /* NO LONGER NEEDED. */
3011
3012         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with job time
3017  ********************************************************************/
3018
3019 static void spoolss_notify_job_time(int snum,
3020                                     struct spoolss_Notify *data,
3021                                     print_queue_struct *queue,
3022                                     NT_PRINTER_INFO_LEVEL *printer,
3023                                     TALLOC_CTX *mem_ctx)
3024 {
3025         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3026 }
3027
3028 /*******************************************************************
3029  * fill a notify_info_data with job size
3030  ********************************************************************/
3031
3032 static void spoolss_notify_job_size(int snum,
3033                                     struct spoolss_Notify *data,
3034                                     print_queue_struct *queue,
3035                                     NT_PRINTER_INFO_LEVEL *printer,
3036                                     TALLOC_CTX *mem_ctx)
3037 {
3038         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3039 }
3040
3041 /*******************************************************************
3042  * fill a notify_info_data with page info
3043  ********************************************************************/
3044 static void spoolss_notify_total_pages(int snum,
3045                                 struct spoolss_Notify *data,
3046                                 print_queue_struct *queue,
3047                                 NT_PRINTER_INFO_LEVEL *printer,
3048                                 TALLOC_CTX *mem_ctx)
3049 {
3050         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3051 }
3052
3053 /*******************************************************************
3054  * fill a notify_info_data with pages printed info.
3055  ********************************************************************/
3056 static void spoolss_notify_pages_printed(int snum,
3057                                 struct spoolss_Notify *data,
3058                                 print_queue_struct *queue,
3059                                 NT_PRINTER_INFO_LEVEL *printer,
3060                                 TALLOC_CTX *mem_ctx)
3061 {
3062         /* Add code when back-end tracks this */
3063         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3064 }
3065
3066 /*******************************************************************
3067  Fill a notify_info_data with job position.
3068  ********************************************************************/
3069
3070 static void spoolss_notify_job_position(int snum,
3071                                         struct spoolss_Notify *data,
3072                                         print_queue_struct *queue,
3073                                         NT_PRINTER_INFO_LEVEL *printer,
3074                                         TALLOC_CTX *mem_ctx)
3075 {
3076         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3077 }
3078
3079 /*******************************************************************
3080  Fill a notify_info_data with submitted time.
3081  ********************************************************************/
3082
3083 static void spoolss_notify_submitted_time(int snum,
3084                                           struct spoolss_Notify *data,
3085                                           print_queue_struct *queue,
3086                                           NT_PRINTER_INFO_LEVEL *printer,
3087                                           TALLOC_CTX *mem_ctx)
3088 {
3089         data->data.string.string = NULL;
3090         data->data.string.size = 0;
3091
3092         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3093                                &data->data.string.string,
3094                                &data->data.string.size);
3095
3096 }
3097
3098 struct s_notify_info_data_table
3099 {
3100         enum spoolss_NotifyType type;
3101         uint16_t field;
3102         const char *name;
3103         enum spoolss_NotifyTable variable_type;
3104         void (*fn) (int snum, struct spoolss_Notify *data,
3105                     print_queue_struct *queue,
3106                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3107 };
3108
3109 /* A table describing the various print notification constants and
3110    whether the notification data is a pointer to a variable sized
3111    buffer, a one value uint32_t or a two value uint32_t. */
3112
3113 static const struct s_notify_info_data_table notify_info_data_table[] =
3114 {
3115 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3116 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3117 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3118 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3119 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3120 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3121 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3122 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3123 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3124 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3125 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3126 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3127 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3128 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3129 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3130 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3131 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3132 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3133 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3134 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3135 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3136 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3137 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3138 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3139 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3140 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3141 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3142 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3143 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3144 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3145 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3146 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3147 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3148 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3149 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3150 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3151 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3152 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3153 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3154 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3155 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3156 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3157 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3158 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3159 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3160 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3161 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3162 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3163 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3164 };
3165
3166 /*******************************************************************
3167  Return the variable_type of info_data structure.
3168 ********************************************************************/
3169
3170 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3171                                                   uint16_t field)
3172 {
3173         int i=0;
3174
3175         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3176                 if ( (notify_info_data_table[i].type == type) &&
3177                      (notify_info_data_table[i].field == field) ) {
3178                         return notify_info_data_table[i].variable_type;
3179                 }
3180         }
3181
3182         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3183
3184         return 0;
3185 }
3186
3187 /****************************************************************************
3188 ****************************************************************************/
3189
3190 static bool search_notify(enum spoolss_NotifyType type,
3191                           uint16_t field,
3192                           int *value)
3193 {
3194         int i;
3195
3196         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3197                 if (notify_info_data_table[i].type == type &&
3198                     notify_info_data_table[i].field == field &&
3199                     notify_info_data_table[i].fn != NULL) {
3200                         *value = i;
3201                         return true;
3202                 }
3203         }
3204
3205         return false;
3206 }
3207
3208 /****************************************************************************
3209 ****************************************************************************/
3210
3211 void construct_info_data(struct spoolss_Notify *info_data,
3212                          enum spoolss_NotifyType type,
3213                          uint16_t field,
3214                          int id)
3215 {
3216         info_data->type                 = type;
3217         info_data->field.field          = field;
3218         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3219         info_data->job_id               = id;
3220 }
3221
3222 /*******************************************************************
3223  *
3224  * fill a notify_info struct with info asked
3225  *
3226  ********************************************************************/
3227
3228 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3229                                           struct spoolss_NotifyInfo *info,
3230                                           int snum,
3231                                           const struct spoolss_NotifyOptionType *option_type,
3232                                           uint32_t id,
3233                                           TALLOC_CTX *mem_ctx)
3234 {
3235         int field_num,j;
3236         enum spoolss_NotifyType type;
3237         uint16_t field;
3238
3239         struct spoolss_Notify *current_data;
3240         NT_PRINTER_INFO_LEVEL *printer = NULL;
3241         print_queue_struct *queue=NULL;
3242
3243         type = option_type->type;
3244
3245         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3246                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3247                 option_type->count, lp_servicename(snum)));
3248
3249         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3250                 return false;
3251
3252         for(field_num=0; field_num < option_type->count; field_num++) {
3253                 field = option_type->fields[field_num].field;
3254
3255                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3256
3257                 if (!search_notify(type, field, &j) )
3258                         continue;
3259
3260                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3261                                                       struct spoolss_Notify,
3262                                                       info->count + 1);
3263                 if (info->notifies == NULL) {
3264                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3265                         free_a_printer(&printer, 2);
3266                         return false;
3267                 }
3268
3269                 current_data = &info->notifies[info->count];
3270
3271                 construct_info_data(current_data, type, field, id);
3272
3273                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3274                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3275
3276                 notify_info_data_table[j].fn(snum, current_data, queue,
3277                                              printer, mem_ctx);
3278
3279                 info->count++;
3280         }
3281
3282         free_a_printer(&printer, 2);
3283         return true;
3284 }
3285
3286 /*******************************************************************
3287  *
3288  * fill a notify_info struct with info asked
3289  *
3290  ********************************************************************/
3291
3292 static bool construct_notify_jobs_info(print_queue_struct *queue,
3293                                        struct spoolss_NotifyInfo *info,
3294                                        NT_PRINTER_INFO_LEVEL *printer,
3295                                        int snum,
3296                                        const struct spoolss_NotifyOptionType *option_type,
3297                                        uint32_t id,
3298                                        TALLOC_CTX *mem_ctx)
3299 {
3300         int field_num,j;
3301         enum spoolss_NotifyType type;
3302         uint16_t field;
3303         struct spoolss_Notify *current_data;
3304
3305         DEBUG(4,("construct_notify_jobs_info\n"));
3306
3307         type = option_type->type;
3308
3309         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3310                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3311                 option_type->count));
3312
3313         for(field_num=0; field_num<option_type->count; field_num++) {
3314                 field = option_type->fields[field_num].field;
3315
3316                 if (!search_notify(type, field, &j) )
3317                         continue;
3318
3319                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3320                                                       struct spoolss_Notify,
3321                                                       info->count + 1);
3322                 if (info->notifies == NULL) {
3323                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3324                         return false;
3325                 }
3326
3327                 current_data=&(info->notifies[info->count]);
3328
3329                 construct_info_data(current_data, type, field, id);
3330                 notify_info_data_table[j].fn(snum, current_data, queue,
3331                                              printer, mem_ctx);
3332                 info->count++;
3333         }
3334
3335         return true;
3336 }
3337
3338 /*
3339  * JFM: The enumeration is not that simple, it's even non obvious.
3340  *
3341  * let's take an example: I want to monitor the PRINTER SERVER for
3342  * the printer's name and the number of jobs currently queued.
3343  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3344  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3345  *
3346  * I have 3 printers on the back of my server.
3347  *
3348  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3349  * structures.
3350  *   Number     Data                    Id
3351  *      1       printer 1 name          1
3352  *      2       printer 1 cjob          1
3353  *      3       printer 2 name          2
3354  *      4       printer 2 cjob          2
3355  *      5       printer 3 name          3
3356  *      6       printer 3 name          3
3357  *
3358  * that's the print server case, the printer case is even worse.
3359  */
3360
3361 /*******************************************************************
3362  *
3363  * enumerate all printers on the printserver
3364  * fill a notify_info struct with info asked
3365  *
3366  ********************************************************************/
3367
3368 static WERROR printserver_notify_info(pipes_struct *p,
3369                                       struct policy_handle *hnd,
3370                                       struct spoolss_NotifyInfo *info,
3371                                       TALLOC_CTX *mem_ctx)
3372 {
3373         int snum;
3374         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3375         int n_services=lp_numservices();
3376         int i;
3377         struct spoolss_NotifyOption *option;
3378         struct spoolss_NotifyOptionType option_type;
3379
3380         DEBUG(4,("printserver_notify_info\n"));
3381
3382         if (!Printer)
3383                 return WERR_BADFID;
3384
3385         option = Printer->notify.option;
3386
3387         info->version   = 2;
3388         info->notifies  = NULL;
3389         info->count     = 0;
3390
3391         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3392            sending a ffpcn() request first */
3393
3394         if ( !option )
3395                 return WERR_BADFID;
3396
3397         for (i=0; i<option->count; i++) {
3398                 option_type = option->types[i];
3399
3400                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3401                         continue;
3402
3403                 for (snum=0; snum<n_services; snum++)
3404                 {
3405                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3406                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3407                 }
3408         }
3409
3410 #if 0
3411         /*
3412          * Debugging information, don't delete.
3413          */
3414
3415         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3416         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3417         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3418
3419         for (i=0; i<info->count; i++) {
3420                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3421                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3422                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3423         }
3424 #endif
3425
3426         return WERR_OK;
3427 }
3428
3429 /*******************************************************************
3430  *
3431  * fill a notify_info struct with info asked
3432  *
3433  ********************************************************************/
3434
3435 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3436                                   struct spoolss_NotifyInfo *info,
3437                                   TALLOC_CTX *mem_ctx)
3438 {
3439         int snum;
3440         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3441         int i;
3442         uint32_t id;
3443         struct spoolss_NotifyOption *option;
3444         struct spoolss_NotifyOptionType option_type;
3445         int count,j;
3446         print_queue_struct *queue=NULL;
3447         print_status_struct status;
3448
3449         DEBUG(4,("printer_notify_info\n"));
3450
3451         if (!Printer)
3452                 return WERR_BADFID;
3453
3454         option = Printer->notify.option;
3455         id = 0x0;
3456
3457         info->version   = 2;
3458         info->notifies  = NULL;
3459         info->count     = 0;
3460
3461         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3462            sending a ffpcn() request first */
3463
3464         if ( !option )
3465                 return WERR_BADFID;
3466
3467         get_printer_snum(p, hnd, &snum, NULL);
3468
3469         for (i=0; i<option->count; i++) {
3470                 option_type = option->types[i];
3471
3472                 switch (option_type.type) {
3473                 case PRINTER_NOTIFY_TYPE:
3474                         if(construct_notify_printer_info(Printer, info, snum,
3475                                                          &option_type, id,
3476                                                          mem_ctx))
3477                                 id--;
3478                         break;
3479
3480                 case JOB_NOTIFY_TYPE: {
3481                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3482
3483                         count = print_queue_status(snum, &queue, &status);
3484
3485                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3486                                 goto done;
3487
3488                         for (j=0; j<count; j++) {
3489                                 construct_notify_jobs_info(&queue[j], info,
3490                                                            printer, snum,
3491                                                            &option_type,
3492                                                            queue[j].job,
3493                                                            mem_ctx);
3494                         }
3495
3496                         free_a_printer(&printer, 2);
3497
3498                 done:
3499                         SAFE_FREE(queue);
3500                         break;
3501                 }
3502                 }
3503         }
3504
3505         /*
3506          * Debugging information, don't delete.
3507          */
3508         /*
3509         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3510         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3511         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3512
3513         for (i=0; i<info->count; i++) {
3514                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3515                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3516                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3517         }
3518         */
3519         return WERR_OK;
3520 }
3521
3522 /****************************************************************
3523  _spoolss_RouterRefreshPrinterChangeNotify
3524 ****************************************************************/
3525
3526 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3527                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3528 {
3529         struct spoolss_NotifyInfo *info;
3530
3531         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3532         WERROR result = WERR_BADFID;
3533
3534         /* we always have a spoolss_NotifyInfo struct */
3535         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3536         if (!info) {
3537                 result = WERR_NOMEM;
3538                 goto done;
3539         }
3540
3541         *r->out.info = info;
3542
3543         if (!Printer) {
3544                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3545                         "Invalid handle (%s:%u:%u).\n",
3546                         OUR_HANDLE(r->in.handle)));
3547                 goto done;
3548         }
3549
3550         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3551
3552         /*
3553          *      We are now using the change value, and
3554          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3555          *      I don't have a global notification system, I'm sending back all the
3556          *      informations even when _NOTHING_ has changed.
3557          */
3558
3559         /* We need to keep track of the change value to send back in
3560            RRPCN replies otherwise our updates are ignored. */
3561
3562         Printer->notify.fnpcn = true;
3563
3564         if (Printer->notify.client_connected) {
3565                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3566                         "Saving change value in request [%x]\n",
3567                         r->in.change_low));
3568                 Printer->notify.change = r->in.change_low;
3569         }
3570
3571         /* just ignore the spoolss_NotifyOption */
3572
3573         switch (Printer->printer_type) {
3574                 case SPLHND_SERVER:
3575                         result = printserver_notify_info(p, r->in.handle,
3576                                                          info, p->mem_ctx);
3577                         break;
3578
3579                 case SPLHND_PRINTER:
3580                         result = printer_notify_info(p, r->in.handle,
3581                                                      info, p->mem_ctx);
3582                         break;
3583         }
3584
3585         Printer->notify.fnpcn = false;
3586
3587 done:
3588         return result;
3589 }
3590
3591 /********************************************************************
3592  * construct_printer_info_0
3593  * fill a printer_info_0 struct
3594  ********************************************************************/
3595
3596 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3597                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3598                                       struct spoolss_PrinterInfo0 *r,
3599                                       int snum)
3600 {
3601         int count;
3602         counter_printer_0 *session_counter;
3603         time_t setuptime;
3604         print_status_struct status;
3605
3606         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3607         W_ERROR_HAVE_NO_MEMORY(r->printername);
3608
3609         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3610         W_ERROR_HAVE_NO_MEMORY(r->servername);
3611
3612         count = print_queue_length(snum, &status);
3613
3614         /* check if we already have a counter for this printer */
3615         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3616                 if (session_counter->snum == snum)
3617                         break;
3618         }
3619
3620         /* it's the first time, add it to the list */
3621         if (session_counter == NULL) {
3622                 session_counter = SMB_MALLOC_P(counter_printer_0);
3623                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3624                 ZERO_STRUCTP(session_counter);
3625                 session_counter->snum           = snum;
3626                 session_counter->counter        = 0;
3627                 DLIST_ADD(counter_list, session_counter);
3628         }
3629
3630         /* increment it */
3631         session_counter->counter++;
3632
3633         r->cjobs                        = count;
3634         r->total_jobs                   = 0;
3635         r->total_bytes                  = 0;
3636
3637         setuptime = (time_t)ntprinter->info_2->setuptime;
3638
3639         init_systemtime(&r->time, gmtime(&setuptime));
3640
3641         /* JFM:
3642          * the global_counter should be stored in a TDB as it's common to all the clients
3643          * and should be zeroed on samba startup
3644          */
3645         r->global_counter               = session_counter->counter;
3646         r->total_pages                  = 0;
3647         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3648         r->version                      = 0x0005;       /* NT 5 */
3649         r->free_build                   = 0x0893;       /* build 2195 */
3650         r->spooling                     = 0;
3651         r->max_spooling                 = 0;
3652         r->session_counter              = session_counter->counter;
3653         r->num_error_out_of_paper       = 0x0;
3654         r->num_error_not_ready          = 0x0;          /* number of print failure */
3655         r->job_error                    = 0x0;
3656         r->number_of_processors         = 0x1;
3657         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3658         r->high_part_total_bytes        = 0x0;
3659         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3660         r->last_error                   = WERR_OK;
3661         r->status                       = nt_printq_status(status.status);
3662         r->enumerate_network_printers   = 0x0;
3663         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3664         r->processor_architecture       = 0x0;
3665         r->processor_level              = 0x6;          /* 6  ???*/
3666         r->ref_ic                       = 0;
3667         r->reserved2                    = 0;
3668         r->reserved3                    = 0;
3669
3670         return WERR_OK;
3671 }
3672
3673 /****************************************************************************
3674  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3675  should be valid upon entry
3676 ****************************************************************************/
3677
3678 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3679                                     struct spoolss_DeviceMode *r,
3680                                     const NT_DEVICEMODE *ntdevmode)
3681 {
3682         if (!r || !ntdevmode) {
3683                 return WERR_INVALID_PARAM;
3684         }
3685
3686         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3687         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3688
3689         r->specversion          = ntdevmode->specversion;
3690         r->driverversion        = ntdevmode->driverversion;
3691         r->size                 = ntdevmode->size;
3692         r->__driverextra_length = ntdevmode->driverextra;
3693         r->fields               = ntdevmode->fields;
3694
3695         r->orientation          = ntdevmode->orientation;
3696         r->papersize            = ntdevmode->papersize;
3697         r->paperlength          = ntdevmode->paperlength;
3698         r->paperwidth           = ntdevmode->paperwidth;
3699         r->scale                = ntdevmode->scale;
3700         r->copies               = ntdevmode->copies;
3701         r->defaultsource        = ntdevmode->defaultsource;
3702         r->printquality         = ntdevmode->printquality;
3703         r->color                = ntdevmode->color;
3704         r->duplex               = ntdevmode->duplex;
3705         r->yresolution          = ntdevmode->yresolution;
3706         r->ttoption             = ntdevmode->ttoption;
3707         r->collate              = ntdevmode->collate;
3708
3709         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3710         W_ERROR_HAVE_NO_MEMORY(r->formname);
3711
3712         /* all 0 below are values that have not been set in the old parsing/copy
3713          * function, maybe they should... - gd */
3714
3715         r->logpixels            = 0;
3716         r->bitsperpel           = 0;
3717         r->pelswidth            = 0;
3718         r->pelsheight           = 0;
3719         r->displayflags         = 0;
3720         r->displayfrequency     = 0;
3721         r->icmmethod            = ntdevmode->icmmethod;
3722         r->icmintent            = ntdevmode->icmintent;
3723         r->mediatype            = ntdevmode->mediatype;
3724         r->dithertype           = ntdevmode->dithertype;
3725         r->reserved1            = 0;
3726         r->reserved2            = 0;
3727         r->panningwidth         = 0;
3728         r->panningheight        = 0;
3729
3730         if (ntdevmode->nt_dev_private != NULL) {
3731                 r->driverextra_data = data_blob_talloc(mem_ctx,
3732                         ntdevmode->nt_dev_private,
3733                         ntdevmode->driverextra);
3734                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3735         }
3736
3737         return WERR_OK;
3738 }
3739
3740
3741 /****************************************************************************
3742  Create a spoolss_DeviceMode struct. Returns talloced memory.
3743 ****************************************************************************/
3744
3745 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3746                                               const char *servicename)
3747 {
3748         WERROR result;
3749         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3750         struct spoolss_DeviceMode *devmode = NULL;
3751
3752         DEBUG(7,("construct_dev_mode\n"));
3753
3754         DEBUGADD(8,("getting printer characteristics\n"));
3755
3756         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3757                 return NULL;
3758
3759         if (!printer->info_2->devmode) {
3760                 DEBUG(5, ("BONG! There was no device mode!\n"));
3761                 goto done;
3762         }
3763
3764         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3765         if (!devmode) {
3766                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3767                 goto done;
3768         }
3769
3770         DEBUGADD(8,("loading DEVICEMODE\n"));
3771
3772         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3773         if (!W_ERROR_IS_OK(result)) {
3774                 TALLOC_FREE(devmode);
3775         }
3776
3777 done:
3778         free_a_printer(&printer,2);
3779
3780         return devmode;
3781 }
3782
3783 /********************************************************************
3784  * construct_printer_info3
3785  * fill a spoolss_PrinterInfo3 struct
3786  ********************************************************************/
3787
3788 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3789                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3790                                       struct spoolss_PrinterInfo3 *r,
3791                                       int snum)
3792 {
3793         /* These are the components of the SD we are returning. */
3794
3795         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3796                 /* don't use talloc_steal() here unless you do a deep steal of all
3797                    the SEC_DESC members */
3798
3799                 r->secdesc = dup_sec_desc(mem_ctx,
3800                                           ntprinter->info_2->secdesc_buf->sd);
3801                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3802         }
3803
3804         return WERR_OK;
3805 }
3806
3807 /********************************************************************
3808  * construct_printer_info4
3809  * fill a spoolss_PrinterInfo4 struct
3810  ********************************************************************/
3811
3812 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3813                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3814                                       struct spoolss_PrinterInfo4 *r,
3815                                       int snum)
3816 {
3817         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3818         W_ERROR_HAVE_NO_MEMORY(r->printername);
3819         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3820         W_ERROR_HAVE_NO_MEMORY(r->servername);
3821
3822         r->attributes   = ntprinter->info_2->attributes;
3823
3824         return WERR_OK;
3825 }
3826
3827 /********************************************************************
3828  * construct_printer_info5
3829  * fill a spoolss_PrinterInfo5 struct
3830  ********************************************************************/
3831
3832 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3833                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3834                                       struct spoolss_PrinterInfo5 *r,
3835                                       int snum)
3836 {
3837         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3838         W_ERROR_HAVE_NO_MEMORY(r->printername);
3839         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3840         W_ERROR_HAVE_NO_MEMORY(r->portname);
3841
3842         r->attributes   = ntprinter->info_2->attributes;
3843
3844         /* these two are not used by NT+ according to MSDN */
3845
3846         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3847         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3848
3849         return WERR_OK;
3850 }
3851
3852 /********************************************************************
3853  * construct_printer_info_6
3854  * fill a spoolss_PrinterInfo6 struct
3855  ********************************************************************/
3856
3857 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3858                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3859                                       struct spoolss_PrinterInfo6 *r,
3860                                       int snum)
3861 {
3862         int count;
3863         print_status_struct status;
3864
3865         count = print_queue_length(snum, &status);
3866
3867         r->status = nt_printq_status(status.status);
3868
3869         return WERR_OK;
3870 }
3871
3872 /********************************************************************
3873  * construct_printer_info7
3874  * fill a spoolss_PrinterInfo7 struct
3875  ********************************************************************/
3876
3877 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3878                                       Printer_entry *print_hnd,
3879                                       struct spoolss_PrinterInfo7 *r,
3880                                       int snum)
3881 {
3882         struct GUID guid;
3883
3884         if (is_printer_published(print_hnd, snum, &guid)) {
3885                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3886                 r->action = DSPRINT_PUBLISH;
3887         } else {
3888                 r->guid = talloc_strdup(mem_ctx, "");
3889                 r->action = DSPRINT_UNPUBLISH;
3890         }
3891         W_ERROR_HAVE_NO_MEMORY(r->guid);
3892
3893         return WERR_OK;
3894 }
3895
3896 /********************************************************************
3897  * construct_printer_info8
3898  * fill a spoolss_PrinterInfo8 struct
3899  ********************************************************************/
3900
3901 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3902                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3903                                       struct spoolss_DeviceModeInfo *r,
3904                                       int snum)
3905 {
3906         struct spoolss_DeviceMode *devmode;
3907         WERROR result;
3908
3909         if (!ntprinter->info_2->devmode) {
3910                 r->devmode = NULL;
3911                 return WERR_OK;
3912         }
3913
3914         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3915         W_ERROR_HAVE_NO_MEMORY(devmode);
3916
3917         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
3918         if (!W_ERROR_IS_OK(result)) {
3919                 TALLOC_FREE(devmode);
3920                 return result;
3921         }
3922
3923         r->devmode      = devmode;
3924
3925         return WERR_OK;
3926 }
3927
3928
3929 /********************************************************************
3930  * construct_printer_info1
3931  * fill a spoolss_PrinterInfo1 struct
3932 ********************************************************************/
3933
3934 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3935                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3936                                       uint32_t flags,
3937                                       struct spoolss_PrinterInfo1 *r,
3938                                       int snum)
3939 {
3940         r->flags                = flags;
3941
3942         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3943                                                   ntprinter->info_2->printername,
3944                                                   ntprinter->info_2->drivername,
3945                                                   ntprinter->info_2->location);
3946         W_ERROR_HAVE_NO_MEMORY(r->description);
3947
3948         if (*ntprinter->info_2->comment == '\0') {
3949                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3950         } else {
3951                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3952         }
3953         W_ERROR_HAVE_NO_MEMORY(r->comment);
3954
3955         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3956         W_ERROR_HAVE_NO_MEMORY(r->name);
3957
3958         return WERR_OK;
3959 }
3960
3961 /********************************************************************
3962  * construct_printer_info2
3963  * fill a spoolss_PrinterInfo2 struct
3964 ********************************************************************/
3965
3966 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3967                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3968                                       struct spoolss_PrinterInfo2 *r,
3969                                       int snum)
3970 {
3971         int count;
3972
3973         print_status_struct status;
3974
3975         count = print_queue_length(snum, &status);
3976
3977         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3978         W_ERROR_HAVE_NO_MEMORY(r->servername);
3979         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3980         W_ERROR_HAVE_NO_MEMORY(r->printername);
3981         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3982         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3983         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3984         W_ERROR_HAVE_NO_MEMORY(r->portname);
3985         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3986         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3987
3988         if (*ntprinter->info_2->comment == '\0') {
3989                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3990         } else {
3991                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3992         }
3993         W_ERROR_HAVE_NO_MEMORY(r->comment);
3994
3995         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3996         W_ERROR_HAVE_NO_MEMORY(r->location);
3997         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3998         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3999         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4000         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4001         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4002         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4003         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4004         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4005
4006         r->attributes           = ntprinter->info_2->attributes;
4007
4008         r->priority             = ntprinter->info_2->priority;
4009         r->defaultpriority      = ntprinter->info_2->default_priority;
4010         r->starttime            = ntprinter->info_2->starttime;
4011         r->untiltime            = ntprinter->info_2->untiltime;
4012         r->status               = nt_printq_status(status.status);
4013         r->cjobs                = count;
4014         r->averageppm           = ntprinter->info_2->averageppm;
4015
4016         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4017         if (!r->devmode) {
4018                 DEBUG(8,("Returning NULL Devicemode!\n"));
4019         }
4020
4021         r->secdesc              = NULL;
4022
4023         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4024                 /* don't use talloc_steal() here unless you do a deep steal of all
4025                    the SEC_DESC members */
4026
4027                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4028         }
4029
4030         return WERR_OK;
4031 }
4032
4033 /********************************************************************
4034 ********************************************************************/
4035
4036 static bool snum_is_shared_printer(int snum)
4037 {
4038         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4039 }
4040
4041 /********************************************************************
4042  Spoolss_enumprinters.
4043 ********************************************************************/
4044
4045 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4046                                            uint32_t level,
4047                                            uint32_t flags,
4048                                            union spoolss_PrinterInfo **info_p,
4049                                            uint32_t *count_p)
4050 {
4051         int snum;
4052         int n_services = lp_numservices();
4053         union spoolss_PrinterInfo *info = NULL;
4054         uint32_t count = 0;
4055         WERROR result = WERR_OK;
4056
4057         *count_p = 0;
4058         *info_p = NULL;
4059
4060         for (snum = 0; snum < n_services; snum++) {
4061
4062                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4063
4064                 if (!snum_is_shared_printer(snum)) {
4065                         continue;
4066                 }
4067
4068                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4069                         lp_servicename(snum), snum));
4070
4071                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4072                                             union spoolss_PrinterInfo,
4073                                             count + 1);
4074                 if (!info) {
4075                         result = WERR_NOMEM;
4076                         goto out;
4077                 }
4078
4079                 result = get_a_printer(NULL, &ntprinter, 2,
4080                                        lp_const_servicename(snum));
4081                 if (!W_ERROR_IS_OK(result)) {
4082                         goto out;
4083                 }
4084
4085                 switch (level) {
4086                 case 0:
4087                         result = construct_printer_info0(info, ntprinter,
4088                                                          &info[count].info0, snum);
4089                         break;
4090                 case 1:
4091                         result = construct_printer_info1(info, ntprinter, flags,
4092                                                          &info[count].info1, snum);
4093                         break;
4094                 case 2:
4095                         result = construct_printer_info2(info, ntprinter,
4096                                                          &info[count].info2, snum);
4097                         break;
4098                 case 4:
4099                         result = construct_printer_info4(info, ntprinter,
4100                                                          &info[count].info4, snum);
4101                         break;
4102                 case 5:
4103                         result = construct_printer_info5(info, ntprinter,
4104                                                          &info[count].info5, snum);
4105                         break;
4106
4107                 default:
4108                         result = WERR_UNKNOWN_LEVEL;
4109                         free_a_printer(&ntprinter, 2);
4110                         goto out;
4111                 }
4112
4113                 free_a_printer(&ntprinter, 2);
4114                 if (!W_ERROR_IS_OK(result)) {
4115                         goto out;
4116                 }
4117
4118                 count++;
4119         }
4120
4121         *count_p = count;
4122         *info_p = info;
4123
4124  out:
4125         if (!W_ERROR_IS_OK(result)) {
4126                 TALLOC_FREE(info);
4127                 return result;
4128         }
4129
4130         *info_p = info;
4131
4132         return WERR_OK;
4133 }
4134
4135 /********************************************************************
4136  * handle enumeration of printers at level 0
4137  ********************************************************************/
4138
4139 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4140                                   uint32_t flags,
4141                                   const char *servername,
4142                                   union spoolss_PrinterInfo **info,
4143                                   uint32_t *count)
4144 {
4145         DEBUG(4,("enum_all_printers_info_0\n"));
4146
4147         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4148 }
4149
4150
4151 /********************************************************************
4152 ********************************************************************/
4153
4154 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4155                                        uint32_t flags,
4156                                        union spoolss_PrinterInfo **info,
4157                                        uint32_t *count)
4158 {
4159         DEBUG(4,("enum_all_printers_info_1\n"));
4160
4161         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4162 }
4163
4164 /********************************************************************
4165  enum_all_printers_info_1_local.
4166 *********************************************************************/
4167
4168 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4169                                              union spoolss_PrinterInfo **info,
4170                                              uint32_t *count)
4171 {
4172         DEBUG(4,("enum_all_printers_info_1_local\n"));
4173
4174         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4175 }
4176
4177 /********************************************************************
4178  enum_all_printers_info_1_name.
4179 *********************************************************************/
4180
4181 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4182                                             const char *name,
4183                                             union spoolss_PrinterInfo **info,
4184                                             uint32_t *count)
4185 {
4186         const char *s = name;
4187
4188         DEBUG(4,("enum_all_printers_info_1_name\n"));
4189
4190         if ((name[0] == '\\') && (name[1] == '\\')) {
4191                 s = name + 2;
4192         }
4193
4194         if (!is_myname_or_ipaddr(s)) {
4195                 return WERR_INVALID_NAME;
4196         }
4197
4198         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4199 }
4200
4201 /********************************************************************
4202  enum_all_printers_info_1_network.
4203 *********************************************************************/
4204
4205 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4206                                                const char *name,
4207                                                union spoolss_PrinterInfo **info,
4208                                                uint32_t *count)
4209 {
4210         const char *s = name;
4211
4212         DEBUG(4,("enum_all_printers_info_1_network\n"));
4213
4214         /* If we respond to a enum_printers level 1 on our name with flags
4215            set to PRINTER_ENUM_REMOTE with a list of printers then these
4216            printers incorrectly appear in the APW browse list.
4217            Specifically the printers for the server appear at the workgroup
4218            level where all the other servers in the domain are
4219            listed. Windows responds to this call with a
4220            WERR_CAN_NOT_COMPLETE so we should do the same. */
4221
4222         if (name[0] == '\\' && name[1] == '\\') {
4223                  s = name + 2;
4224         }
4225
4226         if (is_myname_or_ipaddr(s)) {
4227                  return WERR_CAN_NOT_COMPLETE;
4228         }
4229
4230         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4231 }
4232
4233 /********************************************************************
4234  * api_spoolss_enumprinters
4235  *
4236  * called from api_spoolss_enumprinters (see this to understand)
4237  ********************************************************************/
4238
4239 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4240                                        union spoolss_PrinterInfo **info,
4241                                        uint32_t *count)
4242 {
4243         DEBUG(4,("enum_all_printers_info_2\n"));
4244
4245         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4246 }
4247
4248 /********************************************************************
4249  * handle enumeration of printers at level 1
4250  ********************************************************************/
4251
4252 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4253                                   uint32_t flags,
4254                                   const char *name,
4255                                   union spoolss_PrinterInfo **info,
4256                                   uint32_t *count)
4257 {
4258         /* Not all the flags are equals */
4259
4260         if (flags & PRINTER_ENUM_LOCAL) {
4261                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4262         }
4263
4264         if (flags & PRINTER_ENUM_NAME) {
4265                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4266         }
4267
4268         if (flags & PRINTER_ENUM_NETWORK) {
4269                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4270         }
4271
4272         return WERR_OK; /* NT4sp5 does that */
4273 }
4274
4275 /********************************************************************
4276  * handle enumeration of printers at level 2
4277  ********************************************************************/
4278
4279 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4280                                   uint32_t flags,
4281                                   const char *servername,
4282                                   union spoolss_PrinterInfo **info,
4283                                   uint32_t *count)
4284 {
4285         if (flags & PRINTER_ENUM_LOCAL) {
4286                 return enum_all_printers_info_2(mem_ctx, info, count);
4287         }
4288
4289         if (flags & PRINTER_ENUM_NAME) {
4290                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4291                         return WERR_INVALID_NAME;
4292                 }
4293
4294                 return enum_all_printers_info_2(mem_ctx, info, count);
4295         }
4296
4297         if (flags & PRINTER_ENUM_REMOTE) {
4298                 return WERR_UNKNOWN_LEVEL;
4299         }
4300
4301         return WERR_OK;
4302 }
4303
4304 /********************************************************************
4305  * handle enumeration of printers at level 4
4306  ********************************************************************/
4307
4308 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4309                                   uint32_t flags,
4310                                   const char *servername,
4311                                   union spoolss_PrinterInfo **info,
4312                                   uint32_t *count)
4313 {
4314         DEBUG(4,("enum_all_printers_info_4\n"));
4315
4316         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4317 }
4318
4319
4320 /********************************************************************
4321  * handle enumeration of printers at level 5
4322  ********************************************************************/
4323
4324 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4325                                   uint32_t flags,
4326                                   const char *servername,
4327                                   union spoolss_PrinterInfo **info,
4328                                   uint32_t *count)
4329 {
4330         DEBUG(4,("enum_all_printers_info_5\n"));
4331
4332         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4333 }
4334
4335 /****************************************************************
4336  _spoolss_EnumPrinters
4337 ****************************************************************/
4338
4339 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4340                              struct spoolss_EnumPrinters *r)
4341 {
4342         const char *name;
4343         WERROR result;
4344
4345         /* that's an [in out] buffer */
4346
4347         if (!r->in.buffer && (r->in.offered != 0)) {
4348                 return WERR_INVALID_PARAM;
4349         }
4350
4351         DEBUG(4,("_spoolss_EnumPrinters\n"));
4352
4353         *r->out.needed = 0;
4354         *r->out.count = 0;
4355         *r->out.info = NULL;
4356
4357         /*
4358          * Level 1:
4359          *          flags==PRINTER_ENUM_NAME
4360          *           if name=="" then enumerates all printers
4361          *           if name!="" then enumerate the printer
4362          *          flags==PRINTER_ENUM_REMOTE
4363          *          name is NULL, enumerate printers
4364          * Level 2: name!="" enumerates printers, name can't be NULL
4365          * Level 3: doesn't exist
4366          * Level 4: does a local registry lookup
4367          * Level 5: same as Level 2
4368          */
4369
4370         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4371         W_ERROR_HAVE_NO_MEMORY(name);
4372
4373         switch (r->in.level) {
4374         case 0:
4375                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4376                                              r->out.info, r->out.count);
4377                 break;
4378         case 1:
4379                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4380                                              r->out.info, r->out.count);
4381                 break;
4382         case 2:
4383                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4384                                              r->out.info, r->out.count);
4385                 break;
4386         case 4:
4387                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4388                                              r->out.info, r->out.count);
4389                 break;
4390         case 5:
4391                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4392                                              r->out.info, r->out.count);
4393                 break;
4394         default:
4395                 return WERR_UNKNOWN_LEVEL;
4396         }
4397
4398         if (!W_ERROR_IS_OK(result)) {
4399                 return result;
4400         }
4401
4402         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4403                                                      spoolss_EnumPrinters, NULL,
4404                                                      *r->out.info, r->in.level,
4405                                                      *r->out.count);
4406         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4407         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4408
4409         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4410 }
4411
4412 /****************************************************************
4413  _spoolss_GetPrinter
4414 ****************************************************************/
4415
4416 WERROR _spoolss_GetPrinter(pipes_struct *p,
4417                            struct spoolss_GetPrinter *r)
4418 {
4419         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4420         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4421         WERROR result = WERR_OK;
4422
4423         int snum;
4424
4425         /* that's an [in out] buffer */
4426
4427         if (!r->in.buffer && (r->in.offered != 0)) {
4428                 return WERR_INVALID_PARAM;
4429         }
4430
4431         *r->out.needed = 0;
4432
4433         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4434                 return WERR_BADFID;
4435         }
4436
4437         result = get_a_printer(Printer, &ntprinter, 2,
4438                                lp_const_servicename(snum));
4439         if (!W_ERROR_IS_OK(result)) {
4440                 return result;
4441         }
4442
4443         switch (r->in.level) {
4444         case 0:
4445                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4446                                                  &r->out.info->info0, snum);
4447                 break;
4448         case 1:
4449                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4450                                                  PRINTER_ENUM_ICON8,
4451                                                  &r->out.info->info1, snum);
4452                 break;
4453         case 2:
4454                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4455                                                  &r->out.info->info2, snum);
4456                 break;
4457         case 3:
4458                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4459                                                  &r->out.info->info3, snum);
4460                 break;
4461         case 4:
4462                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4463                                                  &r->out.info->info4, snum);
4464                 break;
4465         case 5:
4466                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4467                                                  &r->out.info->info5, snum);
4468                 break;
4469         case 6:
4470                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4471                                                  &r->out.info->info6, snum);
4472                 break;
4473         case 7:
4474                 result = construct_printer_info7(p->mem_ctx, Printer,
4475                                                  &r->out.info->info7, snum);
4476                 break;
4477         case 8:
4478                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4479                                                  &r->out.info->info8, snum);
4480                 break;
4481         default:
4482                 result = WERR_UNKNOWN_LEVEL;
4483                 break;
4484         }
4485
4486         free_a_printer(&ntprinter, 2);
4487
4488         if (!W_ERROR_IS_OK(result)) {
4489                 TALLOC_FREE(r->out.info);
4490                 return result;
4491         }
4492
4493         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4494                                                r->out.info, r->in.level);
4495         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4496
4497         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4498 }
4499
4500 /********************************************************************
4501  ********************************************************************/
4502
4503 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4504                                                   const char **string_array,
4505                                                   const char *cservername)
4506 {
4507         int i, num_strings = 0;
4508         const char **array = NULL;
4509
4510         if (!string_array) {
4511                 return NULL;
4512         }
4513
4514         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4515
4516                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4517                                                   cservername, string_array[i]);
4518                 if (!str) {
4519                         TALLOC_FREE(array);
4520                         return NULL;
4521                 }
4522
4523
4524                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4525                         TALLOC_FREE(array);
4526                         return NULL;
4527                 }
4528         }
4529
4530         if (i > 0) {
4531                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4532                              &array, &num_strings);
4533         }
4534
4535         return array;
4536 }
4537
4538 /********************************************************************
4539  * fill a spoolss_DriverInfo1 struct
4540  ********************************************************************/
4541
4542 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4543                                         struct spoolss_DriverInfo1 *r,
4544                                         const union spoolss_DriverInfo *driver,
4545                                         const char *servername,
4546                                         const char *architecture)
4547 {
4548         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4549         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4550
4551         return WERR_OK;
4552 }
4553
4554 /********************************************************************
4555  * fill a spoolss_DriverInfo2 struct
4556  ********************************************************************/
4557
4558 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4559                                         struct spoolss_DriverInfo2 *r,
4560                                         const union spoolss_DriverInfo *driver,
4561                                         const char *servername)
4562
4563 {
4564         const char *cservername = canon_servername(servername);
4565
4566         r->version              = driver->info3.version;
4567
4568         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4569         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4570         r->architecture         = talloc_strdup(mem_ctx, driver->info3.architecture);
4571         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4572
4573         if (strlen(driver->info3.driver_path)) {
4574                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4575                                 cservername, driver->info3.driver_path);
4576         } else {
4577                 r->driver_path  = talloc_strdup(mem_ctx, "");
4578         }
4579         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4580
4581         if (strlen(driver->info3.data_file)) {
4582                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4583                                 cservername, driver->info3.data_file);
4584         } else {
4585                 r->data_file    = talloc_strdup(mem_ctx, "");
4586         }
4587         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4588
4589         if (strlen(driver->info3.config_file)) {
4590                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4591                                 cservername, driver->info3.config_file);
4592         } else {
4593                 r->config_file  = talloc_strdup(mem_ctx, "");
4594         }
4595         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4596
4597         return WERR_OK;
4598 }
4599
4600 /********************************************************************
4601  * fill a spoolss_DriverInfo3 struct
4602  ********************************************************************/
4603
4604 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4605                                         struct spoolss_DriverInfo3 *r,
4606                                         const union spoolss_DriverInfo *driver,
4607                                         const char *servername)
4608 {
4609         const char *cservername = canon_servername(servername);
4610
4611         r->version              = driver->info3.version;
4612
4613         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4614         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4615         r->architecture         = talloc_strdup(mem_ctx, driver->info3.architecture);
4616         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4617
4618         if (strlen(driver->info3.driver_path)) {
4619                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4620                                 cservername, driver->info3.driver_path);
4621         } else {
4622                 r->driver_path  = talloc_strdup(mem_ctx, "");
4623         }
4624         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4625
4626         if (strlen(driver->info3.data_file)) {
4627                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4628                                 cservername, driver->info3.data_file);
4629         } else {
4630                 r->data_file    = talloc_strdup(mem_ctx, "");
4631         }
4632         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4633
4634         if (strlen(driver->info3.config_file)) {
4635                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4636                                 cservername, driver->info3.config_file);
4637         } else {
4638                 r->config_file  = talloc_strdup(mem_ctx, "");
4639         }
4640         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4641
4642         if (strlen(driver->info3.help_file)) {
4643                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4644                                 cservername, driver->info3.help_file);
4645         } else {
4646                 r->help_file    = talloc_strdup(mem_ctx, "");
4647         }
4648         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4649
4650         r->monitor_name         = talloc_strdup(mem_ctx, driver->info3.monitor_name);
4651         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4652         r->default_datatype     = talloc_strdup(mem_ctx, driver->info3.default_datatype);
4653         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4654
4655         r->dependent_files = string_array_from_driver_info(mem_ctx,
4656                                                            driver->info3.dependent_files,
4657                                                            cservername);
4658         return WERR_OK;
4659 }
4660
4661 /********************************************************************
4662  * fill a spoolss_DriverInfo4 struct
4663  ********************************************************************/
4664
4665 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4666                                         struct spoolss_DriverInfo4 *r,
4667                                         const union spoolss_DriverInfo *driver,
4668                                         const char *servername)
4669 {
4670         const char *cservername = canon_servername(servername);
4671
4672         r->version              = driver->info3.version;
4673
4674         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4675         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4676         r->architecture         = talloc_strdup(mem_ctx, driver->info3.architecture);
4677         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4678
4679         if (strlen(driver->info3.driver_path)) {
4680                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4681                                 cservername, driver->info3.driver_path);
4682         } else {
4683                 r->driver_path  = talloc_strdup(mem_ctx, "");
4684         }
4685         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4686
4687         if (strlen(driver->info3.data_file)) {
4688                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4689                                 cservername, driver->info3.data_file);
4690         } else {
4691                 r->data_file    = talloc_strdup(mem_ctx, "");
4692         }
4693         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4694
4695         if (strlen(driver->info3.config_file)) {
4696                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4697                                 cservername, driver->info3.config_file);
4698         } else {
4699                 r->config_file  = talloc_strdup(mem_ctx, "");
4700         }
4701         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4702
4703         if (strlen(driver->info3.help_file)) {
4704                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4705                                 cservername, driver->info3.help_file);
4706         } else {
4707                 r->help_file    = talloc_strdup(mem_ctx, "");
4708         }
4709         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4710
4711         r->dependent_files = string_array_from_driver_info(mem_ctx,
4712                                                            driver->info3.dependent_files,
4713                                                            cservername);
4714
4715
4716         r->monitor_name         = talloc_strdup(mem_ctx, driver->info3.monitor_name);
4717         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4718         r->default_datatype     = talloc_strdup(mem_ctx, driver->info3.default_datatype);
4719         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4720
4721         r->previous_names = string_array_from_driver_info(mem_ctx,
4722                                                           NULL,
4723                                                           cservername);
4724
4725         return WERR_OK;
4726 }
4727
4728 /********************************************************************
4729  * fill a spoolss_DriverInfo5 struct
4730  ********************************************************************/
4731
4732 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4733                                         struct spoolss_DriverInfo5 *r,
4734                                         const union spoolss_DriverInfo *driver,
4735                                         const char *servername)
4736 {
4737         const char *cservername = canon_servername(servername);
4738
4739         r->version              = driver->info3.version;
4740
4741         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4742         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4743         r->architecture         = talloc_strdup(mem_ctx, driver->info3.architecture);
4744         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4745
4746         if (strlen(driver->info3.driver_path)) {
4747                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4748                                 cservername, driver->info3.driver_path);
4749         } else {
4750                 r->driver_path  = talloc_strdup(mem_ctx, "");
4751         }
4752         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4753
4754         if (strlen(driver->info3.data_file)) {
4755                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4756                                 cservername, driver->info3.data_file);
4757         } else {
4758                 r->data_file    = talloc_strdup(mem_ctx, "");
4759         }
4760         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4761
4762         if (strlen(driver->info3.config_file)) {
4763                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4764                                 cservername, driver->info3.config_file);
4765         } else {
4766                 r->config_file  = talloc_strdup(mem_ctx, "");
4767         }
4768         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4769
4770         r->driver_attributes    = 0;
4771         r->config_version       = 0;
4772         r->driver_version       = 0;
4773
4774         return WERR_OK;
4775 }
4776 /********************************************************************
4777  * fill a spoolss_DriverInfo6 struct
4778  ********************************************************************/
4779
4780 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4781                                         struct spoolss_DriverInfo6 *r,
4782                                         const union spoolss_DriverInfo *driver,
4783                                         const char *servername)
4784 {
4785         const char *cservername = canon_servername(servername);
4786
4787         r->version              = driver->info3.version;
4788
4789         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4790         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4791         r->architecture         = talloc_strdup(mem_ctx, driver->info3.architecture);
4792         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4793
4794         if (strlen(driver->info3.driver_path)) {
4795                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4796                                 cservername, driver->info3.driver_path);
4797         } else {
4798                 r->driver_path  = talloc_strdup(mem_ctx, "");
4799         }
4800         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4801
4802         if (strlen(driver->info3.data_file)) {
4803                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4804                                 cservername, driver->info3.data_file);
4805         } else {
4806                 r->data_file    = talloc_strdup(mem_ctx, "");
4807         }
4808         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4809
4810         if (strlen(driver->info3.config_file)) {
4811                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4812                                 cservername, driver->info3.config_file);
4813         } else {
4814                 r->config_file  = talloc_strdup(mem_ctx, "");
4815         }
4816         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4817
4818         if (strlen(driver->info3.help_file)) {
4819                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4820                                 cservername, driver->info3.help_file);
4821         } else {
4822                 r->help_file    = talloc_strdup(mem_ctx, "");
4823         }
4824         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4825
4826         r->monitor_name         = talloc_strdup(mem_ctx, driver->info3.monitor_name);
4827         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4828         r->default_datatype     = talloc_strdup(mem_ctx, driver->info3.default_datatype);
4829         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4830
4831         r->dependent_files = string_array_from_driver_info(mem_ctx,
4832                                                            driver->info3.dependent_files,
4833                                                            cservername);
4834         r->previous_names = string_array_from_driver_info(mem_ctx,
4835                                                           NULL,
4836                                                           cservername);
4837
4838         r->driver_date          = 0;
4839         r->driver_version       = 0;
4840
4841         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
4842         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4843         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
4844         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4845         r->hardware_id          = talloc_strdup(mem_ctx, "");
4846         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4847         r->provider             = talloc_strdup(mem_ctx, "");
4848         W_ERROR_HAVE_NO_MEMORY(r->provider);
4849
4850         return WERR_OK;
4851 }
4852
4853 /********************************************************************
4854  ********************************************************************/
4855
4856 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4857                                           struct spoolss_DriverFileInfo *r,
4858                                           const char *cservername,
4859                                           const char *file_name,
4860                                           enum spoolss_DriverFileType file_type,
4861                                           uint32_t file_version)
4862 {
4863         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4864                                           cservername, file_name);
4865         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4866         r->file_type    = file_type;
4867         r->file_version = file_version;
4868
4869         return WERR_OK;
4870 }
4871
4872 /********************************************************************
4873  ********************************************************************/
4874
4875 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4876                                                  const union spoolss_DriverInfo *driver,
4877                                                  const char *cservername,
4878                                                  struct spoolss_DriverFileInfo **info_p,
4879                                                  uint32_t *count_p)
4880 {
4881         struct spoolss_DriverFileInfo *info = NULL;
4882         uint32_t count = 0;
4883         WERROR result;
4884         uint32_t i;
4885
4886         *info_p = NULL;
4887         *count_p = 0;
4888
4889         if (strlen(driver->info3.driver_path)) {
4890                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4891                                             struct spoolss_DriverFileInfo,
4892                                             count + 1);
4893                 W_ERROR_HAVE_NO_MEMORY(info);
4894                 result = fill_spoolss_DriverFileInfo(info,
4895                                                      &info[count],
4896                                                      cservername,
4897                                                      driver->info3.driver_path,
4898                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4899                                                      0);
4900                 W_ERROR_NOT_OK_RETURN(result);
4901                 count++;
4902         }
4903
4904         if (strlen(driver->info3.config_file)) {
4905                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4906                                             struct spoolss_DriverFileInfo,
4907                                             count + 1);
4908                 W_ERROR_HAVE_NO_MEMORY(info);
4909                 result = fill_spoolss_DriverFileInfo(info,
4910                                                      &info[count],
4911                                                      cservername,
4912                                                      driver->info3.config_file,
4913                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4914                                                      0);
4915                 W_ERROR_NOT_OK_RETURN(result);
4916                 count++;
4917         }
4918
4919         if (strlen(driver->info3.data_file)) {
4920                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4921                                             struct spoolss_DriverFileInfo,
4922                                             count + 1);
4923                 W_ERROR_HAVE_NO_MEMORY(info);
4924                 result = fill_spoolss_DriverFileInfo(info,
4925                                                      &info[count],
4926                                                      cservername,
4927                                                      driver->info3.data_file,
4928                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4929                                                      0);
4930                 W_ERROR_NOT_OK_RETURN(result);
4931                 count++;
4932         }
4933
4934         if (strlen(driver->info3.help_file)) {
4935                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4936                                             struct spoolss_DriverFileInfo,
4937                                             count + 1);
4938                 W_ERROR_HAVE_NO_MEMORY(info);
4939                 result = fill_spoolss_DriverFileInfo(info,
4940                                                      &info[count],
4941                                                      cservername,
4942                                                      driver->info3.help_file,
4943                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4944                                                      0);
4945                 W_ERROR_NOT_OK_RETURN(result);
4946                 count++;
4947         }
4948
4949         for (i=0; driver->info3.dependent_files[i] && driver->info3.dependent_files[i][0] != '\0'; i++) {
4950                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4951                                             struct spoolss_DriverFileInfo,
4952                                             count + 1);
4953                 W_ERROR_HAVE_NO_MEMORY(info);
4954                 result = fill_spoolss_DriverFileInfo(info,
4955                                                      &info[count],
4956                                                      cservername,
4957                                                      driver->info3.dependent_files[i],
4958                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4959                                                      0);
4960                 W_ERROR_NOT_OK_RETURN(result);
4961                 count++;
4962         }
4963
4964         *info_p = info;
4965         *count_p = count;
4966
4967         return WERR_OK;
4968 }
4969
4970 /********************************************************************
4971  * fill a spoolss_DriverInfo101 sttruct
4972  ********************************************************************/
4973
4974 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4975                                           struct spoolss_DriverInfo101 *r,
4976                                           const union spoolss_DriverInfo *driver,
4977                                           const char *servername)
4978 {
4979         const char *cservername = canon_servername(servername);
4980         WERROR result;
4981
4982         r->version              = driver->info3.version;
4983
4984         r->driver_name          = talloc_strdup(mem_ctx, driver->info3.driver_name);
4985         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4986         r->architecture         = talloc_strdup(mem_ctx, driver->info3.architecture);
4987         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4988
4989         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4990                                                     cservername,
4991                                                     &r->file_info,
4992                                                     &r->file_count);
4993         if (!W_ERROR_IS_OK(result)) {
4994                 return result;
4995         }
4996
4997         r->monitor_name         = talloc_strdup(mem_ctx, driver->info3.monitor_name);
4998         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4999
5000         r->default_datatype     = talloc_strdup(mem_ctx, driver->info3.default_datatype);
5001         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5002
5003         r->previous_names = string_array_from_driver_info(mem_ctx,
5004                                                           NULL,
5005                                                           cservername);
5006         r->driver_date          = 0;
5007         r->driver_version       = 0;
5008
5009         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5010         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5011         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5012         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5013         r->hardware_id          = talloc_strdup(mem_ctx, "");
5014         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5015         r->provider             = talloc_strdup(mem_ctx, "");
5016         W_ERROR_HAVE_NO_MEMORY(r->provider);
5017
5018         return WERR_OK;
5019 }
5020
5021 /********************************************************************
5022  * construct_printer_driver_info_1
5023  ********************************************************************/
5024
5025 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5026                                               struct spoolss_DriverInfo1 *r,
5027                                               int snum,
5028                                               const char *servername,
5029                                               const char *architecture,
5030                                               uint32_t version)
5031 {
5032         NT_PRINTER_INFO_LEVEL *printer = NULL;
5033         union spoolss_DriverInfo *driver;
5034         WERROR result;
5035
5036         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5037                 return WERR_INVALID_PRINTER_NAME;
5038
5039         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
5040                 free_a_printer(&printer, 2);
5041                 return WERR_UNKNOWN_PRINTER_DRIVER;
5042         }
5043
5044         result = fill_printer_driver_info1(mem_ctx, r, driver, servername, architecture);
5045
5046         free_a_printer_driver(driver);
5047         free_a_printer(&printer,2);
5048
5049         return result;
5050 }
5051
5052 /********************************************************************
5053  * construct_printer_driver_info_2
5054  * fill a printer_info_2 struct
5055  ********************************************************************/
5056
5057 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5058                                               struct spoolss_DriverInfo2 *r,
5059                                               int snum,
5060                                               const char *servername,
5061                                               const char *architecture,
5062                                               uint32_t version)
5063 {
5064         NT_PRINTER_INFO_LEVEL *printer = NULL;
5065         union spoolss_DriverInfo *driver;
5066         WERROR result;
5067
5068         ZERO_STRUCT(printer);
5069
5070         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5071                 return WERR_INVALID_PRINTER_NAME;
5072
5073         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
5074                 free_a_printer(&printer, 2);
5075                 return WERR_UNKNOWN_PRINTER_DRIVER;
5076         }
5077
5078         result = fill_printer_driver_info2(mem_ctx, r, driver, servername);
5079
5080         free_a_printer_driver(driver);
5081         free_a_printer(&printer,2);
5082
5083         return result;
5084 }
5085
5086 /********************************************************************
5087  * construct_printer_info_3
5088  * fill a printer_info_3 struct
5089  ********************************************************************/
5090
5091 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5092                                               struct spoolss_DriverInfo3 *r,
5093                                               int snum,
5094                                               const char *servername,
5095                                               const char *architecture,
5096                                               uint32_t version)
5097 {
5098         NT_PRINTER_INFO_LEVEL *printer = NULL;
5099         union spoolss_DriverInfo *driver;
5100         WERROR status;
5101         ZERO_STRUCT(driver);
5102
5103         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5104         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5105         if (!W_ERROR_IS_OK(status))
5106                 return WERR_INVALID_PRINTER_NAME;
5107
5108         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5109         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5110
5111 #if 0   /* JERRY */
5112
5113         /*
5114          * I put this code in during testing.  Helpful when commenting out the
5115          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5116          * as win2k always queries the driver using an infor level of 6.
5117          * I've left it in (but ifdef'd out) because I'll probably
5118          * use it in experimentation again in the future.   --jerry 22/01/2002
5119          */
5120
5121         if (!W_ERROR_IS_OK(status)) {
5122                 /*
5123                  * Is this a W2k client ?
5124                  */
5125                 if (version == 3) {
5126                         /* Yes - try again with a WinNT driver. */
5127                         version = 2;
5128                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5129                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5130                 }
5131 #endif
5132
5133                 if (!W_ERROR_IS_OK(status)) {
5134                         free_a_printer(&printer,2);
5135                         return WERR_UNKNOWN_PRINTER_DRIVER;
5136                 }
5137
5138 #if 0   /* JERRY */
5139         }
5140 #endif
5141
5142
5143         status = fill_printer_driver_info3(mem_ctx, r, driver, servername);
5144
5145         free_a_printer_driver(driver);
5146         free_a_printer(&printer,2);
5147
5148         return status;
5149 }
5150
5151 /********************************************************************
5152  * construct_printer_info_6
5153  * fill a printer_info_6 struct
5154  ********************************************************************/
5155
5156 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5157                                               struct spoolss_DriverInfo6 *r,
5158                                               int snum,
5159                                               const char *servername,
5160                                               const char *architecture,
5161                                               uint32_t version)
5162 {
5163         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5164         union spoolss_DriverInfo *driver;
5165         WERROR                          status;
5166
5167         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5168
5169         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5170
5171         if (!W_ERROR_IS_OK(status))
5172                 return WERR_INVALID_PRINTER_NAME;
5173
5174         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5175
5176         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5177
5178         if (!W_ERROR_IS_OK(status))
5179         {
5180                 /*
5181                  * Is this a W2k client ?
5182                  */
5183
5184                 if (version < 3) {
5185                         free_a_printer(&printer,2);
5186                         return WERR_UNKNOWN_PRINTER_DRIVER;
5187                 }
5188
5189                 /* Yes - try again with a WinNT driver. */
5190                 version = 2;
5191                 status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5192                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5193                 if (!W_ERROR_IS_OK(status)) {
5194                         free_a_printer(&printer,2);
5195                         return WERR_UNKNOWN_PRINTER_DRIVER;
5196                 }
5197         }
5198
5199         status = fill_printer_driver_info6(mem_ctx, r, driver, servername);
5200
5201         free_a_printer(&printer,2);
5202         free_a_printer_driver(driver);
5203
5204         return status;
5205 }
5206
5207 /********************************************************************
5208  * construct_printer_info_101
5209  * fill a printer_info_101 struct
5210  ********************************************************************/
5211
5212 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5213                                                 struct spoolss_DriverInfo101 *r,
5214                                                 int snum,
5215                                                 const char *servername,
5216                                                 const char *architecture,
5217                                                 uint32_t version)
5218 {
5219         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5220         union spoolss_DriverInfo *driver;
5221         WERROR                          result;
5222
5223         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5224
5225         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5226                 win_errstr(result)));
5227
5228         if (!W_ERROR_IS_OK(result)) {
5229                 return WERR_INVALID_PRINTER_NAME;
5230         }
5231
5232         result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5233                                       architecture, version);
5234
5235         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5236                 win_errstr(result)));
5237
5238         if (!W_ERROR_IS_OK(result)) {
5239                 /*
5240                  * Is this a W2k client ?
5241                  */
5242
5243                 if (version < 3) {
5244                         free_a_printer(&printer, 2);
5245                         return WERR_UNKNOWN_PRINTER_DRIVER;
5246                 }
5247
5248                 /* Yes - try again with a WinNT driver. */
5249                 version = 2;
5250                 result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5251                                               architecture, version);
5252                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5253                         win_errstr(result)));
5254                 if (!W_ERROR_IS_OK(result)) {
5255                         free_a_printer(&printer, 2);
5256                         return WERR_UNKNOWN_PRINTER_DRIVER;
5257                 }
5258         }
5259
5260         result = fill_printer_driver_info101(mem_ctx, r, driver, servername);
5261
5262         free_a_printer(&printer, 2);
5263         free_a_printer_driver(driver);
5264
5265         return result;
5266 }
5267
5268 /****************************************************************
5269  _spoolss_GetPrinterDriver2
5270 ****************************************************************/
5271
5272 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5273                                   struct spoolss_GetPrinterDriver2 *r)
5274 {
5275         Printer_entry *printer;
5276         WERROR result;
5277
5278         const char *servername;
5279         int snum;
5280
5281         /* that's an [in out] buffer */
5282
5283         if (!r->in.buffer && (r->in.offered != 0)) {
5284                 return WERR_INVALID_PARAM;
5285         }
5286
5287         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5288
5289         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5290                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5291                 return WERR_INVALID_PRINTER_NAME;
5292         }
5293
5294         *r->out.needed = 0;
5295         *r->out.server_major_version = 0;
5296         *r->out.server_minor_version = 0;
5297
5298         servername = get_server_name(printer);
5299
5300         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5301                 return WERR_BADFID;
5302         }
5303
5304         switch (r->in.level) {
5305         case 1:
5306                 result = construct_printer_driver_info_1(p->mem_ctx,
5307                                                          &r->out.info->info1,
5308                                                          snum,
5309                                                          servername,
5310                                                          r->in.architecture,
5311                                                          r->in.client_major_version);
5312                 break;
5313         case 2:
5314                 result = construct_printer_driver_info_2(p->mem_ctx,
5315                                                          &r->out.info->info2,
5316                                                          snum,
5317                                                          servername,
5318                                                          r->in.architecture,
5319                                                          r->in.client_major_version);
5320                 break;
5321         case 3:
5322                 result = construct_printer_driver_info_3(p->mem_ctx,
5323                                                          &r->out.info->info3,
5324                                                          snum,
5325                                                          servername,
5326                                                          r->in.architecture,
5327                                                          r->in.client_major_version);
5328                 break;
5329         case 6:
5330                 result = construct_printer_driver_info_6(p->mem_ctx,
5331                                                          &r->out.info->info6,
5332                                                          snum,
5333                                                          servername,
5334                                                          r->in.architecture,
5335                                                          r->in.client_major_version);
5336                 break;
5337         case 101:
5338                 result = construct_printer_driver_info_101(p->mem_ctx,
5339                                                            &r->out.info->info101,
5340                                                            snum,
5341                                                            servername,
5342                                                            r->in.architecture,
5343                                                            r->in.client_major_version);
5344                 break;
5345         default:
5346                 result = WERR_UNKNOWN_LEVEL;
5347                 break;
5348         }
5349
5350         if (!W_ERROR_IS_OK(result)) {
5351                 TALLOC_FREE(r->out.info);
5352                 return result;
5353         }
5354
5355         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5356                                                r->out.info, r->in.level);
5357         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5358
5359         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5360 }
5361
5362
5363 /****************************************************************
5364  _spoolss_StartPagePrinter
5365 ****************************************************************/
5366
5367 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5368                                  struct spoolss_StartPagePrinter *r)
5369 {
5370         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5371
5372         if (!Printer) {
5373                 DEBUG(3,("_spoolss_StartPagePrinter: "
5374                         "Error in startpageprinter printer handle\n"));
5375                 return WERR_BADFID;
5376         }
5377
5378         Printer->page_started = true;
5379         return WERR_OK;
5380 }
5381
5382 /****************************************************************
5383  _spoolss_EndPagePrinter
5384 ****************************************************************/
5385
5386 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5387                                struct spoolss_EndPagePrinter *r)
5388 {
5389         int snum;
5390
5391         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5392
5393         if (!Printer) {
5394                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5395                         OUR_HANDLE(r->in.handle)));
5396                 return WERR_BADFID;
5397         }
5398
5399         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5400                 return WERR_BADFID;
5401
5402         Printer->page_started = false;
5403         print_job_endpage(snum, Printer->jobid);
5404
5405         return WERR_OK;
5406 }
5407
5408 /****************************************************************
5409  _spoolss_StartDocPrinter
5410 ****************************************************************/
5411
5412 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5413                                 struct spoolss_StartDocPrinter *r)
5414 {
5415         struct spoolss_DocumentInfo1 *info_1;
5416         int snum;
5417         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5418
5419         if (!Printer) {
5420                 DEBUG(2,("_spoolss_StartDocPrinter: "
5421                         "Invalid handle (%s:%u:%u)\n",
5422                         OUR_HANDLE(r->in.handle)));
5423                 return WERR_BADFID;
5424         }
5425
5426         if (r->in.level != 1) {
5427                 return WERR_UNKNOWN_LEVEL;
5428         }
5429
5430         info_1 = r->in.info.info1;
5431
5432         /*
5433          * a nice thing with NT is it doesn't listen to what you tell it.
5434          * when asked to send _only_ RAW datas, it tries to send datas
5435          * in EMF format.
5436          *
5437          * So I add checks like in NT Server ...
5438          */
5439
5440         if (info_1->datatype) {
5441                 if (strcmp(info_1->datatype, "RAW") != 0) {
5442                         *r->out.job_id = 0;
5443                         return WERR_INVALID_DATATYPE;
5444                 }
5445         }
5446
5447         /* get the share number of the printer */
5448         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5449                 return WERR_BADFID;
5450         }
5451
5452         Printer->jobid = print_job_start(p->server_info, snum,
5453                                          info_1->document_name,
5454                                          Printer->nt_devmode);
5455
5456         /* An error occured in print_job_start() so return an appropriate
5457            NT error code. */
5458
5459         if (Printer->jobid == -1) {
5460                 return map_werror_from_unix(errno);
5461         }
5462
5463         Printer->document_started = true;
5464         *r->out.job_id = Printer->jobid;
5465
5466         return WERR_OK;
5467 }
5468
5469 /****************************************************************
5470  _spoolss_EndDocPrinter
5471 ****************************************************************/
5472
5473 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5474                               struct spoolss_EndDocPrinter *r)
5475 {
5476         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5477         int snum;
5478
5479         if (!Printer) {
5480                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5481                         OUR_HANDLE(r->in.handle)));
5482                 return WERR_BADFID;
5483         }
5484
5485         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5486                 return WERR_BADFID;
5487         }
5488
5489         Printer->document_started = false;
5490         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5491         /* error codes unhandled so far ... */
5492
5493         return WERR_OK;
5494 }
5495
5496 /****************************************************************
5497  _spoolss_WritePrinter
5498 ****************************************************************/
5499
5500 WERROR _spoolss_WritePrinter(pipes_struct *p,
5501                              struct spoolss_WritePrinter *r)
5502 {
5503         uint32_t buffer_written;
5504         int snum;
5505         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5506
5507         if (!Printer) {
5508                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5509                         OUR_HANDLE(r->in.handle)));
5510                 *r->out.num_written = r->in._data_size;
5511                 return WERR_BADFID;
5512         }
5513
5514         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5515                 return WERR_BADFID;
5516
5517         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5518                                                    (const char *)r->in.data.data,
5519                                                    (SMB_OFF_T)-1,
5520                                                    (size_t)r->in._data_size);
5521         if (buffer_written == (uint32_t)-1) {
5522                 *r->out.num_written = 0;
5523                 if (errno == ENOSPC)
5524                         return WERR_NO_SPOOL_SPACE;
5525                 else
5526                         return WERR_ACCESS_DENIED;
5527         }
5528
5529         *r->out.num_written = r->in._data_size;
5530
5531         return WERR_OK;
5532 }
5533
5534 /********************************************************************
5535  * api_spoolss_getprinter
5536  * called from the spoolss dispatcher
5537  *
5538  ********************************************************************/
5539
5540 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5541                               pipes_struct *p)
5542 {
5543         int snum;
5544         WERROR errcode = WERR_BADFUNC;
5545         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5546
5547         if (!Printer) {
5548                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5549                         OUR_HANDLE(handle)));
5550                 return WERR_BADFID;
5551         }
5552
5553         if (!get_printer_snum(p, handle, &snum, NULL))
5554                 return WERR_BADFID;
5555
5556         switch (command) {
5557         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5558                 errcode = print_queue_pause(p->server_info, snum);
5559                 break;
5560         case SPOOLSS_PRINTER_CONTROL_RESUME:
5561         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5562                 errcode = print_queue_resume(p->server_info, snum);
5563                 break;
5564         case SPOOLSS_PRINTER_CONTROL_PURGE:
5565                 errcode = print_queue_purge(p->server_info, snum);
5566                 break;
5567         default:
5568                 return WERR_UNKNOWN_LEVEL;
5569         }
5570
5571         return errcode;
5572 }
5573
5574
5575 /****************************************************************
5576  _spoolss_AbortPrinter
5577  * From MSDN: "Deletes printer's spool file if printer is configured
5578  * for spooling"
5579 ****************************************************************/
5580
5581 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5582                              struct spoolss_AbortPrinter *r)
5583 {
5584         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5585         int             snum;
5586         WERROR          errcode = WERR_OK;
5587
5588         if (!Printer) {
5589                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5590                         OUR_HANDLE(r->in.handle)));
5591                 return WERR_BADFID;
5592         }
5593
5594         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5595                 return WERR_BADFID;
5596
5597         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5598
5599         return errcode;
5600 }
5601
5602 /********************************************************************
5603  * called by spoolss_api_setprinter
5604  * when updating a printer description
5605  ********************************************************************/
5606
5607 static WERROR update_printer_sec(struct policy_handle *handle,
5608                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5609 {
5610         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5611         WERROR result;
5612         int snum;
5613
5614         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5615
5616         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5617                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5618                          OUR_HANDLE(handle)));
5619
5620                 result = WERR_BADFID;
5621                 goto done;
5622         }
5623
5624         if (!secdesc_ctr) {
5625                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5626                 result = WERR_INVALID_PARAM;
5627                 goto done;
5628         }
5629
5630         /* Check the user has permissions to change the security
5631            descriptor.  By experimentation with two NT machines, the user
5632            requires Full Access to the printer to change security
5633            information. */
5634
5635         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5636                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5637                 result = WERR_ACCESS_DENIED;
5638                 goto done;
5639         }
5640
5641         /* NT seems to like setting the security descriptor even though
5642            nothing may have actually changed. */
5643
5644         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5645                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5646                 result = WERR_BADFID;
5647                 goto done;
5648         }
5649
5650         if (DEBUGLEVEL >= 10) {
5651                 SEC_ACL *the_acl;
5652                 int i;
5653
5654                 the_acl = old_secdesc_ctr->sd->dacl;
5655                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5656                            PRINTERNAME(snum), the_acl->num_aces));
5657
5658                 for (i = 0; i < the_acl->num_aces; i++) {
5659                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5660                                            &the_acl->aces[i].trustee),
5661                                   the_acl->aces[i].access_mask));
5662                 }
5663
5664                 the_acl = secdesc_ctr->sd->dacl;
5665
5666                 if (the_acl) {
5667                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5668                                    PRINTERNAME(snum), the_acl->num_aces));
5669
5670                         for (i = 0; i < the_acl->num_aces; i++) {
5671                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5672                                                    &the_acl->aces[i].trustee),
5673                                            the_acl->aces[i].access_mask));
5674                         }
5675                 } else {
5676                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5677                 }
5678         }
5679
5680         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5681         if (!new_secdesc_ctr) {
5682                 result = WERR_NOMEM;
5683                 goto done;
5684         }
5685
5686         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5687                 result = WERR_OK;
5688                 goto done;
5689         }
5690
5691         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5692
5693  done:
5694
5695         return result;
5696 }
5697
5698 /********************************************************************
5699  Canonicalize printer info from a client
5700
5701  ATTN: It does not matter what we set the servername to hear
5702  since we do the necessary work in get_a_printer() to set it to
5703  the correct value based on what the client sent in the
5704  _spoolss_open_printer_ex().
5705  ********************************************************************/
5706
5707 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5708 {
5709         fstring printername;
5710         const char *p;
5711
5712         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5713                 "portname=%s drivername=%s comment=%s location=%s\n",
5714                 info->servername, info->printername, info->sharename,
5715                 info->portname, info->drivername, info->comment, info->location));
5716
5717         /* we force some elements to "correct" values */
5718         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5719         fstrcpy(info->sharename, lp_servicename(snum));
5720
5721         /* check to see if we allow printername != sharename */
5722
5723         if ( lp_force_printername(snum) ) {
5724                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5725                         global_myname(), info->sharename );
5726         } else {
5727
5728                 /* make sure printername is in \\server\printername format */
5729
5730                 fstrcpy( printername, info->printername );
5731                 p = printername;
5732                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5733                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5734                                 p++;
5735                 }
5736
5737                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5738                          global_myname(), p );
5739         }
5740
5741         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5742         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5743
5744
5745
5746         return true;
5747 }
5748
5749 /****************************************************************************
5750 ****************************************************************************/
5751
5752 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5753 {
5754         char *cmd = lp_addport_cmd();
5755         char *command = NULL;
5756         int ret;
5757         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5758         bool is_print_op = false;
5759
5760         if ( !*cmd ) {
5761                 return WERR_ACCESS_DENIED;
5762         }
5763
5764         command = talloc_asprintf(ctx,
5765                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5766         if (!command) {
5767                 return WERR_NOMEM;
5768         }
5769
5770         if ( token )
5771                 is_print_op = user_has_privileges( token, &se_printop );
5772
5773         DEBUG(10,("Running [%s]\n", command));
5774
5775         /********* BEGIN SePrintOperatorPrivilege **********/
5776
5777         if ( is_print_op )
5778                 become_root();
5779
5780         ret = smbrun(command, NULL);
5781
5782         if ( is_print_op )
5783                 unbecome_root();
5784
5785         /********* END SePrintOperatorPrivilege **********/
5786
5787         DEBUGADD(10,("returned [%d]\n", ret));
5788
5789         TALLOC_FREE(command);
5790
5791         if ( ret != 0 ) {
5792                 return WERR_ACCESS_DENIED;
5793         }
5794
5795         return WERR_OK;
5796 }
5797
5798 /****************************************************************************
5799 ****************************************************************************/
5800
5801 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5802 {
5803         char *cmd = lp_addprinter_cmd();
5804         char **qlines;
5805         char *command = NULL;
5806         int numlines;
5807         int ret;
5808         int fd;
5809         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5810         bool is_print_op = false;
5811         char *remote_machine = talloc_strdup(ctx, "%m");
5812
5813         if (!remote_machine) {
5814                 return false;
5815         }
5816         remote_machine = talloc_sub_basic(ctx,
5817                                 current_user_info.smb_name,
5818                                 current_user_info.domain,
5819                                 remote_machine);
5820         if (!remote_machine) {
5821                 return false;
5822         }
5823
5824         command = talloc_asprintf(ctx,
5825                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5826                         cmd, printer->info_2->printername, printer->info_2->sharename,
5827                         printer->info_2->portname, printer->info_2->drivername,
5828                         printer->info_2->location, printer->info_2->comment, remote_machine);
5829         if (!command) {
5830                 return false;
5831         }
5832
5833         if ( token )
5834                 is_print_op = user_has_privileges( token, &se_printop );
5835
5836         DEBUG(10,("Running [%s]\n", command));
5837
5838         /********* BEGIN SePrintOperatorPrivilege **********/
5839
5840         if ( is_print_op )
5841                 become_root();
5842
5843         if ( (ret = smbrun(command, &fd)) == 0 ) {
5844                 /* Tell everyone we updated smb.conf. */
5845                 message_send_all(smbd_messaging_context(),
5846                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5847         }
5848
5849         if ( is_print_op )
5850                 unbecome_root();
5851
5852         /********* END SePrintOperatorPrivilege **********/
5853
5854         DEBUGADD(10,("returned [%d]\n", ret));
5855
5856         TALLOC_FREE(command);
5857         TALLOC_FREE(remote_machine);
5858
5859         if ( ret != 0 ) {
5860                 if (fd != -1)
5861                         close(fd);
5862                 return false;
5863         }
5864
5865         /* reload our services immediately */
5866         become_root();
5867         reload_services(false);
5868         unbecome_root();
5869
5870         numlines = 0;
5871         /* Get lines and convert them back to dos-codepage */
5872         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5873         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5874         close(fd);
5875
5876         /* Set the portname to what the script says the portname should be. */
5877         /* but don't require anything to be return from the script exit a good error code */
5878
5879         if (numlines) {
5880                 /* Set the portname to what the script says the portname should be. */
5881                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5882                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5883         }
5884
5885         TALLOC_FREE(qlines);
5886         return true;
5887 }
5888
5889
5890 /********************************************************************
5891  * Called by spoolss_api_setprinter
5892  * when updating a printer description.
5893  ********************************************************************/
5894
5895 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5896                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5897                              struct spoolss_DeviceMode *devmode)
5898 {
5899         int snum;
5900         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5901         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5902         WERROR result;
5903         DATA_BLOB buffer;
5904         fstring asc_buffer;
5905
5906         DEBUG(8,("update_printer\n"));
5907
5908         result = WERR_OK;
5909
5910         if (!Printer) {
5911                 result = WERR_BADFID;
5912                 goto done;
5913         }
5914
5915         if (!get_printer_snum(p, handle, &snum, NULL)) {
5916                 result = WERR_BADFID;
5917                 goto done;
5918         }
5919
5920         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5921             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5922                 result = WERR_BADFID;
5923                 goto done;
5924         }
5925
5926         DEBUGADD(8,("Converting info_2 struct\n"));
5927
5928         /*
5929          * convert_printer_info converts the incoming
5930          * info from the client and overwrites the info
5931          * just read from the tdb in the pointer 'printer'.
5932          */
5933
5934         if (!convert_printer_info(info_ctr, printer)) {
5935                 result =  WERR_NOMEM;
5936                 goto done;
5937         }
5938
5939         if (devmode) {
5940                 /* we have a valid devmode
5941                    convert it and link it*/
5942
5943                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5944                 if (!convert_devicemode(printer->info_2->printername, devmode,
5945                                         &printer->info_2->devmode)) {
5946                         result =  WERR_NOMEM;
5947                         goto done;
5948                 }
5949         }
5950
5951         /* Do sanity check on the requested changes for Samba */
5952
5953         if (!check_printer_ok(printer->info_2, snum)) {
5954                 result = WERR_INVALID_PARAM;
5955                 goto done;
5956         }
5957
5958         /* FIXME!!! If the driver has changed we really should verify that
5959            it is installed before doing much else   --jerry */
5960
5961         /* Check calling user has permission to update printer description */
5962
5963         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5964                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5965                 result = WERR_ACCESS_DENIED;
5966                 goto done;
5967         }
5968
5969         /* Call addprinter hook */
5970         /* Check changes to see if this is really needed */
5971
5972         if ( *lp_addprinter_cmd()
5973                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5974                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5975                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5976                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5977         {
5978                 /* add_printer_hook() will call reload_services() */
5979
5980                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5981                                        printer) ) {
5982                         result = WERR_ACCESS_DENIED;
5983                         goto done;
5984                 }
5985         }
5986
5987         /*
5988          * When a *new* driver is bound to a printer, the drivername is used to
5989          * lookup previously saved driver initialization info, which is then
5990          * bound to the printer, simulating what happens in the Windows arch.
5991          */
5992         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5993         {
5994                 if (!set_driver_init(printer, 2))
5995                 {
5996                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5997                                 printer->info_2->drivername));
5998                 }
5999
6000                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6001                         printer->info_2->drivername));
6002
6003                 notify_printer_driver(snum, printer->info_2->drivername);
6004         }
6005
6006         /*
6007          * flag which changes actually occured.  This is a small subset of
6008          * all the possible changes.  We also have to update things in the
6009          * DsSpooler key.
6010          */
6011
6012         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6013                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
6014                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6015                         REG_SZ, buffer.data, buffer.length);
6016
6017                 notify_printer_comment(snum, printer->info_2->comment);
6018         }
6019
6020         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6021                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
6022                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6023                         REG_SZ, buffer.data, buffer.length);
6024
6025                 notify_printer_sharename(snum, printer->info_2->sharename);
6026         }
6027
6028         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6029                 char *pname;
6030
6031                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6032                         pname++;
6033                 else
6034                         pname = printer->info_2->printername;
6035
6036
6037                 push_reg_sz(talloc_tos(), &buffer, pname);
6038                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6039                         REG_SZ, buffer.data, buffer.length);
6040
6041                 notify_printer_printername( snum, pname );
6042         }
6043
6044         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6045                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
6046                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6047                         REG_SZ, buffer.data, buffer.length);
6048
6049                 notify_printer_port(snum, printer->info_2->portname);
6050         }
6051
6052         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6053                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
6054                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6055                         REG_SZ, buffer.data, buffer.length);
6056
6057                 notify_printer_location(snum, printer->info_2->location);
6058         }
6059
6060         /* here we need to update some more DsSpooler keys */
6061         /* uNCName, serverName, shortServerName */
6062
6063         push_reg_sz(talloc_tos(), &buffer, global_myname());
6064         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6065                 REG_SZ, buffer.data, buffer.length);
6066         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6067                 REG_SZ, buffer.data, buffer.length);
6068
6069         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6070                  global_myname(), printer->info_2->sharename );
6071         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
6072         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6073                 REG_SZ, buffer.data, buffer.length);
6074
6075         /* Update printer info */
6076         result = mod_a_printer(printer, 2);
6077
6078 done:
6079         free_a_printer(&printer, 2);
6080         free_a_printer(&old_printer, 2);
6081
6082
6083         return result;
6084 }
6085
6086 /****************************************************************************
6087 ****************************************************************************/
6088 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6089                                            struct policy_handle *handle,
6090                                            struct spoolss_SetPrinterInfo7 *info7)
6091 {
6092 #ifdef HAVE_ADS
6093         int snum;
6094         Printer_entry *Printer;
6095
6096         if ( lp_security() != SEC_ADS ) {
6097                 return WERR_UNKNOWN_LEVEL;
6098         }
6099
6100         Printer = find_printer_index_by_hnd(p, handle);
6101
6102         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6103
6104         if (!Printer)
6105                 return WERR_BADFID;
6106
6107         if (!get_printer_snum(p, handle, &snum, NULL))
6108                 return WERR_BADFID;
6109
6110         nt_printer_publish(Printer, snum, info7->action);
6111
6112         return WERR_OK;
6113 #else
6114         return WERR_UNKNOWN_LEVEL;
6115 #endif
6116 }
6117
6118 /****************************************************************
6119  _spoolss_SetPrinter
6120 ****************************************************************/
6121
6122 WERROR _spoolss_SetPrinter(pipes_struct *p,
6123                            struct spoolss_SetPrinter *r)
6124 {
6125         WERROR result;
6126
6127         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6128
6129         if (!Printer) {
6130                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6131                         OUR_HANDLE(r->in.handle)));
6132                 return WERR_BADFID;
6133         }
6134
6135         /* check the level */
6136         switch (r->in.info_ctr->level) {
6137                 case 0:
6138                         return control_printer(r->in.handle, r->in.command, p);
6139                 case 2:
6140                         result = update_printer(p, r->in.handle,
6141                                                 r->in.info_ctr,
6142                                                 r->in.devmode_ctr->devmode);
6143                         if (!W_ERROR_IS_OK(result))
6144                                 return result;
6145                         if (r->in.secdesc_ctr->sd)
6146                                 result = update_printer_sec(r->in.handle, p,
6147                                                             r->in.secdesc_ctr);
6148                         return result;
6149                 case 3:
6150                         return update_printer_sec(r->in.handle, p,
6151                                                   r->in.secdesc_ctr);
6152                 case 7:
6153                         return publish_or_unpublish_printer(p, r->in.handle,
6154                                                             r->in.info_ctr->info.info7);
6155                 default:
6156                         return WERR_UNKNOWN_LEVEL;
6157         }
6158 }
6159
6160 /****************************************************************
6161  _spoolss_FindClosePrinterNotify
6162 ****************************************************************/
6163
6164 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6165                                        struct spoolss_FindClosePrinterNotify *r)
6166 {
6167         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6168
6169         if (!Printer) {
6170                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6171                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6172                 return WERR_BADFID;
6173         }
6174
6175         if (Printer->notify.client_connected == true) {
6176                 int snum = -1;
6177
6178                 if ( Printer->printer_type == SPLHND_SERVER)
6179                         snum = -1;
6180                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6181                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6182                         return WERR_BADFID;
6183
6184                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6185         }
6186
6187         Printer->notify.flags=0;
6188         Printer->notify.options=0;
6189         Printer->notify.localmachine[0]='\0';
6190         Printer->notify.printerlocal=0;
6191         TALLOC_FREE(Printer->notify.option);
6192         Printer->notify.client_connected = false;
6193
6194         return WERR_OK;
6195 }
6196
6197 /****************************************************************
6198  _spoolss_AddJob
6199 ****************************************************************/
6200
6201 WERROR _spoolss_AddJob(pipes_struct *p,
6202                        struct spoolss_AddJob *r)
6203 {
6204         if (!r->in.buffer && (r->in.offered != 0)) {
6205                 return WERR_INVALID_PARAM;
6206         }
6207
6208         /* this is what a NT server returns for AddJob. AddJob must fail on
6209          * non-local printers */
6210
6211         if (r->in.level != 1) {
6212                 return WERR_UNKNOWN_LEVEL;
6213         }
6214
6215         return WERR_INVALID_PARAM;
6216 }
6217
6218 /****************************************************************************
6219 fill_job_info1
6220 ****************************************************************************/
6221
6222 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6223                              struct spoolss_JobInfo1 *r,
6224                              const print_queue_struct *queue,
6225                              int position, int snum,
6226                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6227 {
6228         struct tm *t;
6229
6230         t = gmtime(&queue->time);
6231
6232         r->job_id               = queue->job;
6233
6234         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6235         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6236         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6237         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6238         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6239         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6240         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6241         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6242         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6243         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6244         r->text_status          = talloc_strdup(mem_ctx, "");
6245         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6246
6247         r->status               = nt_printj_status(queue->status);
6248         r->priority             = queue->priority;
6249         r->position             = position;
6250         r->total_pages          = queue->page_count;
6251         r->pages_printed        = 0; /* ??? */
6252
6253         init_systemtime(&r->submitted, t);
6254
6255         return WERR_OK;
6256 }
6257
6258 /****************************************************************************
6259 fill_job_info2
6260 ****************************************************************************/
6261
6262 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6263                              struct spoolss_JobInfo2 *r,
6264                              const print_queue_struct *queue,
6265                              int position, int snum,
6266                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6267                              struct spoolss_DeviceMode *devmode)
6268 {
6269         struct tm *t;
6270
6271         t = gmtime(&queue->time);
6272
6273         r->job_id               = queue->job;
6274
6275         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6276         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6277         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6278         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6279         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6280         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6281         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6282         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6283         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6284         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6285         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6286         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6287         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6288         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6289         r->parameters           = talloc_strdup(mem_ctx, "");
6290         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6291         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6292         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6293
6294         r->devmode              = devmode;
6295
6296         r->text_status          = talloc_strdup(mem_ctx, "");
6297         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6298
6299         r->secdesc              = NULL;
6300
6301         r->status               = nt_printj_status(queue->status);
6302         r->priority             = queue->priority;
6303         r->position             = position;
6304         r->start_time           = 0;
6305         r->until_time           = 0;
6306         r->total_pages          = queue->page_count;
6307         r->size                 = queue->size;
6308         init_systemtime(&r->submitted, t);
6309         r->time                 = 0;
6310         r->pages_printed        = 0; /* ??? */
6311
6312         return WERR_OK;
6313 }
6314
6315 /****************************************************************************
6316  Enumjobs at level 1.
6317 ****************************************************************************/
6318
6319 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6320                               const print_queue_struct *queue,
6321                               uint32_t num_queues, int snum,
6322                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6323                               union spoolss_JobInfo **info_p,
6324                               uint32_t *count)
6325 {
6326         union spoolss_JobInfo *info;
6327         int i;
6328         WERROR result = WERR_OK;
6329
6330         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6331         W_ERROR_HAVE_NO_MEMORY(info);
6332
6333         *count = num_queues;
6334
6335         for (i=0; i<*count; i++) {
6336                 result = fill_job_info1(info,
6337                                         &info[i].info1,
6338                                         &queue[i],
6339                                         i,
6340                                         snum,
6341                                         ntprinter);
6342                 if (!W_ERROR_IS_OK(result)) {
6343                         goto out;
6344                 }
6345         }
6346
6347  out:
6348         if (!W_ERROR_IS_OK(result)) {
6349                 TALLOC_FREE(info);
6350                 *count = 0;
6351                 return result;
6352         }
6353
6354         *info_p = info;
6355
6356         return WERR_OK;
6357 }
6358
6359 /****************************************************************************
6360  Enumjobs at level 2.
6361 ****************************************************************************/
6362
6363 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6364                               const print_queue_struct *queue,
6365                               uint32_t num_queues, int snum,
6366                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6367                               union spoolss_JobInfo **info_p,
6368                               uint32_t *count)
6369 {
6370         union spoolss_JobInfo *info;
6371         int i;
6372         WERROR result = WERR_OK;
6373
6374         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6375         W_ERROR_HAVE_NO_MEMORY(info);
6376
6377         *count = num_queues;
6378
6379         for (i=0; i<*count; i++) {
6380
6381                 struct spoolss_DeviceMode *devmode;
6382
6383                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6384                 if (!devmode) {
6385                         result = WERR_NOMEM;
6386                         goto out;
6387                 }
6388
6389                 result = fill_job_info2(info,
6390                                         &info[i].info2,
6391                                         &queue[i],
6392                                         i,
6393                                         snum,
6394                                         ntprinter,
6395                                         devmode);
6396                 if (!W_ERROR_IS_OK(result)) {
6397                         goto out;
6398                 }
6399         }
6400
6401  out:
6402         if (!W_ERROR_IS_OK(result)) {
6403                 TALLOC_FREE(info);
6404                 *count = 0;
6405                 return result;
6406         }
6407
6408         *info_p = info;
6409
6410         return WERR_OK;
6411 }
6412
6413 /****************************************************************
6414  _spoolss_EnumJobs
6415 ****************************************************************/
6416
6417 WERROR _spoolss_EnumJobs(pipes_struct *p,
6418                          struct spoolss_EnumJobs *r)
6419 {
6420         WERROR result;
6421         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6422         int snum;
6423         print_status_struct prt_status;
6424         print_queue_struct *queue = NULL;
6425         uint32_t count;
6426
6427         /* that's an [in out] buffer */
6428
6429         if (!r->in.buffer && (r->in.offered != 0)) {
6430                 return WERR_INVALID_PARAM;
6431         }
6432
6433         DEBUG(4,("_spoolss_EnumJobs\n"));
6434
6435         *r->out.needed = 0;
6436         *r->out.count = 0;
6437         *r->out.info = NULL;
6438
6439         /* lookup the printer snum and tdb entry */
6440
6441         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6442                 return WERR_BADFID;
6443         }
6444
6445         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6446         if (!W_ERROR_IS_OK(result)) {
6447                 return result;
6448         }
6449
6450         count = print_queue_status(snum, &queue, &prt_status);
6451         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6452                 count, prt_status.status, prt_status.message));
6453
6454         if (count == 0) {
6455                 SAFE_FREE(queue);
6456                 free_a_printer(&ntprinter, 2);
6457                 return WERR_OK;
6458         }
6459
6460         switch (r->in.level) {
6461         case 1:
6462                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6463                                          ntprinter, r->out.info, r->out.count);
6464                 break;
6465         case 2:
6466                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6467                                          ntprinter, r->out.info, r->out.count);
6468                 break;
6469         default:
6470                 result = WERR_UNKNOWN_LEVEL;
6471                 break;
6472         }
6473
6474         SAFE_FREE(queue);
6475         free_a_printer(&ntprinter, 2);
6476
6477         if (!W_ERROR_IS_OK(result)) {
6478                 return result;
6479         }
6480
6481         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6482                                                      spoolss_EnumJobs, NULL,
6483                                                      *r->out.info, r->in.level,
6484                                                      *r->out.count);
6485         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6486         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6487
6488         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6489 }
6490
6491 /****************************************************************
6492  _spoolss_ScheduleJob
6493 ****************************************************************/
6494
6495 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6496                             struct spoolss_ScheduleJob *r)
6497 {
6498         return WERR_OK;
6499 }
6500
6501 /****************************************************************
6502  _spoolss_SetJob
6503 ****************************************************************/
6504
6505 WERROR _spoolss_SetJob(pipes_struct *p,
6506                        struct spoolss_SetJob *r)
6507 {
6508         int snum;
6509         WERROR errcode = WERR_BADFUNC;
6510
6511         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6512                 return WERR_BADFID;
6513         }
6514
6515         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6516                 return WERR_INVALID_PRINTER_NAME;
6517         }
6518
6519         switch (r->in.command) {
6520         case SPOOLSS_JOB_CONTROL_CANCEL:
6521         case SPOOLSS_JOB_CONTROL_DELETE:
6522                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6523                         errcode = WERR_OK;
6524                 }
6525                 break;
6526         case SPOOLSS_JOB_CONTROL_PAUSE:
6527                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6528                         errcode = WERR_OK;
6529                 }
6530                 break;
6531         case SPOOLSS_JOB_CONTROL_RESTART:
6532         case SPOOLSS_JOB_CONTROL_RESUME:
6533                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6534                         errcode = WERR_OK;
6535                 }
6536                 break;
6537         default:
6538                 return WERR_UNKNOWN_LEVEL;
6539         }
6540
6541         return errcode;
6542 }
6543
6544 /****************************************************************************
6545  Enumerates all printer drivers by level and architecture.
6546 ****************************************************************************/
6547
6548 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6549                                                        const char *servername,
6550                                                        const char *architecture,
6551                                                        uint32_t level,
6552                                                        union spoolss_DriverInfo **info_p,
6553                                                        uint32_t *count_p)
6554 {
6555         int i;
6556         int ndrivers;
6557         uint32_t version;
6558         fstring *list = NULL;
6559         union spoolss_DriverInfo *driver;
6560         union spoolss_DriverInfo *info = NULL;
6561         uint32_t count = 0;
6562         WERROR result = WERR_OK;
6563
6564         *count_p = 0;
6565         *info_p = NULL;
6566
6567         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6568                 list = NULL;
6569                 ndrivers = get_ntdrivers(&list, architecture, version);
6570                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6571                         ndrivers, architecture, version));
6572
6573                 if (ndrivers == -1) {
6574                         result = WERR_NOMEM;
6575                         goto out;
6576                 }
6577
6578                 if (ndrivers != 0) {
6579                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6580                                                     union spoolss_DriverInfo,
6581                                                     count + ndrivers);
6582                         if (!info) {
6583                                 DEBUG(0,("enumprinterdrivers_level1: "
6584                                         "failed to enlarge driver info buffer!\n"));
6585                                 result = WERR_NOMEM;
6586                                 goto out;
6587                         }
6588                 }
6589
6590                 for (i=0; i<ndrivers; i++) {
6591                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6592                         ZERO_STRUCT(driver);
6593                         result = get_a_printer_driver(mem_ctx, &driver, 3, list[i],
6594                                                       architecture, version);
6595                         if (!W_ERROR_IS_OK(result)) {
6596                                 goto out;
6597                         }
6598
6599                         switch (level) {
6600                         case 1:
6601                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6602                                                                    driver, servername,
6603                                                                    architecture);
6604                                 break;
6605                         case 2:
6606                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6607                                                                    driver, servername);
6608                                 break;
6609                         case 3:
6610                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6611                                                                    driver, servername);
6612                                 break;
6613                         case 4:
6614                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6615                                                                    driver, servername);
6616                                 break;
6617                         case 5:
6618                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6619                                                                    driver, servername);
6620                                 break;
6621                         case 6:
6622                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6623                                                                    driver, servername);
6624                                 break;
6625                         default:
6626                                 result = WERR_UNKNOWN_LEVEL;
6627                                 break;
6628                         }
6629
6630                         free_a_printer_driver(driver);
6631
6632                         if (!W_ERROR_IS_OK(result)) {
6633                                 goto out;
6634                         }
6635                 }
6636
6637                 count += ndrivers;
6638                 SAFE_FREE(list);
6639         }
6640
6641  out:
6642         SAFE_FREE(list);
6643
6644         if (!W_ERROR_IS_OK(result)) {
6645                 TALLOC_FREE(info);
6646                 return result;
6647         }
6648
6649         *info_p = info;
6650         *count_p = count;
6651
6652         return WERR_OK;
6653 }
6654
6655 /****************************************************************************
6656  Enumerates all printer drivers by level.
6657 ****************************************************************************/
6658
6659 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6660                                        const char *servername,
6661                                        const char *architecture,
6662                                        uint32_t level,
6663                                        union spoolss_DriverInfo **info_p,
6664                                        uint32_t *count_p)
6665 {
6666         uint32_t a,i;
6667         WERROR result = WERR_OK;
6668
6669         if (strequal(architecture, "all")) {
6670
6671                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6672
6673                         union spoolss_DriverInfo *info = NULL;
6674                         uint32_t count = 0;
6675
6676                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6677                                                                           servername,
6678                                                                           archi_table[a].long_archi,
6679                                                                           level,
6680                                                                           &info,
6681                                                                           &count);
6682                         if (!W_ERROR_IS_OK(result)) {
6683                                 continue;
6684                         }
6685
6686                         for (i=0; i < count; i++) {
6687                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6688                                              info[i], info_p, count_p);
6689                         }
6690                 }
6691
6692                 return result;
6693         }
6694
6695         return enumprinterdrivers_level_by_architecture(mem_ctx,
6696                                                         servername,
6697                                                         architecture,
6698                                                         level,
6699                                                         info_p,
6700                                                         count_p);
6701 }
6702
6703 /****************************************************************************
6704  Enumerates all printer drivers at level 1.
6705 ****************************************************************************/
6706
6707 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6708                                         const char *servername,
6709                                         const char *architecture,
6710                                         union spoolss_DriverInfo **info_p,
6711                                         uint32_t *count)
6712 {
6713         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6714                                         info_p, count);
6715 }
6716
6717 /****************************************************************************
6718  Enumerates all printer drivers at level 2.
6719 ****************************************************************************/
6720
6721 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6722                                         const char *servername,
6723                                         const char *architecture,
6724                                         union spoolss_DriverInfo **info_p,
6725                                         uint32_t *count)
6726 {
6727         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6728                                         info_p, count);
6729 }
6730
6731 /****************************************************************************
6732  Enumerates all printer drivers at level 3.
6733 ****************************************************************************/
6734
6735 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6736                                         const char *servername,
6737                                         const char *architecture,
6738                                         union spoolss_DriverInfo **info_p,
6739                                         uint32_t *count)
6740 {
6741         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6742                                         info_p, count);
6743 }
6744
6745 /****************************************************************************
6746  Enumerates all printer drivers at level 4.
6747 ****************************************************************************/
6748
6749 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6750                                         const char *servername,
6751                                         const char *architecture,
6752                                         union spoolss_DriverInfo **info_p,
6753                                         uint32_t *count)
6754 {
6755         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6756                                         info_p, count);
6757 }
6758
6759 /****************************************************************************
6760  Enumerates all printer drivers at level 5.
6761 ****************************************************************************/
6762
6763 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6764                                         const char *servername,
6765                                         const char *architecture,
6766                                         union spoolss_DriverInfo **info_p,
6767                                         uint32_t *count)
6768 {
6769         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6770                                         info_p, count);
6771 }
6772
6773 /****************************************************************************
6774  Enumerates all printer drivers at level 6.
6775 ****************************************************************************/
6776
6777 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6778                                         const char *servername,
6779                                         const char *architecture,
6780                                         union spoolss_DriverInfo **info_p,
6781                                         uint32_t *count)
6782 {
6783         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6784                                         info_p, count);
6785 }
6786
6787
6788 /****************************************************************
6789  _spoolss_EnumPrinterDrivers
6790 ****************************************************************/
6791
6792 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6793                                    struct spoolss_EnumPrinterDrivers *r)
6794 {
6795         const char *cservername;
6796         WERROR result;
6797
6798         /* that's an [in out] buffer */
6799
6800         if (!r->in.buffer && (r->in.offered != 0)) {
6801                 return WERR_INVALID_PARAM;
6802         }
6803
6804         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6805
6806         *r->out.needed = 0;
6807         *r->out.count = 0;
6808         *r->out.info = NULL;
6809
6810         cservername = canon_servername(r->in.server);
6811
6812         if (!is_myname_or_ipaddr(cservername)) {
6813                 return WERR_UNKNOWN_PRINTER_DRIVER;
6814         }
6815
6816         switch (r->in.level) {
6817         case 1:
6818                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6819                                                    r->in.environment,
6820                                                    r->out.info, r->out.count);
6821                 break;
6822         case 2:
6823                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6824                                                    r->in.environment,
6825                                                    r->out.info, r->out.count);
6826                 break;
6827         case 3:
6828                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6829                                                    r->in.environment,
6830                                                    r->out.info, r->out.count);
6831                 break;
6832         case 4:
6833                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6834                                                    r->in.environment,
6835                                                    r->out.info, r->out.count);
6836                 break;
6837         case 5:
6838                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6839                                                    r->in.environment,
6840                                                    r->out.info, r->out.count);
6841                 break;
6842         case 6:
6843                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6844                                                    r->in.environment,
6845                                                    r->out.info, r->out.count);
6846                 break;
6847         default:
6848                 return WERR_UNKNOWN_LEVEL;
6849         }
6850
6851         if (!W_ERROR_IS_OK(result)) {
6852                 return result;
6853         }
6854
6855         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6856                                                      spoolss_EnumPrinterDrivers, NULL,
6857                                                      *r->out.info, r->in.level,
6858                                                      *r->out.count);
6859         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6860         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6861
6862         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6863 }
6864
6865 /****************************************************************************
6866 ****************************************************************************/
6867
6868 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6869                                struct spoolss_FormInfo1 *r,
6870                                const nt_forms_struct *form)
6871 {
6872         r->form_name    = talloc_strdup(mem_ctx, form->name);
6873         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6874
6875         r->flags        = form->flag;
6876         r->size.width   = form->width;
6877         r->size.height  = form->length;
6878         r->area.left    = form->left;
6879         r->area.top     = form->top;
6880         r->area.right   = form->right;
6881         r->area.bottom  = form->bottom;
6882
6883         return WERR_OK;
6884 }
6885
6886 /****************************************************************
6887  spoolss_enumforms_level1
6888 ****************************************************************/
6889
6890 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6891                                        const nt_forms_struct *builtin_forms,
6892                                        uint32_t num_builtin_forms,
6893                                        const nt_forms_struct *user_forms,
6894                                        uint32_t num_user_forms,
6895                                        union spoolss_FormInfo **info_p,
6896                                        uint32_t *count)
6897 {
6898         union spoolss_FormInfo *info;
6899         WERROR result = WERR_OK;
6900         int i;
6901
6902         *count = num_builtin_forms + num_user_forms;
6903
6904         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6905         W_ERROR_HAVE_NO_MEMORY(info);
6906
6907         /* construct the list of form structures */
6908         for (i=0; i<num_builtin_forms; i++) {
6909                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6910                 result = fill_form_info_1(info, &info[i].info1,
6911                                           &builtin_forms[i]);
6912                 if (!W_ERROR_IS_OK(result)) {
6913                         goto out;
6914                 }
6915         }
6916
6917         for (i=0; i<num_user_forms; i++) {
6918                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6919                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6920                                           &user_forms[i]);
6921                 if (!W_ERROR_IS_OK(result)) {
6922                         goto out;
6923                 }
6924         }
6925
6926  out:
6927         if (!W_ERROR_IS_OK(result)) {
6928                 TALLOC_FREE(info);
6929                 *count = 0;
6930                 return result;
6931         }
6932
6933         *info_p = info;
6934
6935         return WERR_OK;
6936 }
6937
6938 /****************************************************************
6939  _spoolss_EnumForms
6940 ****************************************************************/
6941
6942 WERROR _spoolss_EnumForms(pipes_struct *p,
6943                           struct spoolss_EnumForms *r)
6944 {
6945         WERROR result;
6946         nt_forms_struct *user_forms = NULL;
6947         nt_forms_struct *builtin_forms = NULL;
6948         uint32_t num_user_forms;
6949         uint32_t num_builtin_forms;
6950
6951         *r->out.count = 0;
6952         *r->out.needed = 0;
6953         *r->out.info = NULL;
6954
6955         /* that's an [in out] buffer */
6956
6957         if (!r->in.buffer && (r->in.offered != 0) ) {
6958                 return WERR_INVALID_PARAM;
6959         }
6960
6961         DEBUG(4,("_spoolss_EnumForms\n"));
6962         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6963         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6964
6965         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6966         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6967         num_user_forms = get_ntforms(&user_forms);
6968         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6969
6970         if (num_user_forms + num_builtin_forms == 0) {
6971                 SAFE_FREE(builtin_forms);
6972                 SAFE_FREE(user_forms);
6973                 return WERR_NO_MORE_ITEMS;
6974         }
6975
6976         switch (r->in.level) {
6977         case 1:
6978                 result = spoolss_enumforms_level1(p->mem_ctx,
6979                                                   builtin_forms,
6980                                                   num_builtin_forms,
6981                                                   user_forms,
6982                                                   num_user_forms,
6983                                                   r->out.info,
6984                                                   r->out.count);
6985                 break;
6986         default:
6987                 result = WERR_UNKNOWN_LEVEL;
6988                 break;
6989         }
6990
6991         SAFE_FREE(user_forms);
6992         SAFE_FREE(builtin_forms);
6993
6994         if (!W_ERROR_IS_OK(result)) {
6995                 return result;
6996         }
6997
6998         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6999                                                      spoolss_EnumForms, NULL,
7000                                                      *r->out.info, r->in.level,
7001                                                      *r->out.count);
7002         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7003         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7004
7005         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7006 }
7007
7008 /****************************************************************
7009 ****************************************************************/
7010
7011 static WERROR find_form_byname(const char *name,
7012                                nt_forms_struct *form)
7013 {
7014         nt_forms_struct *list = NULL;
7015         int num_forms = 0, i = 0;
7016
7017         if (get_a_builtin_ntform_by_string(name, form)) {
7018                 return WERR_OK;
7019         }
7020
7021         num_forms = get_ntforms(&list);
7022         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7023
7024         if (num_forms == 0) {
7025                 return WERR_BADFID;
7026         }
7027
7028         /* Check if the requested name is in the list of form structures */
7029         for (i = 0; i < num_forms; i++) {
7030
7031                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7032
7033                 if (strequal(name, list[i].name)) {
7034                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7035                         *form = list[i];
7036                         SAFE_FREE(list);
7037                         return WERR_OK;
7038                 }
7039         }
7040
7041         SAFE_FREE(list);
7042
7043         return WERR_BADFID;
7044 }
7045
7046 /****************************************************************
7047  _spoolss_GetForm
7048 ****************************************************************/
7049
7050 WERROR _spoolss_GetForm(pipes_struct *p,
7051                         struct spoolss_GetForm *r)
7052 {
7053         WERROR result;
7054         nt_forms_struct form;
7055
7056         /* that's an [in out] buffer */
7057
7058         if (!r->in.buffer && (r->in.offered != 0)) {
7059                 return WERR_INVALID_PARAM;
7060         }
7061
7062         DEBUG(4,("_spoolss_GetForm\n"));
7063         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7064         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7065
7066         result = find_form_byname(r->in.form_name, &form);
7067         if (!W_ERROR_IS_OK(result)) {
7068                 TALLOC_FREE(r->out.info);
7069                 return result;
7070         }
7071
7072         switch (r->in.level) {
7073         case 1:
7074                 result = fill_form_info_1(p->mem_ctx,
7075                                           &r->out.info->info1,
7076                                           &form);
7077                 break;
7078
7079         default:
7080                 result = WERR_UNKNOWN_LEVEL;
7081                 break;
7082         }
7083
7084         if (!W_ERROR_IS_OK(result)) {
7085                 TALLOC_FREE(r->out.info);
7086                 return result;
7087         }
7088
7089         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7090                                                r->out.info, r->in.level);
7091         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7092
7093         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7094 }
7095
7096 /****************************************************************************
7097 ****************************************************************************/
7098
7099 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7100                           struct spoolss_PortInfo1 *r,
7101                           const char *name)
7102 {
7103         r->port_name = talloc_strdup(mem_ctx, name);
7104         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7105
7106         return WERR_OK;
7107 }
7108
7109 /****************************************************************************
7110  TODO: This probably needs distinguish between TCP/IP and Local ports
7111  somehow.
7112 ****************************************************************************/
7113
7114 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7115                           struct spoolss_PortInfo2 *r,
7116                           const char *name)
7117 {
7118         r->port_name = talloc_strdup(mem_ctx, name);
7119         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7120
7121         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7122         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7123
7124         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7125         W_ERROR_HAVE_NO_MEMORY(r->description);
7126
7127         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7128         r->reserved = 0;
7129
7130         return WERR_OK;
7131 }
7132
7133
7134 /****************************************************************************
7135  wrapper around the enumer ports command
7136 ****************************************************************************/
7137
7138 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7139 {
7140         char *cmd = lp_enumports_cmd();
7141         char **qlines = NULL;
7142         char *command = NULL;
7143         int numlines;
7144         int ret;
7145         int fd;
7146
7147         *count = 0;
7148         *lines = NULL;
7149
7150         /* if no hook then just fill in the default port */
7151
7152         if ( !*cmd ) {
7153                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7154                         return WERR_NOMEM;
7155                 }
7156                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7157                         TALLOC_FREE(qlines);
7158                         return WERR_NOMEM;
7159                 }
7160                 qlines[1] = NULL;
7161                 numlines = 1;
7162         }
7163         else {
7164                 /* we have a valid enumport command */
7165
7166                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7167                 if (!command) {
7168                         return WERR_NOMEM;
7169                 }
7170
7171                 DEBUG(10,("Running [%s]\n", command));
7172                 ret = smbrun(command, &fd);
7173                 DEBUG(10,("Returned [%d]\n", ret));
7174                 TALLOC_FREE(command);
7175                 if (ret != 0) {
7176                         if (fd != -1) {
7177                                 close(fd);
7178                         }
7179                         return WERR_ACCESS_DENIED;
7180                 }
7181
7182                 numlines = 0;
7183                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7184                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7185                 close(fd);
7186         }
7187
7188         *count = numlines;
7189         *lines = qlines;
7190
7191         return WERR_OK;
7192 }
7193
7194 /****************************************************************************
7195  enumports level 1.
7196 ****************************************************************************/
7197
7198 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7199                                 union spoolss_PortInfo **info_p,
7200                                 uint32_t *count)
7201 {
7202         union spoolss_PortInfo *info = NULL;
7203         int i=0;
7204         WERROR result = WERR_OK;
7205         char **qlines = NULL;
7206         int numlines = 0;
7207
7208         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7209         if (!W_ERROR_IS_OK(result)) {
7210                 goto out;
7211         }
7212
7213         if (numlines) {
7214                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7215                 if (!info) {
7216                         DEBUG(10,("Returning WERR_NOMEM\n"));
7217                         result = WERR_NOMEM;
7218                         goto out;
7219                 }
7220
7221                 for (i=0; i<numlines; i++) {
7222                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7223                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7224                         if (!W_ERROR_IS_OK(result)) {
7225                                 goto out;
7226                         }
7227                 }
7228         }
7229         TALLOC_FREE(qlines);
7230
7231 out:
7232         if (!W_ERROR_IS_OK(result)) {
7233                 TALLOC_FREE(info);
7234                 TALLOC_FREE(qlines);
7235                 *count = 0;
7236                 *info_p = NULL;
7237                 return result;
7238         }
7239
7240         *info_p = info;
7241         *count = numlines;
7242
7243         return WERR_OK;
7244 }
7245
7246 /****************************************************************************
7247  enumports level 2.
7248 ****************************************************************************/
7249
7250 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7251                                 union spoolss_PortInfo **info_p,
7252                                 uint32_t *count)
7253 {
7254         union spoolss_PortInfo *info = NULL;
7255         int i=0;
7256         WERROR result = WERR_OK;
7257         char **qlines = NULL;
7258         int numlines = 0;
7259
7260         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7261         if (!W_ERROR_IS_OK(result)) {
7262                 goto out;
7263         }
7264
7265         if (numlines) {
7266                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7267                 if (!info) {
7268                         DEBUG(10,("Returning WERR_NOMEM\n"));
7269                         result = WERR_NOMEM;
7270                         goto out;
7271                 }
7272
7273                 for (i=0; i<numlines; i++) {
7274                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7275                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7276                         if (!W_ERROR_IS_OK(result)) {
7277                                 goto out;
7278                         }
7279                 }
7280         }
7281         TALLOC_FREE(qlines);
7282
7283 out:
7284         if (!W_ERROR_IS_OK(result)) {
7285                 TALLOC_FREE(info);
7286                 TALLOC_FREE(qlines);
7287                 *count = 0;
7288                 *info_p = NULL;
7289                 return result;
7290         }
7291
7292         *info_p = info;
7293         *count = numlines;
7294
7295         return WERR_OK;
7296 }
7297
7298 /****************************************************************
7299  _spoolss_EnumPorts
7300 ****************************************************************/
7301
7302 WERROR _spoolss_EnumPorts(pipes_struct *p,
7303                           struct spoolss_EnumPorts *r)
7304 {
7305         WERROR result;
7306
7307         /* that's an [in out] buffer */
7308
7309         if (!r->in.buffer && (r->in.offered != 0)) {
7310                 return WERR_INVALID_PARAM;
7311         }
7312
7313         DEBUG(4,("_spoolss_EnumPorts\n"));
7314
7315         *r->out.count = 0;
7316         *r->out.needed = 0;
7317         *r->out.info = NULL;
7318
7319         switch (r->in.level) {
7320         case 1:
7321                 result = enumports_level_1(p->mem_ctx, r->out.info,
7322                                            r->out.count);
7323                 break;
7324         case 2:
7325                 result = enumports_level_2(p->mem_ctx, r->out.info,
7326                                            r->out.count);
7327                 break;
7328         default:
7329                 return WERR_UNKNOWN_LEVEL;
7330         }
7331
7332         if (!W_ERROR_IS_OK(result)) {
7333                 return result;
7334         }
7335
7336         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7337                                                      spoolss_EnumPorts, NULL,
7338                                                      *r->out.info, r->in.level,
7339                                                      *r->out.count);
7340         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7341         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7342
7343         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7344 }
7345
7346 /****************************************************************************
7347 ****************************************************************************/
7348
7349 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7350                                            const char *server,
7351                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7352                                            struct spoolss_DeviceMode *devmode,
7353                                            struct security_descriptor *sec_desc,
7354                                            struct spoolss_UserLevelCtr *user_ctr,
7355                                            struct policy_handle *handle)
7356 {
7357         NT_PRINTER_INFO_LEVEL *printer = NULL;
7358         fstring name;
7359         int     snum;
7360         WERROR err = WERR_OK;
7361
7362         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7363                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7364                 return WERR_NOMEM;
7365         }
7366
7367         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7368         if (!convert_printer_info(info_ctr, printer)) {
7369                 free_a_printer(&printer, 2);
7370                 return WERR_NOMEM;
7371         }
7372
7373         /* check to see if the printer already exists */
7374
7375         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7376                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7377                         printer->info_2->sharename));
7378                 free_a_printer(&printer, 2);
7379                 return WERR_PRINTER_ALREADY_EXISTS;
7380         }
7381
7382         /* FIXME!!!  smbd should check to see if the driver is installed before
7383            trying to add a printer like this  --jerry */
7384
7385         if (*lp_addprinter_cmd() ) {
7386                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7387                                        printer) ) {
7388                         free_a_printer(&printer,2);
7389                         return WERR_ACCESS_DENIED;
7390                 }
7391         } else {
7392                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7393                         "smb.conf parameter \"addprinter command\" is defined. This"
7394                         "parameter must exist for this call to succeed\n",
7395                         printer->info_2->sharename ));
7396         }
7397
7398         /* use our primary netbios name since get_a_printer() will convert
7399            it to what the client expects on a case by case basis */
7400
7401         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7402              printer->info_2->sharename);
7403
7404
7405         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7406                 free_a_printer(&printer,2);
7407                 return WERR_ACCESS_DENIED;
7408         }
7409
7410         /* you must be a printer admin to add a new printer */
7411         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7412                 free_a_printer(&printer,2);
7413                 return WERR_ACCESS_DENIED;
7414         }
7415
7416         /*
7417          * Do sanity check on the requested changes for Samba.
7418          */
7419
7420         if (!check_printer_ok(printer->info_2, snum)) {
7421                 free_a_printer(&printer,2);
7422                 return WERR_INVALID_PARAM;
7423         }
7424
7425         /*
7426          * When a printer is created, the drivername bound to the printer is used
7427          * to lookup previously saved driver initialization info, which is then
7428          * bound to the new printer, simulating what happens in the Windows arch.
7429          */
7430
7431         if (!devmode)
7432         {
7433                 set_driver_init(printer, 2);
7434         }
7435         else
7436         {
7437                 /* A valid devmode was included, convert and link it
7438                 */
7439                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7440
7441                 if (!convert_devicemode(printer->info_2->printername, devmode,
7442                                         &printer->info_2->devmode)) {
7443                         return  WERR_NOMEM;
7444                 }
7445         }
7446
7447         /* write the ASCII on disk */
7448         err = mod_a_printer(printer, 2);
7449         if (!W_ERROR_IS_OK(err)) {
7450                 free_a_printer(&printer,2);
7451                 return err;
7452         }
7453
7454         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7455                 /* Handle open failed - remove addition. */
7456                 del_a_printer(printer->info_2->sharename);
7457                 free_a_printer(&printer,2);
7458                 ZERO_STRUCTP(handle);
7459                 return WERR_ACCESS_DENIED;
7460         }
7461
7462         update_c_setprinter(false);
7463         free_a_printer(&printer,2);
7464
7465         return WERR_OK;
7466 }
7467
7468 /****************************************************************
7469  _spoolss_AddPrinterEx
7470 ****************************************************************/
7471
7472 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7473                              struct spoolss_AddPrinterEx *r)
7474 {
7475         switch (r->in.info_ctr->level) {
7476         case 1:
7477                 /* we don't handle yet */
7478                 /* but I know what to do ... */
7479                 return WERR_UNKNOWN_LEVEL;
7480         case 2:
7481                 return spoolss_addprinterex_level_2(p, r->in.server,
7482                                                     r->in.info_ctr,
7483                                                     r->in.devmode_ctr->devmode,
7484                                                     r->in.secdesc_ctr->sd,
7485                                                     r->in.userlevel_ctr,
7486                                                     r->out.handle);
7487         default:
7488                 return WERR_UNKNOWN_LEVEL;
7489         }
7490 }
7491
7492 /****************************************************************
7493  _spoolss_AddPrinter
7494 ****************************************************************/
7495
7496 WERROR _spoolss_AddPrinter(pipes_struct *p,
7497                            struct spoolss_AddPrinter *r)
7498 {
7499         struct spoolss_AddPrinterEx a;
7500         struct spoolss_UserLevelCtr userlevel_ctr;
7501
7502         ZERO_STRUCT(userlevel_ctr);
7503
7504         userlevel_ctr.level = 1;
7505
7506         a.in.server             = r->in.server;
7507         a.in.info_ctr           = r->in.info_ctr;
7508         a.in.devmode_ctr        = r->in.devmode_ctr;
7509         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7510         a.in.userlevel_ctr      = &userlevel_ctr;
7511         a.out.handle            = r->out.handle;
7512
7513         return _spoolss_AddPrinterEx(p, &a);
7514 }
7515
7516 /****************************************************************
7517  _spoolss_AddPrinterDriver
7518 ****************************************************************/
7519
7520 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7521                                  struct spoolss_AddPrinterDriver *r)
7522 {
7523         WERROR err = WERR_OK;
7524         char *driver_name = NULL;
7525         uint32_t version;
7526         const char *fn;
7527
7528         switch (p->hdr_req.opnum) {
7529                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7530                         fn = "_spoolss_AddPrinterDriver";
7531                         break;
7532                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7533                         fn = "_spoolss_AddPrinterDriverEx";
7534                         break;
7535                 default:
7536                         return WERR_INVALID_PARAM;
7537         }
7538
7539
7540         /* FIXME */
7541         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7542                 /* Clever hack from Martin Zielinski <mz@seh.de>
7543                  * to allow downgrade from level 8 (Vista).
7544                  */
7545                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7546                         r->in.info_ctr->level));
7547                 return WERR_UNKNOWN_LEVEL;
7548         }
7549
7550         DEBUG(5,("Cleaning driver's information\n"));
7551         err = clean_up_driver_struct(p, r->in.info_ctr);
7552         if (!W_ERROR_IS_OK(err))
7553                 goto done;
7554
7555         DEBUG(5,("Moving driver to final destination\n"));
7556         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7557                                                               &err)) ) {
7558                 goto done;
7559         }
7560
7561         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7562                 err = WERR_ACCESS_DENIED;
7563                 goto done;
7564         }
7565
7566         /*
7567          * I think this is where he DrvUpgradePrinter() hook would be
7568          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7569          * server.  Right now, we just need to send ourselves a message
7570          * to update each printer bound to this driver.   --jerry
7571          */
7572
7573         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7574                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7575                         fn, driver_name));
7576         }
7577
7578         /*
7579          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7580          * decide if the driver init data should be deleted. The rules are:
7581          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7582          *  2) delete init data only if there is no 2k/Xp driver
7583          *  3) always delete init data
7584          * The generalized rule is always use init data from the highest order driver.
7585          * It is necessary to follow the driver install by an initialization step to
7586          * finish off this process.
7587         */
7588
7589         switch (version) {
7590                 /*
7591                  * 9x printer driver - never delete init data
7592                 */
7593                 case 0:
7594                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7595                                 fn, driver_name));
7596                         break;
7597
7598                 /*
7599                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7600                  * there is no 2k/Xp driver init data for this driver name.
7601                 */
7602                 case 2:
7603                 {
7604                         union spoolss_DriverInfo *driver1;
7605
7606                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, 3, driver_name, "Windows NT x86", 3))) {
7607                                 /*
7608                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7609                                 */
7610                                 if (!del_driver_init(driver_name))
7611                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7612                                                 fn, driver_name));
7613                         } else {
7614                                 /*
7615                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7616                                 */
7617                                 free_a_printer_driver(driver1);
7618                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7619                                         fn, driver_name));
7620                         }
7621                 }
7622                 break;
7623
7624                 /*
7625                  * 2k or Xp printer driver - always delete init data
7626                 */
7627                 case 3:
7628                         if (!del_driver_init(driver_name))
7629                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7630                                         fn, driver_name));
7631                         break;
7632
7633                 default:
7634                         DEBUG(0,("%s: invalid level=%d\n", fn,
7635                                 r->in.info_ctr->level));
7636                         break;
7637         }
7638
7639
7640 done:
7641         return err;
7642 }
7643
7644 /****************************************************************
7645  _spoolss_AddPrinterDriverEx
7646 ****************************************************************/
7647
7648 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7649                                    struct spoolss_AddPrinterDriverEx *r)
7650 {
7651         struct spoolss_AddPrinterDriver a;
7652
7653         /*
7654          * we only support the semantics of AddPrinterDriver()
7655          * i.e. only copy files that are newer than existing ones
7656          */
7657
7658         if (r->in.flags != APD_COPY_NEW_FILES) {
7659                 return WERR_ACCESS_DENIED;
7660         }
7661
7662         a.in.servername         = r->in.servername;
7663         a.in.info_ctr           = r->in.info_ctr;
7664
7665         return _spoolss_AddPrinterDriver(p, &a);
7666 }
7667
7668 /****************************************************************************
7669 ****************************************************************************/
7670
7671 struct _spoolss_paths {
7672         int type;
7673         const char *share;
7674         const char *dir;
7675 };
7676
7677 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7678
7679 static const struct _spoolss_paths spoolss_paths[]= {
7680         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7681         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7682 };
7683
7684 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7685                                           const char *servername,
7686                                           const char *environment,
7687                                           int component,
7688                                           char **path)
7689 {
7690         const char *pservername = NULL;
7691         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7692         const char *short_archi;
7693
7694         *path = NULL;
7695
7696         /* environment may be empty */
7697         if (environment && strlen(environment)) {
7698                 long_archi = environment;
7699         }
7700
7701         /* servername may be empty */
7702         if (servername && strlen(servername)) {
7703                 pservername = canon_servername(servername);
7704
7705                 if (!is_myname_or_ipaddr(pservername)) {
7706                         return WERR_INVALID_PARAM;
7707                 }
7708         }
7709
7710         if (!(short_archi = get_short_archi(long_archi))) {
7711                 return WERR_INVALID_ENVIRONMENT;
7712         }
7713
7714         switch (component) {
7715         case SPOOLSS_PRTPROCS_PATH:
7716         case SPOOLSS_DRIVER_PATH:
7717                 if (pservername) {
7718                         *path = talloc_asprintf(mem_ctx,
7719                                         "\\\\%s\\%s\\%s",
7720                                         pservername,
7721                                         spoolss_paths[component].share,
7722                                         short_archi);
7723                 } else {
7724                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7725                                         SPOOLSS_DEFAULT_SERVER_PATH,
7726                                         spoolss_paths[component].dir,
7727                                         short_archi);
7728                 }
7729                 break;
7730         default:
7731                 return WERR_INVALID_PARAM;
7732         }
7733
7734         if (!*path) {
7735                 return WERR_NOMEM;
7736         }
7737
7738         return WERR_OK;
7739 }
7740
7741 /****************************************************************************
7742 ****************************************************************************/
7743
7744 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7745                                           const char *servername,
7746                                           const char *environment,
7747                                           struct spoolss_DriverDirectoryInfo1 *r)
7748 {
7749         WERROR werr;
7750         char *path = NULL;
7751
7752         werr = compose_spoolss_server_path(mem_ctx,
7753                                            servername,
7754                                            environment,
7755                                            SPOOLSS_DRIVER_PATH,
7756                                            &path);
7757         if (!W_ERROR_IS_OK(werr)) {
7758                 return werr;
7759         }
7760
7761         DEBUG(4,("printer driver directory: [%s]\n", path));
7762
7763         r->directory_name = path;
7764
7765         return WERR_OK;
7766 }
7767
7768 /****************************************************************
7769  _spoolss_GetPrinterDriverDirectory
7770 ****************************************************************/
7771
7772 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7773                                           struct spoolss_GetPrinterDriverDirectory *r)
7774 {
7775         WERROR werror;
7776
7777         /* that's an [in out] buffer */
7778
7779         if (!r->in.buffer && (r->in.offered != 0)) {
7780                 return WERR_INVALID_PARAM;
7781         }
7782
7783         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7784                 r->in.level));
7785
7786         *r->out.needed = 0;
7787
7788         /* r->in.level is ignored */
7789
7790         werror = getprinterdriverdir_level_1(p->mem_ctx,
7791                                              r->in.server,
7792                                              r->in.environment,
7793                                              &r->out.info->info1);
7794         if (!W_ERROR_IS_OK(werror)) {
7795                 TALLOC_FREE(r->out.info);
7796                 return werror;
7797         }
7798
7799         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7800                                                r->out.info, r->in.level);
7801         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7802
7803         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7804 }
7805
7806 /****************************************************************
7807  _spoolss_EnumPrinterData
7808 ****************************************************************/
7809
7810 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7811                                 struct spoolss_EnumPrinterData *r)
7812 {
7813         NT_PRINTER_INFO_LEVEL *printer = NULL;
7814         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7815         int             snum;
7816         WERROR          result;
7817         struct regval_blob      *val = NULL;
7818         NT_PRINTER_DATA *p_data;
7819         int             i, key_index, num_values;
7820         int             name_length;
7821
7822         *r->out.value_needed    = 0;
7823         *r->out.type            = REG_NONE;
7824         *r->out.data_needed     = 0;
7825
7826         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7827
7828         if (!Printer) {
7829                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7830                         OUR_HANDLE(r->in.handle)));
7831                 return WERR_BADFID;
7832         }
7833
7834         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7835                 return WERR_BADFID;
7836         }
7837
7838         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7839         if (!W_ERROR_IS_OK(result)) {
7840                 return result;
7841         }
7842
7843         p_data = printer->info_2->data;
7844         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7845
7846         result = WERR_OK;
7847
7848         /*
7849          * The NT machine wants to know the biggest size of value and data
7850          *
7851          * cf: MSDN EnumPrinterData remark section
7852          */
7853
7854         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7855
7856                 uint32_t biggest_valuesize = 0;
7857                 uint32_t biggest_datasize = 0;
7858
7859                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7860
7861                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7862
7863                 for ( i=0; i<num_values; i++ )
7864                 {
7865                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7866
7867                         name_length = strlen(val->valuename);
7868                         if ( strlen(val->valuename) > biggest_valuesize )
7869                                 biggest_valuesize = name_length;
7870
7871                         if ( val->size > biggest_datasize )
7872                                 biggest_datasize = val->size;
7873
7874                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7875                                 biggest_datasize));
7876                 }
7877
7878                 /* the value is an UNICODE string but real_value_size is the length
7879                    in bytes including the trailing 0 */
7880
7881                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7882                 *r->out.data_needed  = biggest_datasize;
7883
7884                 DEBUG(6,("final values: [%d], [%d]\n",
7885                         *r->out.value_needed, *r->out.data_needed));
7886
7887                 goto done;
7888         }
7889
7890         /*
7891          * the value len is wrong in NT sp3
7892          * that's the number of bytes not the number of unicode chars
7893          */
7894
7895         if (key_index != -1) {
7896                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7897                                                 r->in.enum_index);
7898         }
7899
7900         if (!val) {
7901
7902                 /* out_value should default to "" or else NT4 has
7903                    problems unmarshalling the response */
7904
7905                 if (r->in.value_offered) {
7906                         *r->out.value_needed = 1;
7907                         r->out.value_name = talloc_strdup(r, "");
7908                         if (!r->out.value_name) {
7909                                 result = WERR_NOMEM;
7910                                 goto done;
7911                         }
7912                 } else {
7913                         r->out.value_name = NULL;
7914                         *r->out.value_needed = 0;
7915                 }
7916
7917                 /* the data is counted in bytes */
7918
7919                 *r->out.data_needed = r->in.data_offered;
7920
7921                 result = WERR_NO_MORE_ITEMS;
7922         } else {
7923                 /*
7924                  * the value is:
7925                  * - counted in bytes in the request
7926                  * - counted in UNICODE chars in the max reply
7927                  * - counted in bytes in the real size
7928                  *
7929                  * take a pause *before* coding not *during* coding
7930                  */
7931
7932                 /* name */
7933                 if (r->in.value_offered) {
7934                         r->out.value_name = talloc_strdup(r, regval_name(val));
7935                         if (!r->out.value_name) {
7936                                 result = WERR_NOMEM;
7937                                 goto done;
7938                         }
7939                         *r->out.value_needed = strlen_m(regval_name(val));
7940                 } else {
7941                         r->out.value_name = NULL;
7942                         *r->out.value_needed = 0;
7943                 }
7944
7945                 /* type */
7946
7947                 *r->out.type = regval_type(val);
7948
7949                 /* data - counted in bytes */
7950
7951                 if (r->out.data && regval_size(val)) {
7952                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
7953                 }
7954
7955                 *r->out.data_needed = regval_size(val);
7956         }
7957
7958 done:
7959         free_a_printer(&printer, 2);
7960         return result;
7961 }
7962
7963 /****************************************************************
7964  _spoolss_SetPrinterData
7965 ****************************************************************/
7966
7967 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7968                                struct spoolss_SetPrinterData *r)
7969 {
7970         NT_PRINTER_INFO_LEVEL *printer = NULL;
7971         int snum=0;
7972         WERROR result = WERR_OK;
7973         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7974         DATA_BLOB blob;
7975
7976         DEBUG(5,("_spoolss_SetPrinterData\n"));
7977
7978         if (!Printer) {
7979                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7980                         OUR_HANDLE(r->in.handle)));
7981                 return WERR_BADFID;
7982         }
7983
7984         if (Printer->printer_type == SPLHND_SERVER) {
7985                 DEBUG(10,("_spoolss_SetPrinterData: "
7986                         "Not implemented for server handles yet\n"));
7987                 return WERR_INVALID_PARAM;
7988         }
7989
7990         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7991                 return WERR_BADFID;
7992         }
7993
7994         /*
7995          * Access check : NT returns "access denied" if you make a
7996          * SetPrinterData call without the necessary privildge.
7997          * we were originally returning OK if nothing changed
7998          * which made Win2k issue **a lot** of SetPrinterData
7999          * when connecting to a printer  --jerry
8000          */
8001
8002         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8003                 DEBUG(3,("_spoolss_SetPrinterData: "
8004                         "change denied by handle access permissions\n"));
8005                 result = WERR_ACCESS_DENIED;
8006                 goto done;
8007         }
8008
8009         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8010         if (!W_ERROR_IS_OK(result)) {
8011                 return result;
8012         }
8013
8014         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8015                                           r->in.type, &r->in.data);
8016         if (!W_ERROR_IS_OK(result)) {
8017                 goto done;
8018         }
8019
8020         /*
8021          * When client side code sets a magic printer data key, detect it and save
8022          * the current printer data and the magic key's data (its the DEVMODE) for
8023          * future printer/driver initializations.
8024          */
8025         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8026                 /* Set devmode and printer initialization info */
8027                 result = save_driver_init(printer, 2, blob.data, blob.length);
8028
8029                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8030
8031                 goto done;
8032         }
8033
8034         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8035                                     r->in.value_name, r->in.type,
8036                                     blob.data, blob.length);
8037         if (W_ERROR_IS_OK(result)) {
8038                 result = mod_a_printer(printer, 2);
8039         }
8040
8041 done:
8042         free_a_printer(&printer, 2);
8043
8044         return result;
8045 }
8046
8047 /****************************************************************
8048  _spoolss_ResetPrinter
8049 ****************************************************************/
8050
8051 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8052                              struct spoolss_ResetPrinter *r)
8053 {
8054         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8055         int             snum;
8056
8057         DEBUG(5,("_spoolss_ResetPrinter\n"));
8058
8059         /*
8060          * All we do is to check to see if the handle and queue is valid.
8061          * This call really doesn't mean anything to us because we only
8062          * support RAW printing.   --jerry
8063          */
8064
8065         if (!Printer) {
8066                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8067                         OUR_HANDLE(r->in.handle)));
8068                 return WERR_BADFID;
8069         }
8070
8071         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8072                 return WERR_BADFID;
8073
8074
8075         /* blindly return success */
8076         return WERR_OK;
8077 }
8078
8079 /****************************************************************
8080  _spoolss_DeletePrinterData
8081 ****************************************************************/
8082
8083 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8084                                   struct spoolss_DeletePrinterData *r)
8085 {
8086         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8087         int             snum=0;
8088         WERROR          status = WERR_OK;
8089         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8090
8091         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8092
8093         if (!Printer) {
8094                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8095                         OUR_HANDLE(r->in.handle)));
8096                 return WERR_BADFID;
8097         }
8098
8099         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8100                 return WERR_BADFID;
8101
8102         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8103                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8104                         "printer properties change denied by handle\n"));
8105                 return WERR_ACCESS_DENIED;
8106         }
8107
8108         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8109         if (!W_ERROR_IS_OK(status))
8110                 return status;
8111
8112         if (!r->in.value_name) {
8113                 free_a_printer(&printer, 2);
8114                 return WERR_NOMEM;
8115         }
8116
8117         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8118                                         r->in.value_name );
8119
8120         if ( W_ERROR_IS_OK(status) )
8121                 mod_a_printer( printer, 2 );
8122
8123         free_a_printer(&printer, 2);
8124
8125         return status;
8126 }
8127
8128 /****************************************************************
8129  _spoolss_AddForm
8130 ****************************************************************/
8131
8132 WERROR _spoolss_AddForm(pipes_struct *p,
8133                         struct spoolss_AddForm *r)
8134 {
8135         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8136         nt_forms_struct tmpForm;
8137         int snum = -1;
8138         WERROR status = WERR_OK;
8139         NT_PRINTER_INFO_LEVEL *printer = NULL;
8140         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8141
8142         int count=0;
8143         nt_forms_struct *list=NULL;
8144         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8145
8146         DEBUG(5,("_spoolss_AddForm\n"));
8147
8148         if (!Printer) {
8149                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8150                         OUR_HANDLE(r->in.handle)));
8151                 return WERR_BADFID;
8152         }
8153
8154
8155         /* forms can be added on printer of on the print server handle */
8156
8157         if ( Printer->printer_type == SPLHND_PRINTER )
8158         {
8159                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8160                         return WERR_BADFID;
8161
8162                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8163                 if (!W_ERROR_IS_OK(status))
8164                         goto done;
8165         }
8166
8167         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8168            and not a printer admin, then fail */
8169
8170         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8171              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8172              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8173                                           NULL, NULL,
8174                                           p->server_info->ptok,
8175                                           lp_printer_admin(snum))) {
8176                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8177                 return WERR_ACCESS_DENIED;
8178         }
8179
8180         /* can't add if builtin */
8181
8182         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8183                 status = WERR_FILE_EXISTS;
8184                 goto done;
8185         }
8186
8187         count = get_ntforms(&list);
8188
8189         if(!add_a_form(&list, form, &count)) {
8190                 status =  WERR_NOMEM;
8191                 goto done;
8192         }
8193
8194         become_root();
8195         write_ntforms(&list, count);
8196         unbecome_root();
8197
8198         /*
8199          * ChangeID must always be set if this is a printer
8200          */
8201
8202         if ( Printer->printer_type == SPLHND_PRINTER )
8203                 status = mod_a_printer(printer, 2);
8204
8205 done:
8206         if ( printer )
8207                 free_a_printer(&printer, 2);
8208         SAFE_FREE(list);
8209
8210         return status;
8211 }
8212
8213 /****************************************************************
8214  _spoolss_DeleteForm
8215 ****************************************************************/
8216
8217 WERROR _spoolss_DeleteForm(pipes_struct *p,
8218                            struct spoolss_DeleteForm *r)
8219 {
8220         const char *form_name = r->in.form_name;
8221         nt_forms_struct tmpForm;
8222         int count=0;
8223         nt_forms_struct *list=NULL;
8224         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8225         int snum = -1;
8226         WERROR status = WERR_OK;
8227         NT_PRINTER_INFO_LEVEL *printer = NULL;
8228         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8229         bool ret = false;
8230
8231         DEBUG(5,("_spoolss_DeleteForm\n"));
8232
8233         if (!Printer) {
8234                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8235                         OUR_HANDLE(r->in.handle)));
8236                 return WERR_BADFID;
8237         }
8238
8239         /* forms can be deleted on printer of on the print server handle */
8240
8241         if ( Printer->printer_type == SPLHND_PRINTER )
8242         {
8243                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8244                         return WERR_BADFID;
8245
8246                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8247                 if (!W_ERROR_IS_OK(status))
8248                         goto done;
8249         }
8250
8251         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8252              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8253              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8254                                           NULL, NULL,
8255                                           p->server_info->ptok,
8256                                           lp_printer_admin(snum))) {
8257                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8258                 return WERR_ACCESS_DENIED;
8259         }
8260
8261
8262         /* can't delete if builtin */
8263
8264         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8265                 status = WERR_INVALID_PARAM;
8266                 goto done;
8267         }
8268
8269         count = get_ntforms(&list);
8270
8271         become_root();
8272         ret = delete_a_form(&list, form_name, &count, &status);
8273         unbecome_root();
8274         if (ret == false) {
8275                 goto done;
8276         }
8277
8278         /*
8279          * ChangeID must always be set if this is a printer
8280          */
8281
8282         if ( Printer->printer_type == SPLHND_PRINTER )
8283                 status = mod_a_printer(printer, 2);
8284
8285 done:
8286         if ( printer )
8287                 free_a_printer(&printer, 2);
8288         SAFE_FREE(list);
8289
8290         return status;
8291 }
8292
8293 /****************************************************************
8294  _spoolss_SetForm
8295 ****************************************************************/
8296
8297 WERROR _spoolss_SetForm(pipes_struct *p,
8298                         struct spoolss_SetForm *r)
8299 {
8300         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8301         nt_forms_struct tmpForm;
8302         int snum = -1;
8303         WERROR status = WERR_OK;
8304         NT_PRINTER_INFO_LEVEL *printer = NULL;
8305         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8306
8307         int count=0;
8308         nt_forms_struct *list=NULL;
8309         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8310
8311         DEBUG(5,("_spoolss_SetForm\n"));
8312
8313         if (!Printer) {
8314                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8315                         OUR_HANDLE(r->in.handle)));
8316                 return WERR_BADFID;
8317         }
8318
8319         /* forms can be modified on printer of on the print server handle */
8320
8321         if ( Printer->printer_type == SPLHND_PRINTER )
8322         {
8323                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8324                         return WERR_BADFID;
8325
8326                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8327                 if (!W_ERROR_IS_OK(status))
8328                         goto done;
8329         }
8330
8331         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8332            and not a printer admin, then fail */
8333
8334         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8335              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8336              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8337                                           NULL, NULL,
8338                                           p->server_info->ptok,
8339                                           lp_printer_admin(snum))) {
8340                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8341                 return WERR_ACCESS_DENIED;
8342         }
8343
8344         /* can't set if builtin */
8345         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8346                 status = WERR_INVALID_PARAM;
8347                 goto done;
8348         }
8349
8350         count = get_ntforms(&list);
8351         update_a_form(&list, form, count);
8352         become_root();
8353         write_ntforms(&list, count);
8354         unbecome_root();
8355
8356         /*
8357          * ChangeID must always be set if this is a printer
8358          */
8359
8360         if ( Printer->printer_type == SPLHND_PRINTER )
8361                 status = mod_a_printer(printer, 2);
8362
8363
8364 done:
8365         if ( printer )
8366                 free_a_printer(&printer, 2);
8367         SAFE_FREE(list);
8368
8369         return status;
8370 }
8371
8372 /****************************************************************************
8373  fill_print_processor1
8374 ****************************************************************************/
8375
8376 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8377                                     struct spoolss_PrintProcessorInfo1 *r,
8378                                     const char *print_processor_name)
8379 {
8380         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8381         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8382
8383         return WERR_OK;
8384 }
8385
8386 /****************************************************************************
8387  enumprintprocessors level 1.
8388 ****************************************************************************/
8389
8390 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8391                                           union spoolss_PrintProcessorInfo **info_p,
8392                                           uint32_t *count)
8393 {
8394         union spoolss_PrintProcessorInfo *info;
8395         WERROR result;
8396
8397         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8398         W_ERROR_HAVE_NO_MEMORY(info);
8399
8400         *count = 1;
8401
8402         result = fill_print_processor1(info, &info[0].info1, "winprint");
8403         if (!W_ERROR_IS_OK(result)) {
8404                 goto out;
8405         }
8406
8407  out:
8408         if (!W_ERROR_IS_OK(result)) {
8409                 TALLOC_FREE(info);
8410                 *count = 0;
8411                 return result;
8412         }
8413
8414         *info_p = info;
8415
8416         return WERR_OK;
8417 }
8418
8419 /****************************************************************
8420  _spoolss_EnumPrintProcessors
8421 ****************************************************************/
8422
8423 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8424                                     struct spoolss_EnumPrintProcessors *r)
8425 {
8426         WERROR result;
8427
8428         /* that's an [in out] buffer */
8429
8430         if (!r->in.buffer && (r->in.offered != 0)) {
8431                 return WERR_INVALID_PARAM;
8432         }
8433
8434         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8435
8436         /*
8437          * Enumerate the print processors ...
8438          *
8439          * Just reply with "winprint", to keep NT happy
8440          * and I can use my nice printer checker.
8441          */
8442
8443         *r->out.count = 0;
8444         *r->out.needed = 0;
8445         *r->out.info = NULL;
8446
8447         switch (r->in.level) {
8448         case 1:
8449                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8450                                                      r->out.count);
8451                 break;
8452         default:
8453                 return WERR_UNKNOWN_LEVEL;
8454         }
8455
8456         if (!W_ERROR_IS_OK(result)) {
8457                 return result;
8458         }
8459
8460         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8461                                                      spoolss_EnumPrintProcessors, NULL,
8462                                                      *r->out.info, r->in.level,
8463                                                      *r->out.count);
8464         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8465         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8466
8467         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8468 }
8469
8470 /****************************************************************************
8471  fill_printprocdatatype1
8472 ****************************************************************************/
8473
8474 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8475                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8476                                       const char *name_array)
8477 {
8478         r->name_array = talloc_strdup(mem_ctx, name_array);
8479         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8480
8481         return WERR_OK;
8482 }
8483
8484 /****************************************************************************
8485  enumprintprocdatatypes level 1.
8486 ****************************************************************************/
8487
8488 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8489                                              union spoolss_PrintProcDataTypesInfo **info_p,
8490                                              uint32_t *count)
8491 {
8492         WERROR result;
8493         union spoolss_PrintProcDataTypesInfo *info;
8494
8495         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8496         W_ERROR_HAVE_NO_MEMORY(info);
8497
8498         *count = 1;
8499
8500         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8501         if (!W_ERROR_IS_OK(result)) {
8502                 goto out;
8503         }
8504
8505  out:
8506         if (!W_ERROR_IS_OK(result)) {
8507                 TALLOC_FREE(info);
8508                 *count = 0;
8509                 return result;
8510         }
8511
8512         *info_p = info;
8513
8514         return WERR_OK;
8515 }
8516
8517 /****************************************************************
8518  _spoolss_EnumPrintProcDataTypes
8519 ****************************************************************/
8520
8521 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8522                                        struct spoolss_EnumPrintProcDataTypes *r)
8523 {
8524         WERROR result;
8525
8526         /* that's an [in out] buffer */
8527
8528         if (!r->in.buffer && (r->in.offered != 0)) {
8529                 return WERR_INVALID_PARAM;
8530         }
8531
8532         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8533
8534         *r->out.count = 0;
8535         *r->out.needed = 0;
8536         *r->out.info = NULL;
8537
8538         switch (r->in.level) {
8539         case 1:
8540                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8541                                                         r->out.count);
8542                 break;
8543         default:
8544                 return WERR_UNKNOWN_LEVEL;
8545         }
8546
8547         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8548                                                      spoolss_EnumPrintProcDataTypes, NULL,
8549                                                      *r->out.info, r->in.level,
8550                                                      *r->out.count);
8551         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8552         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8553
8554         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8555 }
8556
8557 /****************************************************************************
8558  fill_monitor_1
8559 ****************************************************************************/
8560
8561 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8562                              struct spoolss_MonitorInfo1 *r,
8563                              const char *monitor_name)
8564 {
8565         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8566         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8567
8568         return WERR_OK;
8569 }
8570
8571 /****************************************************************************
8572  fill_monitor_2
8573 ****************************************************************************/
8574
8575 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8576                              struct spoolss_MonitorInfo2 *r,
8577                              const char *monitor_name,
8578                              const char *environment,
8579                              const char *dll_name)
8580 {
8581         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8582         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8583         r->environment                  = talloc_strdup(mem_ctx, environment);
8584         W_ERROR_HAVE_NO_MEMORY(r->environment);
8585         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8586         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8587
8588         return WERR_OK;
8589 }
8590
8591 /****************************************************************************
8592  enumprintmonitors level 1.
8593 ****************************************************************************/
8594
8595 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8596                                         union spoolss_MonitorInfo **info_p,
8597                                         uint32_t *count)
8598 {
8599         union spoolss_MonitorInfo *info;
8600         WERROR result = WERR_OK;
8601
8602         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8603         W_ERROR_HAVE_NO_MEMORY(info);
8604
8605         *count = 2;
8606
8607         result = fill_monitor_1(info, &info[0].info1,
8608                                 SPL_LOCAL_PORT);
8609         if (!W_ERROR_IS_OK(result)) {
8610                 goto out;
8611         }
8612
8613         result = fill_monitor_1(info, &info[1].info1,
8614                                 SPL_TCPIP_PORT);
8615         if (!W_ERROR_IS_OK(result)) {
8616                 goto out;
8617         }
8618
8619 out:
8620         if (!W_ERROR_IS_OK(result)) {
8621                 TALLOC_FREE(info);
8622                 *count = 0;
8623                 return result;
8624         }
8625
8626         *info_p = info;
8627
8628         return WERR_OK;
8629 }
8630
8631 /****************************************************************************
8632  enumprintmonitors level 2.
8633 ****************************************************************************/
8634
8635 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8636                                         union spoolss_MonitorInfo **info_p,
8637                                         uint32_t *count)
8638 {
8639         union spoolss_MonitorInfo *info;
8640         WERROR result = WERR_OK;
8641
8642         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8643         W_ERROR_HAVE_NO_MEMORY(info);
8644
8645         *count = 2;
8646
8647         result = fill_monitor_2(info, &info[0].info2,
8648                                 SPL_LOCAL_PORT,
8649                                 "Windows NT X86", /* FIXME */
8650                                 "localmon.dll");
8651         if (!W_ERROR_IS_OK(result)) {
8652                 goto out;
8653         }
8654
8655         result = fill_monitor_2(info, &info[1].info2,
8656                                 SPL_TCPIP_PORT,
8657                                 "Windows NT X86", /* FIXME */
8658                                 "tcpmon.dll");
8659         if (!W_ERROR_IS_OK(result)) {
8660                 goto out;
8661         }
8662
8663 out:
8664         if (!W_ERROR_IS_OK(result)) {
8665                 TALLOC_FREE(info);
8666                 *count = 0;
8667                 return result;
8668         }
8669
8670         *info_p = info;
8671
8672         return WERR_OK;
8673 }
8674
8675 /****************************************************************
8676  _spoolss_EnumMonitors
8677 ****************************************************************/
8678
8679 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8680                              struct spoolss_EnumMonitors *r)
8681 {
8682         WERROR result;
8683
8684         /* that's an [in out] buffer */
8685
8686         if (!r->in.buffer && (r->in.offered != 0)) {
8687                 return WERR_INVALID_PARAM;
8688         }
8689
8690         DEBUG(5,("_spoolss_EnumMonitors\n"));
8691
8692         /*
8693          * Enumerate the print monitors ...
8694          *
8695          * Just reply with "Local Port", to keep NT happy
8696          * and I can use my nice printer checker.
8697          */
8698
8699         *r->out.count = 0;
8700         *r->out.needed = 0;
8701         *r->out.info = NULL;
8702
8703         switch (r->in.level) {
8704         case 1:
8705                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8706                                                    r->out.count);
8707                 break;
8708         case 2:
8709                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8710                                                    r->out.count);
8711                 break;
8712         default:
8713                 return WERR_UNKNOWN_LEVEL;
8714         }
8715
8716         if (!W_ERROR_IS_OK(result)) {
8717                 return result;
8718         }
8719
8720         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8721                                                      spoolss_EnumMonitors, NULL,
8722                                                      *r->out.info, r->in.level,
8723                                                      *r->out.count);
8724         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8725         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8726
8727         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8728 }
8729
8730 /****************************************************************************
8731 ****************************************************************************/
8732
8733 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8734                              const print_queue_struct *queue,
8735                              int count, int snum,
8736                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8737                              uint32_t jobid,
8738                              struct spoolss_JobInfo1 *r)
8739 {
8740         int i = 0;
8741         bool found = false;
8742
8743         for (i=0; i<count && found == false; i++) {
8744                 if (queue[i].job == (int)jobid) {
8745                         found = true;
8746                 }
8747         }
8748
8749         if (found == false) {
8750                 /* NT treats not found as bad param... yet another bad choice */
8751                 return WERR_INVALID_PARAM;
8752         }
8753
8754         return fill_job_info1(mem_ctx,
8755                               r,
8756                               &queue[i-1],
8757                               i,
8758                               snum,
8759                               ntprinter);
8760 }
8761
8762 /****************************************************************************
8763 ****************************************************************************/
8764
8765 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8766                              const print_queue_struct *queue,
8767                              int count, int snum,
8768                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8769                              uint32_t jobid,
8770                              struct spoolss_JobInfo2 *r)
8771 {
8772         int i = 0;
8773         bool found = false;
8774         struct spoolss_DeviceMode *devmode;
8775         NT_DEVICEMODE *nt_devmode;
8776         WERROR result;
8777
8778         for (i=0; i<count && found == false; i++) {
8779                 if (queue[i].job == (int)jobid) {
8780                         found = true;
8781                 }
8782         }
8783
8784         if (found == false) {
8785                 /* NT treats not found as bad param... yet another bad
8786                    choice */
8787                 return WERR_INVALID_PARAM;
8788         }
8789
8790         /*
8791          * if the print job does not have a DEVMODE associated with it,
8792          * just use the one for the printer. A NULL devicemode is not
8793          *  a failure condition
8794          */
8795
8796         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8797         if (nt_devmode) {
8798                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8799                 W_ERROR_HAVE_NO_MEMORY(devmode);
8800                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8801                 if (!W_ERROR_IS_OK(result)) {
8802                         return result;
8803                 }
8804         } else {
8805                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8806                 W_ERROR_HAVE_NO_MEMORY(devmode);
8807         }
8808
8809         return fill_job_info2(mem_ctx,
8810                               r,
8811                               &queue[i-1],
8812                               i,
8813                               snum,
8814                               ntprinter,
8815                               devmode);
8816 }
8817
8818 /****************************************************************
8819  _spoolss_GetJob
8820 ****************************************************************/
8821
8822 WERROR _spoolss_GetJob(pipes_struct *p,
8823                        struct spoolss_GetJob *r)
8824 {
8825         WERROR result = WERR_OK;
8826         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8827         int snum;
8828         int count;
8829         print_queue_struct      *queue = NULL;
8830         print_status_struct prt_status;
8831
8832         /* that's an [in out] buffer */
8833
8834         if (!r->in.buffer && (r->in.offered != 0)) {
8835                 return WERR_INVALID_PARAM;
8836         }
8837
8838         DEBUG(5,("_spoolss_GetJob\n"));
8839
8840         *r->out.needed = 0;
8841
8842         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8843                 return WERR_BADFID;
8844         }
8845
8846         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8847         if (!W_ERROR_IS_OK(result)) {
8848                 return result;
8849         }
8850
8851         count = print_queue_status(snum, &queue, &prt_status);
8852
8853         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8854                      count, prt_status.status, prt_status.message));
8855
8856         switch (r->in.level) {
8857         case 1:
8858                 result = getjob_level_1(p->mem_ctx,
8859                                         queue, count, snum, ntprinter,
8860                                         r->in.job_id, &r->out.info->info1);
8861                 break;
8862         case 2:
8863                 result = getjob_level_2(p->mem_ctx,
8864                                         queue, count, snum, ntprinter,
8865                                         r->in.job_id, &r->out.info->info2);
8866                 break;
8867         default:
8868                 result = WERR_UNKNOWN_LEVEL;
8869                 break;
8870         }
8871
8872         SAFE_FREE(queue);
8873         free_a_printer(&ntprinter, 2);
8874
8875         if (!W_ERROR_IS_OK(result)) {
8876                 TALLOC_FREE(r->out.info);
8877                 return result;
8878         }
8879
8880         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8881                                                r->out.info, r->in.level);
8882         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8883
8884         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8885 }
8886
8887 /****************************************************************
8888  _spoolss_GetPrinterDataEx
8889
8890  From MSDN documentation of GetPrinterDataEx: pass request
8891  to GetPrinterData if key is "PrinterDriverData".
8892 ****************************************************************/
8893
8894 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8895                                  struct spoolss_GetPrinterDataEx *r)
8896 {
8897
8898         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8899         struct regval_blob              *val = NULL;
8900         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8901         int                     snum = 0;
8902         WERROR result = WERR_OK;
8903
8904         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8905
8906         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8907                 r->in.key_name, r->in.value_name));
8908
8909         /* in case of problem, return some default values */
8910
8911         *r->out.needed  = 0;
8912         *r->out.type    = REG_NONE;
8913
8914         if (!Printer) {
8915                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8916                         OUR_HANDLE(r->in.handle)));
8917                 result = WERR_BADFID;
8918                 goto done;
8919         }
8920
8921         /* Is the handle to a printer or to the server? */
8922
8923         if (Printer->printer_type == SPLHND_SERVER) {
8924                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8925                         "Not implemented for server handles yet\n"));
8926                 result = WERR_INVALID_PARAM;
8927                 goto done;
8928         }
8929
8930         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8931                 return WERR_BADFID;
8932         }
8933
8934         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8935         if (!W_ERROR_IS_OK(result)) {
8936                 goto done;
8937         }
8938
8939         /* check to see if the keyname is valid */
8940         if (!strlen(r->in.key_name)) {
8941                 result = WERR_INVALID_PARAM;
8942                 goto done;
8943         }
8944
8945         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8946                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8947                         "Invalid keyname [%s]\n", r->in.key_name ));
8948                 result = WERR_BADFILE;
8949                 goto done;
8950         }
8951
8952         /* When given a new keyname, we should just create it */
8953
8954         val = get_printer_data(printer->info_2,
8955                                r->in.key_name, r->in.value_name);
8956         if (!val) {
8957                 result = WERR_BADFILE;
8958                 goto done;
8959         }
8960
8961         *r->out.needed = regval_size(val);
8962
8963         if (*r->out.needed > r->in.offered) {
8964                 result = WERR_MORE_DATA;
8965                 goto done;
8966         }
8967
8968         *r->out.type = regval_type(val);
8969
8970         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
8971
8972  done:
8973         if (printer) {
8974                 free_a_printer(&printer, 2);
8975         }
8976
8977         return result;
8978 }
8979
8980 /****************************************************************
8981  _spoolss_SetPrinterDataEx
8982 ****************************************************************/
8983
8984 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8985                                  struct spoolss_SetPrinterDataEx *r)
8986 {
8987         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8988         int                     snum = 0;
8989         WERROR                  result = WERR_OK;
8990         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8991         char                    *oid_string;
8992
8993         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8994
8995         /* From MSDN documentation of SetPrinterDataEx: pass request to
8996            SetPrinterData if key is "PrinterDriverData" */
8997
8998         if (!Printer) {
8999                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9000                         OUR_HANDLE(r->in.handle)));
9001                 return WERR_BADFID;
9002         }
9003
9004         if (Printer->printer_type == SPLHND_SERVER) {
9005                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9006                         "Not implemented for server handles yet\n"));
9007                 return WERR_INVALID_PARAM;
9008         }
9009
9010         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9011                 return WERR_BADFID;
9012         }
9013
9014         /*
9015          * Access check : NT returns "access denied" if you make a
9016          * SetPrinterData call without the necessary privildge.
9017          * we were originally returning OK if nothing changed
9018          * which made Win2k issue **a lot** of SetPrinterData
9019          * when connecting to a printer  --jerry
9020          */
9021
9022         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9023                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9024                         "change denied by handle access permissions\n"));
9025                 return WERR_ACCESS_DENIED;
9026         }
9027
9028         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9029         if (!W_ERROR_IS_OK(result)) {
9030                 return result;
9031         }
9032
9033         /* check for OID in valuename */
9034
9035         oid_string = strchr(r->in.value_name, ',');
9036         if (oid_string) {
9037                 *oid_string = '\0';
9038                 oid_string++;
9039         }
9040
9041         /* save the registry data */
9042
9043         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9044                                     r->in.type, r->in.buffer, r->in.offered);
9045
9046         if (W_ERROR_IS_OK(result)) {
9047                 /* save the OID if one was specified */
9048                 if (oid_string) {
9049                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9050                                 r->in.key_name, SPOOL_OID_KEY);
9051                         if (!str) {
9052                                 result = WERR_NOMEM;
9053                                 goto done;
9054                         }
9055
9056                         /*
9057                          * I'm not checking the status here on purpose.  Don't know
9058                          * if this is right, but I'm returning the status from the
9059                          * previous set_printer_dataex() call.  I have no idea if
9060                          * this is right.    --jerry
9061                          */
9062
9063                         set_printer_dataex(printer, str, r->in.value_name,
9064                                            REG_SZ, (uint8_t *)oid_string,
9065                                            strlen(oid_string)+1);
9066                 }
9067
9068                 result = mod_a_printer(printer, 2);
9069         }
9070
9071  done:
9072         free_a_printer(&printer, 2);
9073
9074         return result;
9075 }
9076
9077 /****************************************************************
9078  _spoolss_DeletePrinterDataEx
9079 ****************************************************************/
9080
9081 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9082                                     struct spoolss_DeletePrinterDataEx *r)
9083 {
9084         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9085         int             snum=0;
9086         WERROR          status = WERR_OK;
9087         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9088
9089         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9090
9091         if (!Printer) {
9092                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9093                         "Invalid handle (%s:%u:%u).\n",
9094                         OUR_HANDLE(r->in.handle)));
9095                 return WERR_BADFID;
9096         }
9097
9098         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9099                 return WERR_BADFID;
9100
9101         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9102                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9103                         "printer properties change denied by handle\n"));
9104                 return WERR_ACCESS_DENIED;
9105         }
9106
9107         if (!r->in.value_name || !r->in.key_name) {
9108                 return WERR_NOMEM;
9109         }
9110
9111         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9112         if (!W_ERROR_IS_OK(status))
9113                 return status;
9114
9115         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9116
9117         if ( W_ERROR_IS_OK(status) )
9118                 mod_a_printer( printer, 2 );
9119
9120         free_a_printer(&printer, 2);
9121
9122         return status;
9123 }
9124
9125 /****************************************************************
9126  _spoolss_EnumPrinterKey
9127 ****************************************************************/
9128
9129 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9130                                struct spoolss_EnumPrinterKey *r)
9131 {
9132         fstring         *keynames = NULL;
9133         int             num_keys;
9134         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9135         NT_PRINTER_DATA *data;
9136         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9137         int             snum = 0;
9138         WERROR          result = WERR_BADFILE;
9139         int i;
9140         const char **array = NULL;
9141         DATA_BLOB blob;
9142
9143         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9144
9145         if (!Printer) {
9146                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9147                         OUR_HANDLE(r->in.handle)));
9148                 return WERR_BADFID;
9149         }
9150
9151         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9152                 return WERR_BADFID;
9153         }
9154
9155         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9156         if (!W_ERROR_IS_OK(result)) {
9157                 return result;
9158         }
9159
9160         /* get the list of subkey names */
9161
9162         data = printer->info_2->data;
9163
9164         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9165         if (num_keys == -1) {
9166                 result = WERR_BADFILE;
9167                 goto done;
9168         }
9169
9170         /* two byte termination (a multisz) */
9171
9172         *r->out.needed = 2;
9173
9174         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9175         if (!array) {
9176                 result = WERR_NOMEM;
9177                 goto done;
9178         }
9179
9180         for (i=0; i < num_keys; i++) {
9181
9182                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9183                         keynames[i]));
9184
9185                 array[i] = talloc_strdup(array, keynames[i]);
9186                 if (!array[i]) {
9187                         result = WERR_NOMEM;
9188                         goto done;
9189                 }
9190
9191                 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9192         }
9193
9194         if (r->in.offered < *r->out.needed) {
9195                 result = WERR_MORE_DATA;
9196                 goto done;
9197         }
9198
9199         result = WERR_OK;
9200
9201         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9202                 result = WERR_NOMEM;
9203                 goto done;
9204         }
9205
9206         if (r->in.offered == blob.length) {
9207                 memcpy(r->out.key_buffer, blob.data, blob.length);
9208         }
9209
9210  done:
9211         if (!W_ERROR_IS_OK(result)) {
9212                 TALLOC_FREE(array);
9213                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9214                         *r->out.needed = 0;
9215                 }
9216         }
9217
9218         free_a_printer(&printer, 2);
9219         SAFE_FREE(keynames);
9220
9221         return result;
9222 }
9223
9224 /****************************************************************
9225  _spoolss_DeletePrinterKey
9226 ****************************************************************/
9227
9228 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9229                                  struct spoolss_DeletePrinterKey *r)
9230 {
9231         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9232         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9233         int                     snum=0;
9234         WERROR                  status;
9235
9236         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9237
9238         if (!Printer) {
9239                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9240                         OUR_HANDLE(r->in.handle)));
9241                 return WERR_BADFID;
9242         }
9243
9244         /* if keyname == NULL, return error */
9245
9246         if ( !r->in.key_name )
9247                 return WERR_INVALID_PARAM;
9248
9249         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9250                 return WERR_BADFID;
9251
9252         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9253                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9254                         "printer properties change denied by handle\n"));
9255                 return WERR_ACCESS_DENIED;
9256         }
9257
9258         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9259         if (!W_ERROR_IS_OK(status))
9260                 return status;
9261
9262         /* delete the key and all subneys */
9263
9264         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9265
9266         if ( W_ERROR_IS_OK(status) )
9267                 status = mod_a_printer(printer, 2);
9268
9269         free_a_printer( &printer, 2 );
9270
9271         return status;
9272 }
9273
9274 /****************************************************************
9275 ****************************************************************/
9276
9277 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9278                                                    struct regval_blob *v,
9279                                                    struct spoolss_PrinterEnumValues *r)
9280 {
9281         WERROR result;
9282
9283         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9284         W_ERROR_HAVE_NO_MEMORY(r->data);
9285
9286         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9287         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9288
9289         r->type         = regval_type(v);
9290         r->data_length  = regval_size(v);
9291
9292         if (r->data_length) {
9293                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9294                                                  regval_size(v));
9295                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9296                                                   r->data,
9297                                                   r->type);
9298                 if (!W_ERROR_IS_OK(result)) {
9299                         return result;
9300                 }
9301         }
9302
9303         return WERR_OK;
9304 }
9305
9306 /****************************************************************
9307  _spoolss_EnumPrinterDataEx
9308 ****************************************************************/
9309
9310 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9311                                   struct spoolss_EnumPrinterDataEx *r)
9312 {
9313         uint32_t        count = 0;
9314         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9315         struct spoolss_PrinterEnumValues *info = NULL;
9316         NT_PRINTER_DATA         *p_data;
9317         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9318         int             snum;
9319         WERROR          result;
9320         int             key_index;
9321         int             i;
9322
9323         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9324
9325         *r->out.count = 0;
9326         *r->out.needed = 0;
9327         *r->out.info = NULL;
9328
9329         if (!Printer) {
9330                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9331                         OUR_HANDLE(r->in.handle)));
9332                 return WERR_BADFID;
9333         }
9334
9335         /*
9336          * first check for a keyname of NULL or "".  Win2k seems to send
9337          * this a lot and we should send back WERR_INVALID_PARAM
9338          * no need to spend time looking up the printer in this case.
9339          * --jerry
9340          */
9341
9342         if (!strlen(r->in.key_name)) {
9343                 result = WERR_INVALID_PARAM;
9344                 goto done;
9345         }
9346
9347         /* get the printer off of disk */
9348
9349         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9350                 return WERR_BADFID;
9351         }
9352
9353         ZERO_STRUCT(printer);
9354         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9355         if (!W_ERROR_IS_OK(result)) {
9356                 return result;
9357         }
9358
9359         /* now look for a match on the key name */
9360
9361         p_data = printer->info_2->data;
9362
9363         key_index = lookup_printerkey(p_data, r->in.key_name);
9364         if (key_index == -1) {
9365                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9366                         r->in.key_name));
9367                 result = WERR_INVALID_PARAM;
9368                 goto done;
9369         }
9370
9371         /* allocate the memory for the array of pointers -- if necessary */
9372
9373         count = regval_ctr_numvals(p_data->keys[key_index].values);
9374         if (!count) {
9375                 result = WERR_OK; /* ??? */
9376                 goto done;
9377         }
9378
9379         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9380                                  struct spoolss_PrinterEnumValues,
9381                                  count);
9382         if (!info) {
9383                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9384                 result = WERR_NOMEM;
9385                 goto done;
9386         }
9387
9388         /*
9389          * loop through all params and build the array to pass
9390          * back to the  client
9391          */
9392
9393         for (i=0; i < count; i++) {
9394
9395                 struct regval_blob      *val;
9396
9397                 /* lookup the registry value */
9398
9399                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9400
9401                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9402
9403                 /* copy the data */
9404
9405                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9406                 if (!W_ERROR_IS_OK(result)) {
9407                         goto done;
9408                 }
9409         }
9410
9411 #if 0 /* FIXME - gd */
9412         /* housekeeping information in the reply */
9413
9414         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9415          * the hand marshalled container size is a multiple
9416          * of 4 bytes for RPC alignment.
9417          */
9418
9419         if (needed % 4) {
9420                 needed += 4-(needed % 4);
9421         }
9422 #endif
9423         *r->out.count   = count;
9424         *r->out.info    = info;
9425
9426  done:
9427
9428         if (printer) {
9429                 free_a_printer(&printer, 2);
9430         }
9431
9432         if (!W_ERROR_IS_OK(result)) {
9433                 return result;
9434         }
9435
9436         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9437                                                spoolss_EnumPrinterDataEx, NULL,
9438                                                *r->out.info,
9439                                                *r->out.count);
9440         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9441         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9442
9443         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9444 }
9445
9446 /****************************************************************************
9447 ****************************************************************************/
9448
9449 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9450                                                  const char *servername,
9451                                                  const char *environment,
9452                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9453 {
9454         WERROR werr;
9455         char *path = NULL;
9456
9457         werr = compose_spoolss_server_path(mem_ctx,
9458                                            servername,
9459                                            environment,
9460                                            SPOOLSS_PRTPROCS_PATH,
9461                                            &path);
9462         if (!W_ERROR_IS_OK(werr)) {
9463                 return werr;
9464         }
9465
9466         DEBUG(4,("print processor directory: [%s]\n", path));
9467
9468         r->directory_name = path;
9469
9470         return WERR_OK;
9471 }
9472
9473 /****************************************************************
9474  _spoolss_GetPrintProcessorDirectory
9475 ****************************************************************/
9476
9477 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9478                                            struct spoolss_GetPrintProcessorDirectory *r)
9479 {
9480         WERROR result;
9481
9482         /* that's an [in out] buffer */
9483
9484         if (!r->in.buffer && (r->in.offered != 0)) {
9485                 return WERR_INVALID_PARAM;
9486         }
9487
9488         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9489                 r->in.level));
9490
9491         *r->out.needed = 0;
9492
9493         /* r->in.level is ignored */
9494
9495         /* We always should reply with a local print processor directory so that
9496          * users are not forced to have a [prnproc$] share on the Samba spoolss
9497          * server - Guenther */
9498
9499         result = getprintprocessordirectory_level_1(p->mem_ctx,
9500                                                     NULL, /* r->in.server */
9501                                                     r->in.environment,
9502                                                     &r->out.info->info1);
9503         if (!W_ERROR_IS_OK(result)) {
9504                 TALLOC_FREE(r->out.info);
9505                 return result;
9506         }
9507
9508         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9509                                                r->out.info, r->in.level);
9510         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9511
9512         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9513 }
9514
9515 /*******************************************************************
9516  ********************************************************************/
9517
9518 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9519                                const char *dllname)
9520 {
9521         enum ndr_err_code ndr_err;
9522         struct spoolss_MonitorUi ui;
9523
9524         ui.dll_name = dllname;
9525
9526         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9527                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9528         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9529                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9530         }
9531         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9532 }
9533
9534 /*******************************************************************
9535  Streams the monitor UI DLL name in UNICODE
9536 *******************************************************************/
9537
9538 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9539                                NT_USER_TOKEN *token, DATA_BLOB *in,
9540                                DATA_BLOB *out, uint32_t *needed)
9541 {
9542         const char *dllname = "tcpmonui.dll";
9543
9544         *needed = (strlen(dllname)+1) * 2;
9545
9546         if (out->length < *needed) {
9547                 return WERR_INSUFFICIENT_BUFFER;
9548         }
9549
9550         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9551                 return WERR_NOMEM;
9552         }
9553
9554         return WERR_OK;
9555 }
9556
9557 /*******************************************************************
9558  ********************************************************************/
9559
9560 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9561                              struct spoolss_PortData1 *port1,
9562                              const DATA_BLOB *buf)
9563 {
9564         enum ndr_err_code ndr_err;
9565         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9566                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9567         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9568                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9569         }
9570         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9571 }
9572
9573 /*******************************************************************
9574  ********************************************************************/
9575
9576 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9577                              struct spoolss_PortData2 *port2,
9578                              const DATA_BLOB *buf)
9579 {
9580         enum ndr_err_code ndr_err;
9581         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9582                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9583         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9584                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9585         }
9586         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9587 }
9588
9589 /*******************************************************************
9590  Create a new TCP/IP port
9591 *******************************************************************/
9592
9593 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9594                              NT_USER_TOKEN *token, DATA_BLOB *in,
9595                              DATA_BLOB *out, uint32_t *needed)
9596 {
9597         struct spoolss_PortData1 port1;
9598         struct spoolss_PortData2 port2;
9599         char *device_uri = NULL;
9600         uint32_t version;
9601
9602         const char *portname;
9603         const char *hostaddress;
9604         const char *queue;
9605         uint32_t port_number;
9606         uint32_t protocol;
9607
9608         /* peek for spoolss_PortData version */
9609
9610         if (!in || (in->length < (128 + 4))) {
9611                 return WERR_GENERAL_FAILURE;
9612         }
9613
9614         version = IVAL(in->data, 128);
9615
9616         switch (version) {
9617                 case 1:
9618                         ZERO_STRUCT(port1);
9619
9620                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9621                                 return WERR_NOMEM;
9622                         }
9623
9624                         portname        = port1.portname;
9625                         hostaddress     = port1.hostaddress;
9626                         queue           = port1.queue;
9627                         protocol        = port1.protocol;
9628                         port_number     = port1.port_number;
9629
9630                         break;
9631                 case 2:
9632                         ZERO_STRUCT(port2);
9633
9634                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9635                                 return WERR_NOMEM;
9636                         }
9637
9638                         portname        = port2.portname;
9639                         hostaddress     = port2.hostaddress;
9640                         queue           = port2.queue;
9641                         protocol        = port2.protocol;
9642                         port_number     = port2.port_number;
9643
9644                         break;
9645                 default:
9646                         DEBUG(1,("xcvtcp_addport: "
9647                                 "unknown version of port_data: %d\n", version));
9648                         return WERR_UNKNOWN_PORT;
9649         }
9650
9651         /* create the device URI and call the add_port_hook() */
9652
9653         switch (protocol) {
9654         case PROTOCOL_RAWTCP_TYPE:
9655                 device_uri = talloc_asprintf(mem_ctx,
9656                                 "socket://%s:%d/", hostaddress,
9657                                 port_number);
9658                 break;
9659
9660         case PROTOCOL_LPR_TYPE:
9661                 device_uri = talloc_asprintf(mem_ctx,
9662                         "lpr://%s/%s", hostaddress, queue );
9663                 break;
9664
9665         default:
9666                 return WERR_UNKNOWN_PORT;
9667         }
9668
9669         if (!device_uri) {
9670                 return WERR_NOMEM;
9671         }
9672
9673         return add_port_hook(mem_ctx, token, portname, device_uri);
9674 }
9675
9676 /*******************************************************************
9677 *******************************************************************/
9678
9679 struct xcv_api_table xcvtcp_cmds[] = {
9680         { "MonitorUI",  xcvtcp_monitorui },
9681         { "AddPort",    xcvtcp_addport},
9682         { NULL,         NULL }
9683 };
9684
9685 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9686                                      NT_USER_TOKEN *token, const char *command,
9687                                      DATA_BLOB *inbuf,
9688                                      DATA_BLOB *outbuf,
9689                                      uint32_t *needed )
9690 {
9691         int i;
9692
9693         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9694
9695         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9696                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9697                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9698         }
9699
9700         return WERR_BADFUNC;
9701 }
9702
9703 /*******************************************************************
9704 *******************************************************************/
9705 #if 0   /* don't support management using the "Local Port" monitor */
9706
9707 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9708                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9709                                  DATA_BLOB *out, uint32_t *needed)
9710 {
9711         const char *dllname = "localui.dll";
9712
9713         *needed = (strlen(dllname)+1) * 2;
9714
9715         if (out->length < *needed) {
9716                 return WERR_INSUFFICIENT_BUFFER;
9717         }
9718
9719         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9720                 return WERR_NOMEM;
9721         }
9722
9723         return WERR_OK;
9724 }
9725
9726 /*******************************************************************
9727 *******************************************************************/
9728
9729 struct xcv_api_table xcvlocal_cmds[] = {
9730         { "MonitorUI",  xcvlocal_monitorui },
9731         { NULL,         NULL }
9732 };
9733 #else
9734 struct xcv_api_table xcvlocal_cmds[] = {
9735         { NULL,         NULL }
9736 };
9737 #endif
9738
9739
9740
9741 /*******************************************************************
9742 *******************************************************************/
9743
9744 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9745                                        NT_USER_TOKEN *token, const char *command,
9746                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9747                                        uint32_t *needed)
9748 {
9749         int i;
9750
9751         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9752
9753         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9754                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9755                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9756         }
9757         return WERR_BADFUNC;
9758 }
9759
9760 /****************************************************************
9761  _spoolss_XcvData
9762 ****************************************************************/
9763
9764 WERROR _spoolss_XcvData(pipes_struct *p,
9765                         struct spoolss_XcvData *r)
9766 {
9767         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9768         DATA_BLOB out_data = data_blob_null;
9769         WERROR werror;
9770
9771         if (!Printer) {
9772                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9773                         OUR_HANDLE(r->in.handle)));
9774                 return WERR_BADFID;
9775         }
9776
9777         /* Has to be a handle to the TCP/IP port monitor */
9778
9779         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9780                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9781                 return WERR_BADFID;
9782         }
9783
9784         /* requires administrative access to the server */
9785
9786         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9787                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9788                 return WERR_ACCESS_DENIED;
9789         }
9790
9791         /* Allocate the outgoing buffer */
9792
9793         if (r->in.out_data_size) {
9794                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9795                 if (out_data.data == NULL) {
9796                         return WERR_NOMEM;
9797                 }
9798         }
9799
9800         switch ( Printer->printer_type ) {
9801         case SPLHND_PORTMON_TCP:
9802                 werror = process_xcvtcp_command(p->mem_ctx,
9803                                                 p->server_info->ptok,
9804                                                 r->in.function_name,
9805                                                 &r->in.in_data, &out_data,
9806                                                 r->out.needed);
9807                 break;
9808         case SPLHND_PORTMON_LOCAL:
9809                 werror = process_xcvlocal_command(p->mem_ctx,
9810                                                   p->server_info->ptok,
9811                                                   r->in.function_name,
9812                                                   &r->in.in_data, &out_data,
9813                                                   r->out.needed);
9814                 break;
9815         default:
9816                 werror = WERR_INVALID_PRINT_MONITOR;
9817         }
9818
9819         if (!W_ERROR_IS_OK(werror)) {
9820                 return werror;
9821         }
9822
9823         *r->out.status_code = 0;
9824
9825         memcpy(r->out.out_data, out_data.data, out_data.length);
9826
9827         return WERR_OK;
9828 }
9829
9830 /****************************************************************
9831  _spoolss_AddPrintProcessor
9832 ****************************************************************/
9833
9834 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9835                                   struct spoolss_AddPrintProcessor *r)
9836 {
9837         /* for now, just indicate success and ignore the add.  We'll
9838            automatically set the winprint processor for printer
9839            entries later.  Used to debug the LexMark Optra S 1855 PCL
9840            driver --jerry */
9841
9842         return WERR_OK;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_AddPort
9847 ****************************************************************/
9848
9849 WERROR _spoolss_AddPort(pipes_struct *p,
9850                         struct spoolss_AddPort *r)
9851 {
9852         /* do what w2k3 does */
9853
9854         return WERR_NOT_SUPPORTED;
9855 }
9856
9857 /****************************************************************
9858  _spoolss_GetPrinterDriver
9859 ****************************************************************/
9860
9861 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9862                                  struct spoolss_GetPrinterDriver *r)
9863 {
9864         p->rng_fault_state = true;
9865         return WERR_NOT_SUPPORTED;
9866 }
9867
9868 /****************************************************************
9869  _spoolss_ReadPrinter
9870 ****************************************************************/
9871
9872 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9873                             struct spoolss_ReadPrinter *r)
9874 {
9875         p->rng_fault_state = true;
9876         return WERR_NOT_SUPPORTED;
9877 }
9878
9879 /****************************************************************
9880  _spoolss_WaitForPrinterChange
9881 ****************************************************************/
9882
9883 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9884                                      struct spoolss_WaitForPrinterChange *r)
9885 {
9886         p->rng_fault_state = true;
9887         return WERR_NOT_SUPPORTED;
9888 }
9889
9890 /****************************************************************
9891  _spoolss_ConfigurePort
9892 ****************************************************************/
9893
9894 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9895                               struct spoolss_ConfigurePort *r)
9896 {
9897         p->rng_fault_state = true;
9898         return WERR_NOT_SUPPORTED;
9899 }
9900
9901 /****************************************************************
9902  _spoolss_DeletePort
9903 ****************************************************************/
9904
9905 WERROR _spoolss_DeletePort(pipes_struct *p,
9906                            struct spoolss_DeletePort *r)
9907 {
9908         p->rng_fault_state = true;
9909         return WERR_NOT_SUPPORTED;
9910 }
9911
9912 /****************************************************************
9913  _spoolss_CreatePrinterIC
9914 ****************************************************************/
9915
9916 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9917                                 struct spoolss_CreatePrinterIC *r)
9918 {
9919         p->rng_fault_state = true;
9920         return WERR_NOT_SUPPORTED;
9921 }
9922
9923 /****************************************************************
9924  _spoolss_PlayGDIScriptOnPrinterIC
9925 ****************************************************************/
9926
9927 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9928                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9929 {
9930         p->rng_fault_state = true;
9931         return WERR_NOT_SUPPORTED;
9932 }
9933
9934 /****************************************************************
9935  _spoolss_DeletePrinterIC
9936 ****************************************************************/
9937
9938 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9939                                 struct spoolss_DeletePrinterIC *r)
9940 {
9941         p->rng_fault_state = true;
9942         return WERR_NOT_SUPPORTED;
9943 }
9944
9945 /****************************************************************
9946  _spoolss_AddPrinterConnection
9947 ****************************************************************/
9948
9949 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9950                                      struct spoolss_AddPrinterConnection *r)
9951 {
9952         p->rng_fault_state = true;
9953         return WERR_NOT_SUPPORTED;
9954 }
9955
9956 /****************************************************************
9957  _spoolss_DeletePrinterConnection
9958 ****************************************************************/
9959
9960 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9961                                         struct spoolss_DeletePrinterConnection *r)
9962 {
9963         p->rng_fault_state = true;
9964         return WERR_NOT_SUPPORTED;
9965 }
9966
9967 /****************************************************************
9968  _spoolss_PrinterMessageBox
9969 ****************************************************************/
9970
9971 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9972                                   struct spoolss_PrinterMessageBox *r)
9973 {
9974         p->rng_fault_state = true;
9975         return WERR_NOT_SUPPORTED;
9976 }
9977
9978 /****************************************************************
9979  _spoolss_AddMonitor
9980 ****************************************************************/
9981
9982 WERROR _spoolss_AddMonitor(pipes_struct *p,
9983                            struct spoolss_AddMonitor *r)
9984 {
9985         p->rng_fault_state = true;
9986         return WERR_NOT_SUPPORTED;
9987 }
9988
9989 /****************************************************************
9990  _spoolss_DeleteMonitor
9991 ****************************************************************/
9992
9993 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9994                               struct spoolss_DeleteMonitor *r)
9995 {
9996         p->rng_fault_state = true;
9997         return WERR_NOT_SUPPORTED;
9998 }
9999
10000 /****************************************************************
10001  _spoolss_DeletePrintProcessor
10002 ****************************************************************/
10003
10004 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10005                                      struct spoolss_DeletePrintProcessor *r)
10006 {
10007         p->rng_fault_state = true;
10008         return WERR_NOT_SUPPORTED;
10009 }
10010
10011 /****************************************************************
10012  _spoolss_AddPrintProvidor
10013 ****************************************************************/
10014
10015 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10016                                  struct spoolss_AddPrintProvidor *r)
10017 {
10018         p->rng_fault_state = true;
10019         return WERR_NOT_SUPPORTED;
10020 }
10021
10022 /****************************************************************
10023  _spoolss_DeletePrintProvidor
10024 ****************************************************************/
10025
10026 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10027                                     struct spoolss_DeletePrintProvidor *r)
10028 {
10029         p->rng_fault_state = true;
10030         return WERR_NOT_SUPPORTED;
10031 }
10032
10033 /****************************************************************
10034  _spoolss_FindFirstPrinterChangeNotification
10035 ****************************************************************/
10036
10037 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10038                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10039 {
10040         p->rng_fault_state = true;
10041         return WERR_NOT_SUPPORTED;
10042 }
10043
10044 /****************************************************************
10045  _spoolss_FindNextPrinterChangeNotification
10046 ****************************************************************/
10047
10048 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10049                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10050 {
10051         p->rng_fault_state = true;
10052         return WERR_NOT_SUPPORTED;
10053 }
10054
10055 /****************************************************************
10056  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10057 ****************************************************************/
10058
10059 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10060                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10061 {
10062         p->rng_fault_state = true;
10063         return WERR_NOT_SUPPORTED;
10064 }
10065
10066 /****************************************************************
10067  _spoolss_ReplyOpenPrinter
10068 ****************************************************************/
10069
10070 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10071                                  struct spoolss_ReplyOpenPrinter *r)
10072 {
10073         p->rng_fault_state = true;
10074         return WERR_NOT_SUPPORTED;
10075 }
10076
10077 /****************************************************************
10078  _spoolss_RouterReplyPrinter
10079 ****************************************************************/
10080
10081 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10082                                    struct spoolss_RouterReplyPrinter *r)
10083 {
10084         p->rng_fault_state = true;
10085         return WERR_NOT_SUPPORTED;
10086 }
10087
10088 /****************************************************************
10089  _spoolss_ReplyClosePrinter
10090 ****************************************************************/
10091
10092 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10093                                   struct spoolss_ReplyClosePrinter *r)
10094 {
10095         p->rng_fault_state = true;
10096         return WERR_NOT_SUPPORTED;
10097 }
10098
10099 /****************************************************************
10100  _spoolss_AddPortEx
10101 ****************************************************************/
10102
10103 WERROR _spoolss_AddPortEx(pipes_struct *p,
10104                           struct spoolss_AddPortEx *r)
10105 {
10106         p->rng_fault_state = true;
10107         return WERR_NOT_SUPPORTED;
10108 }
10109
10110 /****************************************************************
10111  _spoolss_RouterFindFirstPrinterChangeNotification
10112 ****************************************************************/
10113
10114 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10115                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10116 {
10117         p->rng_fault_state = true;
10118         return WERR_NOT_SUPPORTED;
10119 }
10120
10121 /****************************************************************
10122  _spoolss_SpoolerInit
10123 ****************************************************************/
10124
10125 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10126                             struct spoolss_SpoolerInit *r)
10127 {
10128         p->rng_fault_state = true;
10129         return WERR_NOT_SUPPORTED;
10130 }
10131
10132 /****************************************************************
10133  _spoolss_ResetPrinterEx
10134 ****************************************************************/
10135
10136 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10137                                struct spoolss_ResetPrinterEx *r)
10138 {
10139         p->rng_fault_state = true;
10140         return WERR_NOT_SUPPORTED;
10141 }
10142
10143 /****************************************************************
10144  _spoolss_RouterReplyPrinterEx
10145 ****************************************************************/
10146
10147 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10148                                      struct spoolss_RouterReplyPrinterEx *r)
10149 {
10150         p->rng_fault_state = true;
10151         return WERR_NOT_SUPPORTED;
10152 }
10153
10154 /****************************************************************
10155  _spoolss_44
10156 ****************************************************************/
10157
10158 WERROR _spoolss_44(pipes_struct *p,
10159                    struct spoolss_44 *r)
10160 {
10161         p->rng_fault_state = true;
10162         return WERR_NOT_SUPPORTED;
10163 }
10164
10165 /****************************************************************
10166  _spoolss_47
10167 ****************************************************************/
10168
10169 WERROR _spoolss_47(pipes_struct *p,
10170                    struct spoolss_47 *r)
10171 {
10172         p->rng_fault_state = true;
10173         return WERR_NOT_SUPPORTED;
10174 }
10175
10176 /****************************************************************
10177  _spoolss_4a
10178 ****************************************************************/
10179
10180 WERROR _spoolss_4a(pipes_struct *p,
10181                    struct spoolss_4a *r)
10182 {
10183         p->rng_fault_state = true;
10184         return WERR_NOT_SUPPORTED;
10185 }
10186
10187 /****************************************************************
10188  _spoolss_4b
10189 ****************************************************************/
10190
10191 WERROR _spoolss_4b(pipes_struct *p,
10192                    struct spoolss_4b *r)
10193 {
10194         p->rng_fault_state = true;
10195         return WERR_NOT_SUPPORTED;
10196 }
10197
10198 /****************************************************************
10199  _spoolss_4c
10200 ****************************************************************/
10201
10202 WERROR _spoolss_4c(pipes_struct *p,
10203                    struct spoolss_4c *r)
10204 {
10205         p->rng_fault_state = true;
10206         return WERR_NOT_SUPPORTED;
10207 }
10208
10209 /****************************************************************
10210  _spoolss_53
10211 ****************************************************************/
10212
10213 WERROR _spoolss_53(pipes_struct *p,
10214                    struct spoolss_53 *r)
10215 {
10216         p->rng_fault_state = true;
10217         return WERR_NOT_SUPPORTED;
10218 }
10219
10220 /****************************************************************
10221  _spoolss_55
10222 ****************************************************************/
10223
10224 WERROR _spoolss_55(pipes_struct *p,
10225                    struct spoolss_55 *r)
10226 {
10227         p->rng_fault_state = true;
10228         return WERR_NOT_SUPPORTED;
10229 }
10230
10231 /****************************************************************
10232  _spoolss_56
10233 ****************************************************************/
10234
10235 WERROR _spoolss_56(pipes_struct *p,
10236                    struct spoolss_56 *r)
10237 {
10238         p->rng_fault_state = true;
10239         return WERR_NOT_SUPPORTED;
10240 }
10241
10242 /****************************************************************
10243  _spoolss_57
10244 ****************************************************************/
10245
10246 WERROR _spoolss_57(pipes_struct *p,
10247                    struct spoolss_57 *r)
10248 {
10249         p->rng_fault_state = true;
10250         return WERR_NOT_SUPPORTED;
10251 }
10252
10253 /****************************************************************
10254  _spoolss_5a
10255 ****************************************************************/
10256
10257 WERROR _spoolss_5a(pipes_struct *p,
10258                    struct spoolss_5a *r)
10259 {
10260         p->rng_fault_state = true;
10261         return WERR_NOT_SUPPORTED;
10262 }
10263
10264 /****************************************************************
10265  _spoolss_5b
10266 ****************************************************************/
10267
10268 WERROR _spoolss_5b(pipes_struct *p,
10269                    struct spoolss_5b *r)
10270 {
10271         p->rng_fault_state = true;
10272         return WERR_NOT_SUPPORTED;
10273 }
10274
10275 /****************************************************************
10276  _spoolss_5c
10277 ****************************************************************/
10278
10279 WERROR _spoolss_5c(pipes_struct *p,
10280                    struct spoolss_5c *r)
10281 {
10282         p->rng_fault_state = true;
10283         return WERR_NOT_SUPPORTED;
10284 }
10285
10286 /****************************************************************
10287  _spoolss_5d
10288 ****************************************************************/
10289
10290 WERROR _spoolss_5d(pipes_struct *p,
10291                    struct spoolss_5d *r)
10292 {
10293         p->rng_fault_state = true;
10294         return WERR_NOT_SUPPORTED;
10295 }
10296
10297 /****************************************************************
10298  _spoolss_5e
10299 ****************************************************************/
10300
10301 WERROR _spoolss_5e(pipes_struct *p,
10302                    struct spoolss_5e *r)
10303 {
10304         p->rng_fault_state = true;
10305         return WERR_NOT_SUPPORTED;
10306 }
10307
10308 /****************************************************************
10309  _spoolss_5f
10310 ****************************************************************/
10311
10312 WERROR _spoolss_5f(pipes_struct *p,
10313                    struct spoolss_5f *r)
10314 {
10315         p->rng_fault_state = true;
10316         return WERR_NOT_SUPPORTED;
10317 }
10318
10319 /****************************************************************
10320  _spoolss_60
10321 ****************************************************************/
10322
10323 WERROR _spoolss_60(pipes_struct *p,
10324                    struct spoolss_60 *r)
10325 {
10326         p->rng_fault_state = true;
10327         return WERR_NOT_SUPPORTED;
10328 }
10329
10330 /****************************************************************
10331  _spoolss_61
10332 ****************************************************************/
10333
10334 WERROR _spoolss_61(pipes_struct *p,
10335                    struct spoolss_61 *r)
10336 {
10337         p->rng_fault_state = true;
10338         return WERR_NOT_SUPPORTED;
10339 }
10340
10341 /****************************************************************
10342  _spoolss_62
10343 ****************************************************************/
10344
10345 WERROR _spoolss_62(pipes_struct *p,
10346                    struct spoolss_62 *r)
10347 {
10348         p->rng_fault_state = true;
10349         return WERR_NOT_SUPPORTED;
10350 }
10351
10352 /****************************************************************
10353  _spoolss_63
10354 ****************************************************************/
10355
10356 WERROR _spoolss_63(pipes_struct *p,
10357                    struct spoolss_63 *r)
10358 {
10359         p->rng_fault_state = true;
10360         return WERR_NOT_SUPPORTED;
10361 }
10362
10363 /****************************************************************
10364  _spoolss_64
10365 ****************************************************************/
10366
10367 WERROR _spoolss_64(pipes_struct *p,
10368                    struct spoolss_64 *r)
10369 {
10370         p->rng_fault_state = true;
10371         return WERR_NOT_SUPPORTED;
10372 }
10373
10374 /****************************************************************
10375  _spoolss_65
10376 ****************************************************************/
10377
10378 WERROR _spoolss_65(pipes_struct *p,
10379                    struct spoolss_65 *r)
10380 {
10381         p->rng_fault_state = true;
10382         return WERR_NOT_SUPPORTED;
10383 }
10384
10385 /****************************************************************
10386  _spoolss_GetCorePrinterDrivers
10387 ****************************************************************/
10388
10389 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10390                                       struct spoolss_GetCorePrinterDrivers *r)
10391 {
10392         p->rng_fault_state = true;
10393         return WERR_NOT_SUPPORTED;
10394 }
10395
10396 /****************************************************************
10397  _spoolss_67
10398 ****************************************************************/
10399
10400 WERROR _spoolss_67(pipes_struct *p,
10401                    struct spoolss_67 *r)
10402 {
10403         p->rng_fault_state = true;
10404         return WERR_NOT_SUPPORTED;
10405 }
10406
10407 /****************************************************************
10408  _spoolss_GetPrinterDriverPackagePath
10409 ****************************************************************/
10410
10411 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10412                                             struct spoolss_GetPrinterDriverPackagePath *r)
10413 {
10414         p->rng_fault_state = true;
10415         return WERR_NOT_SUPPORTED;
10416 }
10417
10418 /****************************************************************
10419  _spoolss_69
10420 ****************************************************************/
10421
10422 WERROR _spoolss_69(pipes_struct *p,
10423                    struct spoolss_69 *r)
10424 {
10425         p->rng_fault_state = true;
10426         return WERR_NOT_SUPPORTED;
10427 }
10428
10429 /****************************************************************
10430  _spoolss_6a
10431 ****************************************************************/
10432
10433 WERROR _spoolss_6a(pipes_struct *p,
10434                    struct spoolss_6a *r)
10435 {
10436         p->rng_fault_state = true;
10437         return WERR_NOT_SUPPORTED;
10438 }
10439
10440 /****************************************************************
10441  _spoolss_6b
10442 ****************************************************************/
10443
10444 WERROR _spoolss_6b(pipes_struct *p,
10445                    struct spoolss_6b *r)
10446 {
10447         p->rng_fault_state = true;
10448         return WERR_NOT_SUPPORTED;
10449 }
10450
10451 /****************************************************************
10452  _spoolss_6c
10453 ****************************************************************/
10454
10455 WERROR _spoolss_6c(pipes_struct *p,
10456                    struct spoolss_6c *r)
10457 {
10458         p->rng_fault_state = true;
10459         return WERR_NOT_SUPPORTED;
10460 }
10461
10462 /****************************************************************
10463  _spoolss_6d
10464 ****************************************************************/
10465
10466 WERROR _spoolss_6d(pipes_struct *p,
10467                    struct spoolss_6d *r)
10468 {
10469         p->rng_fault_state = true;
10470         return WERR_NOT_SUPPORTED;
10471 }