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