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