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