s3-spoolss: in spoolss_EnumPrinters r->in.server is a *unique* pointer!
[samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33         ((info)?ndr_size_##fn(info, level, ic, 0):0)
34
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
37
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
42
43
44 extern userdom_struct current_user_info;
45
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
48
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
52
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
55
56 static Printer_entry *printers_list;
57
58 typedef struct _counter_printer_0 {
59         struct _counter_printer_0 *next;
60         struct _counter_printer_0 *prev;
61
62         int snum;
63         uint32_t counter;
64 } counter_printer_0;
65
66 static counter_printer_0 *counter_list;
67
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
70
71
72 /* in printing/nt_printing.c */
73
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
75
76 /* API table for Xcv Monitor functions */
77
78 struct xcv_api_table {
79         const char *name;
80         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
81 };
82
83 /********************************************************************
84  * Canonicalize servername.
85  ********************************************************************/
86
87 static const char *canon_servername(const char *servername)
88 {
89         const char *pservername = servername;
90         while (*pservername == '\\') {
91                 pservername++;
92         }
93         return pservername;
94 }
95
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
98 {
99         switch (v) {
100         case LPQ_QUEUED:
101                 return 0;
102         case LPQ_PAUSED:
103                 return JOB_STATUS_PAUSED;
104         case LPQ_SPOOLING:
105                 return JOB_STATUS_SPOOLING;
106         case LPQ_PRINTING:
107                 return JOB_STATUS_PRINTING;
108         case LPQ_ERROR:
109                 return JOB_STATUS_ERROR;
110         case LPQ_DELETING:
111                 return JOB_STATUS_DELETING;
112         case LPQ_OFFLINE:
113                 return JOB_STATUS_OFFLINE;
114         case LPQ_PAPEROUT:
115                 return JOB_STATUS_PAPEROUT;
116         case LPQ_PRINTED:
117                 return JOB_STATUS_PRINTED;
118         case LPQ_DELETED:
119                 return JOB_STATUS_DELETED;
120         case LPQ_BLOCKED:
121                 return JOB_STATUS_BLOCKED_DEVQ;
122         case LPQ_USER_INTERVENTION:
123                 return JOB_STATUS_USER_INTERVENTION;
124         }
125         return 0;
126 }
127
128 static int nt_printq_status(int v)
129 {
130         switch (v) {
131         case LPQ_PAUSED:
132                 return PRINTER_STATUS_PAUSED;
133         case LPQ_QUEUED:
134         case LPQ_SPOOLING:
135         case LPQ_PRINTING:
136                 return 0;
137         }
138         return 0;
139 }
140
141 /***************************************************************************
142  Disconnect from the client
143 ****************************************************************************/
144
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
146 {
147         WERROR result;
148         NTSTATUS status;
149
150         /*
151          * Tell the specific printing tdb we no longer want messages for this printer
152          * by deregistering our PID.
153          */
154
155         if (!print_notify_deregister_pid(snum))
156                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
157
158         /* weird if the test succeds !!! */
159         if (smb_connections==0) {
160                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161                 return;
162         }
163
164         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
165                                                   handle,
166                                                   &result);
167         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169                         win_errstr(result)));
170
171         /* if it's the last connection, deconnect the IPC$ share */
172         if (smb_connections==1) {
173
174                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
176
177                 messaging_deregister(smbd_messaging_context(),
178                                      MSG_PRINTER_NOTIFY2, NULL);
179
180                 /* Tell the connections db we're no longer interested in
181                  * printer notify messages. */
182
183                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
184         }
185
186         smb_connections--;
187 }
188
189 /****************************************************************************
190  Functions to free a printer entry datastruct.
191 ****************************************************************************/
192
193 static int printer_entry_destructor(Printer_entry *Printer)
194 {
195         if (Printer->notify.client_connected == true) {
196                 int snum = -1;
197
198                 if ( Printer->printer_type == SPLHND_SERVER) {
199                         snum = -1;
200                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201                 } else if (Printer->printer_type == SPLHND_PRINTER) {
202                         snum = print_queue_snum(Printer->sharename);
203                         if (snum != -1)
204                                 srv_spoolss_replycloseprinter(snum,
205                                                 &Printer->notify.client_hnd);
206                 }
207         }
208
209         Printer->notify.flags=0;
210         Printer->notify.options=0;
211         Printer->notify.localmachine[0]='\0';
212         Printer->notify.printerlocal=0;
213         TALLOC_FREE(Printer->notify.option);
214         Printer->notify.client_connected = false;
215
216         free_nt_devicemode( &Printer->nt_devmode );
217         free_a_printer( &Printer->printer_info, 2 );
218
219         /* Remove from the internal list. */
220         DLIST_REMOVE(printers_list, Printer);
221         return 0;
222 }
223
224 /****************************************************************************
225   find printer index by handle
226 ****************************************************************************/
227
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229                                                 struct policy_handle *hnd)
230 {
231         Printer_entry *find_printer = NULL;
232
233         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
235                 return NULL;
236         }
237
238         return find_printer;
239 }
240
241 /****************************************************************************
242  Close printer index by handle.
243 ****************************************************************************/
244
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
246 {
247         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
248
249         if (!Printer) {
250                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
251                         OUR_HANDLE(hnd)));
252                 return false;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return true;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 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", (int)p->pipe_handles->count ));
591
592         return true;
593 }
594
595 /***************************************************************************
596  check to see if the client motify handle is monitoring the notification
597  given by (notify_type, notify_field).
598  **************************************************************************/
599
600 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
601                                       uint16_t notify_field)
602 {
603         return true;
604 }
605
606 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
607                                 uint16_t notify_field)
608 {
609         struct spoolss_NotifyOption *option = p->notify.option;
610         uint32_t i, j;
611
612         /*
613          * Flags should always be zero when the change notify
614          * is registered by the client's spooler.  A user Win32 app
615          * might use the flags though instead of the NOTIFY_OPTION_INFO
616          * --jerry
617          */
618
619         if (!option) {
620                 return false;
621         }
622
623         if (p->notify.flags)
624                 return is_monitoring_event_flags(
625                         p->notify.flags, notify_type, notify_field);
626
627         for (i = 0; i < option->count; i++) {
628
629                 /* Check match for notify_type */
630
631                 if (option->types[i].type != notify_type)
632                         continue;
633
634                 /* Check match for field */
635
636                 for (j = 0; j < option->types[i].count; j++) {
637                         if (option->types[i].fields[j].field == notify_field) {
638                                 return true;
639                         }
640                 }
641         }
642
643         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
644                    p->servername, p->sharename, notify_type, notify_field));
645
646         return false;
647 }
648
649 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
650         _data->data.integer[0] = _integer; \
651         _data->data.integer[1] = 0;
652
653
654 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
655         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
656         if (!_data->data.string.string) {\
657                 _data->data.string.size = 0; \
658         } \
659         _data->data.string.size = strlen_m_term(_p) * 2;
660
661 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
662         _data->data.devmode.devmode = _devmode;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
665         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
666         if (!_data->data.sd.sd) { \
667                 _data->data.sd.sd_size = 0; \
668         } \
669         _data->data.sd.sd_size = _size;
670
671 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
672                                    struct tm *t,
673                                    const char **pp,
674                                    uint32_t *plen)
675 {
676         struct spoolss_Time st;
677         uint32_t len = 16;
678         char *p;
679
680         if (!init_systemtime(&st, t)) {
681                 return;
682         }
683
684         p = talloc_array(mem_ctx, char, len);
685         if (!p) {
686                 return;
687         }
688
689         /*
690          * Systemtime must be linearized as a set of UINT16's.
691          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
692          */
693
694         SSVAL(p, 0, st.year);
695         SSVAL(p, 2, st.month);
696         SSVAL(p, 4, st.day_of_week);
697         SSVAL(p, 6, st.day);
698         SSVAL(p, 8, st.hour);
699         SSVAL(p, 10, st.minute);
700         SSVAL(p, 12, st.second);
701         SSVAL(p, 14, st.millisecond);
702
703         *pp = p;
704         *plen = len;
705 }
706
707 /* Convert a notification message to a struct spoolss_Notify */
708
709 static void notify_one_value(struct spoolss_notify_msg *msg,
710                              struct spoolss_Notify *data,
711                              TALLOC_CTX *mem_ctx)
712 {
713         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
714 }
715
716 static void notify_string(struct spoolss_notify_msg *msg,
717                           struct spoolss_Notify *data,
718                           TALLOC_CTX *mem_ctx)
719 {
720         /* The length of the message includes the trailing \0 */
721
722         data->data.string.size = msg->len * 2;
723         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
724         if (!data->data.string.string) {
725                 data->data.string.size = 0;
726                 return;
727         }
728 }
729
730 static void notify_system_time(struct spoolss_notify_msg *msg,
731                                struct spoolss_Notify *data,
732                                TALLOC_CTX *mem_ctx)
733 {
734         data->data.string.string = NULL;
735         data->data.string.size = 0;
736
737         if (msg->len != sizeof(time_t)) {
738                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
739                           msg->len));
740                 return;
741         }
742
743         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
744                                &data->data.string.string,
745                                &data->data.string.size);
746 }
747
748 struct notify2_message_table {
749         const char *name;
750         void (*fn)(struct spoolss_notify_msg *msg,
751                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
752 };
753
754 static struct notify2_message_table printer_notify_table[] = {
755         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
756         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
757         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
758         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
759         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
760         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
761         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
762         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
763         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
764         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
765         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
766         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
767         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
768         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
769         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
770         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
771         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
772         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
773         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
774 };
775
776 static struct notify2_message_table job_notify_table[] = {
777         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
778         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
779         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
780         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
781         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
782         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
783         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
784         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
785         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
786         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
787         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
788         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
789         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
790         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
791         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
792         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
793         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
794         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
795         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
796         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
797         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
798         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
799         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
800         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
801 };
802
803
804 /***********************************************************************
805  Allocate talloc context for container object
806  **********************************************************************/
807
808 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
809 {
810         if ( !ctr )
811                 return;
812
813         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
814
815         return;
816 }
817
818 /***********************************************************************
819  release all allocated memory and zero out structure
820  **********************************************************************/
821
822 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
823 {
824         if ( !ctr )
825                 return;
826
827         if ( ctr->ctx )
828                 talloc_destroy(ctr->ctx);
829
830         ZERO_STRUCTP(ctr);
831
832         return;
833 }
834
835 /***********************************************************************
836  **********************************************************************/
837
838 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
839 {
840         if ( !ctr )
841                 return NULL;
842
843         return ctr->ctx;
844 }
845
846 /***********************************************************************
847  **********************************************************************/
848
849 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
850 {
851         if ( !ctr || !ctr->msg_groups )
852                 return NULL;
853
854         if ( idx >= ctr->num_groups )
855                 return NULL;
856
857         return &ctr->msg_groups[idx];
858
859 }
860
861 /***********************************************************************
862  How many groups of change messages do we have ?
863  **********************************************************************/
864
865 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 {
867         if ( !ctr )
868                 return 0;
869
870         return ctr->num_groups;
871 }
872
873 /***********************************************************************
874  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
875  **********************************************************************/
876
877 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
878 {
879         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
880         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
881         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
882         int                             i, new_slot;
883
884         if ( !ctr || !msg )
885                 return 0;
886
887         /* loop over all groups looking for a matching printer name */
888
889         for ( i=0; i<ctr->num_groups; i++ ) {
890                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
891                         break;
892         }
893
894         /* add a new group? */
895
896         if ( i == ctr->num_groups ) {
897                 ctr->num_groups++;
898
899                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
900                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
901                         return 0;
902                 }
903                 ctr->msg_groups = groups;
904
905                 /* clear the new entry and set the printer name */
906
907                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
908                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
909         }
910
911         /* add the change messages; 'i' is the correct index now regardless */
912
913         msg_grp = &ctr->msg_groups[i];
914
915         msg_grp->num_msgs++;
916
917         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
918                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
919                 return 0;
920         }
921         msg_grp->msgs = msg_list;
922
923         new_slot = msg_grp->num_msgs-1;
924         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
925
926         /* need to allocate own copy of data */
927
928         if ( msg->len != 0 )
929                 msg_grp->msgs[new_slot].notify.data = (char *)
930                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
931
932         return ctr->num_groups;
933 }
934
935 /***********************************************************************
936  Send a change notication message on all handles which have a call
937  back registered
938  **********************************************************************/
939
940 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
941 {
942         Printer_entry            *p;
943         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
944         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
945         SPOOLSS_NOTIFY_MSG       *messages;
946         int                      sending_msg_count;
947
948         if ( !msg_group ) {
949                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
950                 return;
951         }
952
953         messages = msg_group->msgs;
954
955         if ( !messages ) {
956                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
957                 return;
958         }
959
960         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
961
962         /* loop over all printers */
963
964         for (p = printers_list; p; p = p->next) {
965                 struct spoolss_Notify *notifies;
966                 uint32_t count = 0;
967                 uint32_t id;
968                 int     i;
969
970                 /* Is there notification on this handle? */
971
972                 if ( !p->notify.client_connected )
973                         continue;
974
975                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
976
977                 /* For this printer?  Print servers always receive
978                    notifications. */
979
980                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
981                     ( !strequal(msg_group->printername, p->sharename) ) )
982                         continue;
983
984                 DEBUG(10,("Our printer\n"));
985
986                 /* allocate the max entries possible */
987
988                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
989                 if (!notifies) {
990                         return;
991                 }
992
993                 /* build the array of change notifications */
994
995                 sending_msg_count = 0;
996
997                 for ( i=0; i<msg_group->num_msgs; i++ ) {
998                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
999
1000                         /* Are we monitoring this event? */
1001
1002                         if (!is_monitoring_event(p, msg->type, msg->field))
1003                                 continue;
1004
1005                         sending_msg_count++;
1006
1007
1008                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1009                                 msg->type, msg->field, p->sharename));
1010
1011                         /*
1012                          * if the is a printer notification handle and not a job notification
1013                          * type, then set the id to 0.  Other wise just use what was specified
1014                          * in the message.
1015                          *
1016                          * When registering change notification on a print server handle
1017                          * we always need to send back the id (snum) matching the printer
1018                          * for which the change took place.  For change notify registered
1019                          * on a printer handle, this does not matter and the id should be 0.
1020                          *
1021                          * --jerry
1022                          */
1023
1024                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1025                                 id = 0;
1026                         else
1027                                 id = msg->id;
1028
1029
1030                         /* Convert unix jobid to smb jobid */
1031
1032                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1033                                 id = sysjob_to_jobid(msg->id);
1034
1035                                 if (id == -1) {
1036                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1037                                         goto done;
1038                                 }
1039                         }
1040
1041                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1042
1043                         switch(msg->type) {
1044                         case PRINTER_NOTIFY_TYPE:
1045                                 if ( printer_notify_table[msg->field].fn )
1046                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1047                                 break;
1048
1049                         case JOB_NOTIFY_TYPE:
1050                                 if ( job_notify_table[msg->field].fn )
1051                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1052                                 break;
1053
1054                         default:
1055                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1056                                 goto done;
1057                         }
1058
1059                         count++;
1060                 }
1061
1062                 if ( sending_msg_count ) {
1063                         NTSTATUS status;
1064                         WERROR werr;
1065                         union spoolss_ReplyPrinterInfo info;
1066                         struct spoolss_NotifyInfo info0;
1067                         uint32_t reply_result;
1068
1069                         info0.version   = 0x2;
1070                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1071                         info0.count     = count;
1072                         info0.notifies  = notifies;
1073
1074                         info.info0 = &info0;
1075
1076                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1077                                                                      &p->notify.client_hnd,
1078                                                                      p->notify.change, /* color */
1079                                                                      p->notify.flags,
1080                                                                      &reply_result,
1081                                                                      0, /* reply_type, must be 0 */
1082                                                                      info,
1083                                                                      &werr);
1084                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1085                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1086                                         notify_cli_pipe->srv_name_slash,
1087                                         win_errstr(werr)));
1088                         }
1089                         switch (reply_result) {
1090                                 case 0:
1091                                         break;
1092                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1093                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1094                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1095                                         break;
1096                                 default:
1097                                         break;
1098                         }
1099                 }
1100         }
1101
1102 done:
1103         DEBUG(8,("send_notify2_changes: Exit...\n"));
1104         return;
1105 }
1106
1107 /***********************************************************************
1108  **********************************************************************/
1109
1110 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1111 {
1112
1113         uint32_t tv_sec, tv_usec;
1114         size_t offset = 0;
1115
1116         /* Unpack message */
1117
1118         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1119                              msg->printer);
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1122                                 &tv_sec, &tv_usec,
1123                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1124
1125         if (msg->len == 0)
1126                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1127                            &msg->notify.value[0], &msg->notify.value[1]);
1128         else
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1130                            &msg->len, &msg->notify.data);
1131
1132         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1133                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1134
1135         tv->tv_sec = tv_sec;
1136         tv->tv_usec = tv_usec;
1137
1138         if (msg->len == 0)
1139                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1140                           msg->notify.value[1]));
1141         else
1142                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1143
1144         return true;
1145 }
1146
1147 /********************************************************************
1148  Receive a notify2 message list
1149  ********************************************************************/
1150
1151 static void receive_notify2_message_list(struct messaging_context *msg,
1152                                          void *private_data,
1153                                          uint32_t msg_type,
1154                                          struct server_id server_id,
1155                                          DATA_BLOB *data)
1156 {
1157         size_t                  msg_count, i;
1158         char                    *buf = (char *)data->data;
1159         char                    *msg_ptr;
1160         size_t                  msg_len;
1161         SPOOLSS_NOTIFY_MSG      notify;
1162         SPOOLSS_NOTIFY_MSG_CTR  messages;
1163         int                     num_groups;
1164
1165         if (data->length < 4) {
1166                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1167                 return;
1168         }
1169
1170         msg_count = IVAL(buf, 0);
1171         msg_ptr = buf + 4;
1172
1173         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1174
1175         if (msg_count == 0) {
1176                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1177                 return;
1178         }
1179
1180         /* initialize the container */
1181
1182         ZERO_STRUCT( messages );
1183         notify_msg_ctr_init( &messages );
1184
1185         /*
1186          * build message groups for each printer identified
1187          * in a change_notify msg.  Remember that a PCN message
1188          * includes the handle returned for the srv_spoolss_replyopenprinter()
1189          * call.  Therefore messages are grouped according to printer handle.
1190          */
1191
1192         for ( i=0; i<msg_count; i++ ) {
1193                 struct timeval msg_tv;
1194
1195                 if (msg_ptr + 4 - buf > data->length) {
1196                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1197                         return;
1198                 }
1199
1200                 msg_len = IVAL(msg_ptr,0);
1201                 msg_ptr += 4;
1202
1203                 if (msg_ptr + msg_len - buf > data->length) {
1204                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1205                         return;
1206                 }
1207
1208                 /* unpack messages */
1209
1210                 ZERO_STRUCT( notify );
1211                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1212                 msg_ptr += msg_len;
1213
1214                 /* add to correct list in container */
1215
1216                 notify_msg_ctr_addmsg( &messages, &notify );
1217
1218                 /* free memory that might have been allocated by notify2_unpack_msg() */
1219
1220                 if ( notify.len != 0 )
1221                         SAFE_FREE( notify.notify.data );
1222         }
1223
1224         /* process each group of messages */
1225
1226         num_groups = notify_msg_ctr_numgroups( &messages );
1227         for ( i=0; i<num_groups; i++ )
1228                 send_notify2_changes( &messages, i );
1229
1230
1231         /* cleanup */
1232
1233         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1234                 (uint32_t)msg_count ));
1235
1236         notify_msg_ctr_destroy( &messages );
1237
1238         return;
1239 }
1240
1241 /********************************************************************
1242  Send a message to ourself about new driver being installed
1243  so we can upgrade the information for each printer bound to this
1244  driver
1245  ********************************************************************/
1246
1247 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1248 {
1249         int len = strlen(drivername);
1250
1251         if (!len)
1252                 return false;
1253
1254         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1255                 drivername));
1256
1257         messaging_send_buf(smbd_messaging_context(), procid_self(),
1258                            MSG_PRINTER_DRVUPGRADE,
1259                            (uint8_t *)drivername, len+1);
1260
1261         return true;
1262 }
1263
1264 /**********************************************************************
1265  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1266  over all printers, upgrading ones as necessary
1267  **********************************************************************/
1268
1269 void do_drv_upgrade_printer(struct messaging_context *msg,
1270                             void *private_data,
1271                             uint32_t msg_type,
1272                             struct server_id server_id,
1273                             DATA_BLOB *data)
1274 {
1275         fstring drivername;
1276         int snum;
1277         int n_services = lp_numservices();
1278         size_t len;
1279
1280         len = MIN(data->length,sizeof(drivername)-1);
1281         strncpy(drivername, (const char *)data->data, len);
1282
1283         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1284
1285         /* Iterate the printer list */
1286
1287         for (snum=0; snum<n_services; snum++)
1288         {
1289                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1290                 {
1291                         WERROR result;
1292                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1293
1294                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1295                         if (!W_ERROR_IS_OK(result))
1296                                 continue;
1297
1298                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1299                         {
1300                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1301
1302                                 /* all we care about currently is the change_id */
1303
1304                                 result = mod_a_printer(printer, 2);
1305                                 if (!W_ERROR_IS_OK(result)) {
1306                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1307                                                 win_errstr(result)));
1308                                 }
1309                         }
1310
1311                         free_a_printer(&printer, 2);
1312                 }
1313         }
1314
1315         /* all done */
1316 }
1317
1318 /********************************************************************
1319  Update the cache for all printq's with a registered client
1320  connection
1321  ********************************************************************/
1322
1323 void update_monitored_printq_cache( void )
1324 {
1325         Printer_entry *printer = printers_list;
1326         int snum;
1327
1328         /* loop through all printers and update the cache where
1329            client_connected == true */
1330         while ( printer )
1331         {
1332                 if ( (printer->printer_type == SPLHND_PRINTER)
1333                         && printer->notify.client_connected )
1334                 {
1335                         snum = print_queue_snum(printer->sharename);
1336                         print_queue_status( snum, NULL, NULL );
1337                 }
1338
1339                 printer = printer->next;
1340         }
1341
1342         return;
1343 }
1344 /********************************************************************
1345  Send a message to ourself about new driver being installed
1346  so we can upgrade the information for each printer bound to this
1347  driver
1348  ********************************************************************/
1349
1350 static bool srv_spoolss_reset_printerdata(char* drivername)
1351 {
1352         int len = strlen(drivername);
1353
1354         if (!len)
1355                 return false;
1356
1357         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1358                 drivername));
1359
1360         messaging_send_buf(smbd_messaging_context(), procid_self(),
1361                            MSG_PRINTERDATA_INIT_RESET,
1362                            (uint8_t *)drivername, len+1);
1363
1364         return true;
1365 }
1366
1367 /**********************************************************************
1368  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1369  over all printers, resetting printer data as neessary
1370  **********************************************************************/
1371
1372 void reset_all_printerdata(struct messaging_context *msg,
1373                            void *private_data,
1374                            uint32_t msg_type,
1375                            struct server_id server_id,
1376                            DATA_BLOB *data)
1377 {
1378         fstring drivername;
1379         int snum;
1380         int n_services = lp_numservices();
1381         size_t len;
1382
1383         len = MIN( data->length, sizeof(drivername)-1 );
1384         strncpy( drivername, (const char *)data->data, len );
1385
1386         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1387
1388         /* Iterate the printer list */
1389
1390         for ( snum=0; snum<n_services; snum++ )
1391         {
1392                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1393                 {
1394                         WERROR result;
1395                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1396
1397                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1398                         if ( !W_ERROR_IS_OK(result) )
1399                                 continue;
1400
1401                         /*
1402                          * if the printer is bound to the driver,
1403                          * then reset to the new driver initdata
1404                          */
1405
1406                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1407                         {
1408                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1409
1410                                 if ( !set_driver_init(printer, 2) ) {
1411                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1412                                                 printer->info_2->printername, printer->info_2->drivername));
1413                                 }
1414
1415                                 result = mod_a_printer( printer, 2 );
1416                                 if ( !W_ERROR_IS_OK(result) ) {
1417                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1418                                                 get_dos_error_msg(result)));
1419                                 }
1420                         }
1421
1422                         free_a_printer( &printer, 2 );
1423                 }
1424         }
1425
1426         /* all done */
1427
1428         return;
1429 }
1430
1431 /****************************************************************
1432  _spoolss_OpenPrinter
1433 ****************************************************************/
1434
1435 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1436                             struct spoolss_OpenPrinter *r)
1437 {
1438         struct spoolss_OpenPrinterEx e;
1439         WERROR werr;
1440
1441         ZERO_STRUCT(e.in.userlevel);
1442
1443         e.in.printername        = r->in.printername;
1444         e.in.datatype           = r->in.datatype;
1445         e.in.devmode_ctr        = r->in.devmode_ctr;
1446         e.in.access_mask        = r->in.access_mask;
1447         e.in.level              = 0;
1448
1449         e.out.handle            = r->out.handle;
1450
1451         werr = _spoolss_OpenPrinterEx(p, &e);
1452
1453         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1454                 /* OpenPrinterEx returns this for a bad
1455                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1456                  * instead.
1457                  */
1458                 werr = WERR_INVALID_PRINTER_NAME;
1459         }
1460
1461         return werr;
1462 }
1463
1464 /********************************************************************
1465  ********************************************************************/
1466
1467 bool convert_devicemode(const char *printername,
1468                         const struct spoolss_DeviceMode *devmode,
1469                         NT_DEVICEMODE **pp_nt_devmode)
1470 {
1471         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1472
1473         /*
1474          * Ensure nt_devmode is a valid pointer
1475          * as we will be overwriting it.
1476          */
1477
1478         if (nt_devmode == NULL) {
1479                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1480                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1481                         return false;
1482         }
1483
1484         fstrcpy(nt_devmode->devicename, devmode->devicename);
1485         fstrcpy(nt_devmode->formname, devmode->formname);
1486
1487         nt_devmode->devicename[31] = '\0';
1488         nt_devmode->formname[31] = '\0';
1489
1490         nt_devmode->specversion         = devmode->specversion;
1491         nt_devmode->driverversion       = devmode->driverversion;
1492         nt_devmode->size                = devmode->size;
1493         nt_devmode->fields              = devmode->fields;
1494         nt_devmode->orientation         = devmode->orientation;
1495         nt_devmode->papersize           = devmode->papersize;
1496         nt_devmode->paperlength         = devmode->paperlength;
1497         nt_devmode->paperwidth          = devmode->paperwidth;
1498         nt_devmode->scale               = devmode->scale;
1499         nt_devmode->copies              = devmode->copies;
1500         nt_devmode->defaultsource       = devmode->defaultsource;
1501         nt_devmode->printquality        = devmode->printquality;
1502         nt_devmode->color               = devmode->color;
1503         nt_devmode->duplex              = devmode->duplex;
1504         nt_devmode->yresolution         = devmode->yresolution;
1505         nt_devmode->ttoption            = devmode->ttoption;
1506         nt_devmode->collate             = devmode->collate;
1507
1508         nt_devmode->logpixels           = devmode->logpixels;
1509         nt_devmode->bitsperpel          = devmode->bitsperpel;
1510         nt_devmode->pelswidth           = devmode->pelswidth;
1511         nt_devmode->pelsheight          = devmode->pelsheight;
1512         nt_devmode->displayflags        = devmode->displayflags;
1513         nt_devmode->displayfrequency    = devmode->displayfrequency;
1514         nt_devmode->icmmethod           = devmode->icmmethod;
1515         nt_devmode->icmintent           = devmode->icmintent;
1516         nt_devmode->mediatype           = devmode->mediatype;
1517         nt_devmode->dithertype          = devmode->dithertype;
1518         nt_devmode->reserved1           = devmode->reserved1;
1519         nt_devmode->reserved2           = devmode->reserved2;
1520         nt_devmode->panningwidth        = devmode->panningwidth;
1521         nt_devmode->panningheight       = devmode->panningheight;
1522
1523         /*
1524          * Only change private and driverextra if the incoming devmode
1525          * has a new one. JRA.
1526          */
1527
1528         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1529                 SAFE_FREE(nt_devmode->nt_dev_private);
1530                 nt_devmode->driverextra = devmode->__driverextra_length;
1531                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1532                         return false;
1533                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1534         }
1535
1536         *pp_nt_devmode = nt_devmode;
1537
1538         return true;
1539 }
1540
1541 /****************************************************************
1542  _spoolss_OpenPrinterEx
1543 ****************************************************************/
1544
1545 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1546                               struct spoolss_OpenPrinterEx *r)
1547 {
1548         int snum;
1549         Printer_entry *Printer=NULL;
1550
1551         if (!r->in.printername) {
1552                 return WERR_INVALID_PARAM;
1553         }
1554
1555         /* some sanity check because you can open a printer or a print server */
1556         /* aka: \\server\printer or \\server */
1557
1558         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1559
1560         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1561                 ZERO_STRUCTP(r->out.handle);
1562                 return WERR_INVALID_PARAM;
1563         }
1564
1565         Printer = find_printer_index_by_hnd(p, r->out.handle);
1566         if ( !Printer ) {
1567                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1568                         "handle we created for printer %s\n", r->in.printername));
1569                 close_printer_handle(p, r->out.handle);
1570                 ZERO_STRUCTP(r->out.handle);
1571                 return WERR_INVALID_PARAM;
1572         }
1573
1574         /*
1575          * First case: the user is opening the print server:
1576          *
1577          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1578          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1579          *
1580          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1581          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1582          * or if the user is listed in the smb.conf printer admin parameter.
1583          *
1584          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1585          * client view printer folder, but does not show the MSAPW.
1586          *
1587          * Note: this test needs code to check access rights here too. Jeremy
1588          * could you look at this?
1589          *
1590          * Second case: the user is opening a printer:
1591          * NT doesn't let us connect to a printer if the connecting user
1592          * doesn't have print permission.
1593          *
1594          * Third case: user is opening a Port Monitor
1595          * access checks same as opening a handle to the print server.
1596          */
1597
1598         switch (Printer->printer_type )
1599         {
1600         case SPLHND_SERVER:
1601         case SPLHND_PORTMON_TCP:
1602         case SPLHND_PORTMON_LOCAL:
1603                 /* Printserver handles use global struct... */
1604
1605                 snum = -1;
1606
1607                 /* Map standard access rights to object specific access rights */
1608
1609                 se_map_standard(&r->in.access_mask,
1610                                 &printserver_std_mapping);
1611
1612                 /* Deny any object specific bits that don't apply to print
1613                    servers (i.e printer and job specific bits) */
1614
1615                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1616
1617                 if (r->in.access_mask &
1618                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1619                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1620                         close_printer_handle(p, r->out.handle);
1621                         ZERO_STRUCTP(r->out.handle);
1622                         return WERR_ACCESS_DENIED;
1623                 }
1624
1625                 /* Allow admin access */
1626
1627                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1628                 {
1629                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1630
1631                         if (!lp_ms_add_printer_wizard()) {
1632                                 close_printer_handle(p, r->out.handle);
1633                                 ZERO_STRUCTP(r->out.handle);
1634                                 return WERR_ACCESS_DENIED;
1635                         }
1636
1637                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1638                            and not a printer admin, then fail */
1639
1640                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1641                             !user_has_privileges(p->server_info->ptok,
1642                                                  &se_printop ) &&
1643                             !token_contains_name_in_list(
1644                                     uidtoname(p->server_info->utok.uid),
1645                                     NULL, NULL,
1646                                     p->server_info->ptok,
1647                                     lp_printer_admin(snum))) {
1648                                 close_printer_handle(p, r->out.handle);
1649                                 ZERO_STRUCTP(r->out.handle);
1650                                 return WERR_ACCESS_DENIED;
1651                         }
1652
1653                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1654                 }
1655                 else
1656                 {
1657                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1658                 }
1659
1660                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1661                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1662
1663                 /* We fall through to return WERR_OK */
1664                 break;
1665
1666         case SPLHND_PRINTER:
1667                 /* NT doesn't let us connect to a printer if the connecting user
1668                    doesn't have print permission.  */
1669
1670                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1671                         close_printer_handle(p, r->out.handle);
1672                         ZERO_STRUCTP(r->out.handle);
1673                         return WERR_BADFID;
1674                 }
1675
1676                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1677                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1678                 }
1679
1680                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1681
1682                 /* map an empty access mask to the minimum access mask */
1683                 if (r->in.access_mask == 0x0)
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685
1686                 /*
1687                  * If we are not serving the printer driver for this printer,
1688                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1689                  * will keep NT clients happy  --jerry
1690                  */
1691
1692                 if (lp_use_client_driver(snum)
1693                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1694                 {
1695                         r->in.access_mask = PRINTER_ACCESS_USE;
1696                 }
1697
1698                 /* check smb.conf parameters and the the sec_desc */
1699
1700                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1701                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1702                         ZERO_STRUCTP(r->out.handle);
1703                         return WERR_ACCESS_DENIED;
1704                 }
1705
1706                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1707                                    p->server_info->ptok, snum) ||
1708                     !print_access_check(p->server_info, snum,
1709                                         r->in.access_mask)) {
1710                         DEBUG(3, ("access DENIED for printer open\n"));
1711                         close_printer_handle(p, r->out.handle);
1712                         ZERO_STRUCTP(r->out.handle);
1713                         return WERR_ACCESS_DENIED;
1714                 }
1715
1716                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1717                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1718                         close_printer_handle(p, r->out.handle);
1719                         ZERO_STRUCTP(r->out.handle);
1720                         return WERR_ACCESS_DENIED;
1721                 }
1722
1723                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1724                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1725                 else
1726                         r->in.access_mask = PRINTER_ACCESS_USE;
1727
1728                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1729                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1730
1731                 break;
1732
1733         default:
1734                 /* sanity check to prevent programmer error */
1735                 ZERO_STRUCTP(r->out.handle);
1736                 return WERR_BADFID;
1737         }
1738
1739         Printer->access_granted = r->in.access_mask;
1740
1741         /*
1742          * If the client sent a devmode in the OpenPrinter() call, then
1743          * save it here in case we get a job submission on this handle
1744          */
1745
1746          if ((Printer->printer_type != SPLHND_SERVER) &&
1747              r->in.devmode_ctr.devmode) {
1748                 convert_devicemode(Printer->sharename,
1749                                    r->in.devmode_ctr.devmode,
1750                                    &Printer->nt_devmode);
1751          }
1752
1753 #if 0   /* JERRY -- I'm doubtful this is really effective */
1754         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1755            optimization in Windows 2000 clients  --jerry */
1756
1757         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1758                 && (RA_WIN2K == get_remote_arch()) )
1759         {
1760                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1761                 sys_usleep( 500000 );
1762         }
1763 #endif
1764
1765         return WERR_OK;
1766 }
1767
1768 /****************************************************************************
1769 ****************************************************************************/
1770
1771 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1772                                               NT_PRINTER_INFO_LEVEL_2 *d)
1773 {
1774         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1775
1776         if (!r || !d) {
1777                 return false;
1778         }
1779
1780         d->attributes           = r->attributes;
1781         d->priority             = r->priority;
1782         d->default_priority     = r->defaultpriority;
1783         d->starttime            = r->starttime;
1784         d->untiltime            = r->untiltime;
1785         d->status               = r->status;
1786         d->cjobs                = r->cjobs;
1787
1788         fstrcpy(d->servername,  r->servername);
1789         fstrcpy(d->printername, r->printername);
1790         fstrcpy(d->sharename,   r->sharename);
1791         fstrcpy(d->portname,    r->portname);
1792         fstrcpy(d->drivername,  r->drivername);
1793         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1794         fstrcpy(d->location,    r->location);
1795         fstrcpy(d->sepfile,     r->sepfile);
1796         fstrcpy(d->printprocessor, r->printprocessor);
1797         fstrcpy(d->datatype,    r->datatype);
1798         fstrcpy(d->parameters,  r->parameters);
1799
1800         return true;
1801 }
1802
1803 /****************************************************************************
1804 ****************************************************************************/
1805
1806 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1807                                  NT_PRINTER_INFO_LEVEL *printer)
1808 {
1809         bool ret;
1810
1811         switch (info_ctr->level) {
1812         case 2:
1813                 /* allocate memory if needed.  Messy because
1814                    convert_printer_info is used to update an existing
1815                    printer or build a new one */
1816
1817                 if (!printer->info_2) {
1818                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1819                         if (!printer->info_2) {
1820                                 DEBUG(0,("convert_printer_info: "
1821                                         "talloc() failed!\n"));
1822                                 return false;
1823                         }
1824                 }
1825
1826                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1827                                                         printer->info_2);
1828                 printer->info_2->setuptime = time(NULL);
1829                 return ret;
1830         }
1831
1832         return false;
1833 }
1834
1835 /*******************************************************************
1836 ********************************************************************/
1837
1838 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1839 {
1840         int i;
1841
1842         if (!sarray) {
1843                 *farray = NULL;
1844                 return true;
1845         }
1846
1847         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1848         if (!*farray) {
1849                 return false;
1850         }
1851
1852         for (i=0; sarray[i] != NULL; i++) {
1853                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1854                 if (!*farray) {
1855                         return false;
1856                 }
1857                 fstrcpy((*farray)[i], sarray[i]);
1858         }
1859
1860         fstrcpy((*farray)[i], "");
1861
1862         return true;
1863 }
1864
1865 /*******************************************************************
1866 ********************************************************************/
1867
1868 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1869                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1870 {
1871         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1872
1873         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1874
1875         if (*p == NULL) {
1876                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1877                 if (*p == NULL) {
1878                         return false;
1879                 }
1880                 ZERO_STRUCTP(*p);
1881         }
1882
1883         d = *p;
1884
1885         d->cversion =                   r->version;
1886
1887         fstrcpy(d->name,                r->driver_name);
1888         fstrcpy(d->environment,         r->architecture);
1889         fstrcpy(d->driverpath,          r->driver_path);
1890         fstrcpy(d->datafile,            r->data_file);
1891         fstrcpy(d->configfile,          r->config_file);
1892         fstrcpy(d->helpfile,            r->help_file);
1893         fstrcpy(d->monitorname,         r->monitor_name);
1894         fstrcpy(d->defaultdatatype,     r->default_datatype);
1895
1896         DEBUGADD(8,( "version:         %d\n", d->cversion));
1897         DEBUGADD(8,( "name:            %s\n", d->name));
1898         DEBUGADD(8,( "environment:     %s\n", d->environment));
1899         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1900         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1901         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1902         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1903         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1904         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1905
1906         if (r->dependent_files) {
1907                 if (!string_array_to_fstring_array(r->dependent_files->string,
1908                                                    &d->dependentfiles)) {
1909                         SAFE_FREE(*p);
1910                         return false;
1911                 }
1912         }
1913
1914         return true;
1915 }
1916
1917 /*******************************************************************
1918 ********************************************************************/
1919
1920 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1921                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1922 {
1923         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1924
1925         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1926
1927         if (*p == NULL) {
1928                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1929                 if (*p == NULL) {
1930                         return false;
1931                 }
1932                 ZERO_STRUCTP(*p);
1933         }
1934
1935         d = *p;
1936
1937         d->version =                    r->version;
1938
1939         fstrcpy(d->name,                r->driver_name);
1940         fstrcpy(d->environment,         r->architecture);
1941         fstrcpy(d->driverpath,          r->driver_path);
1942         fstrcpy(d->datafile,            r->data_file);
1943         fstrcpy(d->configfile,          r->config_file);
1944         fstrcpy(d->helpfile,            r->help_file);
1945         fstrcpy(d->monitorname,         r->monitor_name);
1946         fstrcpy(d->defaultdatatype,     r->default_datatype);
1947
1948         DEBUGADD(8,( "version:         %d\n", d->version));
1949         DEBUGADD(8,( "name:            %s\n", d->name));
1950         DEBUGADD(8,( "environment:     %s\n", d->environment));
1951         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1952         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1953         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1954         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1955         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1956         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1957
1958         if (r->dependent_files) {
1959                 if (!string_array_to_fstring_array(r->dependent_files->string,
1960                                                    &d->dependentfiles)) {
1961                         goto error;
1962                 }
1963         }
1964
1965         if (r->previous_names) {
1966                 if (!string_array_to_fstring_array(r->previous_names->string,
1967                                                    &d->previousnames)) {
1968                         goto error;
1969                 }
1970         }
1971
1972         return true;
1973
1974  error:
1975         SAFE_FREE(*p);
1976         return false;
1977 }
1978
1979 /********************************************************************
1980  ********************************************************************/
1981
1982 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1983                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1984                                         uint32_t level)
1985 {
1986         switch (level) {
1987         case 3:
1988                 printer->info_3 = NULL;
1989                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1990                         return false;
1991                 }
1992                 break;
1993         case 6:
1994                 printer->info_6 = NULL;
1995                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1996                         return false;
1997                 }
1998                 break;
1999         default:
2000                 return false;
2001         }
2002
2003         return true;
2004 }
2005
2006 /********************************************************************
2007  * _spoolss_enddocprinter_internal.
2008  ********************************************************************/
2009
2010 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
2011                                               struct policy_handle *handle)
2012 {
2013         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2014         int snum;
2015
2016         if (!Printer) {
2017                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2018                 return WERR_BADFID;
2019         }
2020
2021         if (!get_printer_snum(p, handle, &snum, NULL))
2022                 return WERR_BADFID;
2023
2024         Printer->document_started = false;
2025         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2026         /* error codes unhandled so far ... */
2027
2028         return WERR_OK;
2029 }
2030
2031 /****************************************************************
2032  _spoolss_ClosePrinter
2033 ****************************************************************/
2034
2035 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2036                              struct spoolss_ClosePrinter *r)
2037 {
2038         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2039
2040         if (Printer && Printer->document_started)
2041                 _spoolss_enddocprinter_internal(p, r->in.handle);          /* print job was not closed */
2042
2043         if (!close_printer_handle(p, r->in.handle))
2044                 return WERR_BADFID;
2045
2046         /* clear the returned printer handle.  Observed behavior
2047            from Win2k server.  Don't think this really matters.
2048            Previous code just copied the value of the closed
2049            handle.    --jerry */
2050
2051         ZERO_STRUCTP(r->out.handle);
2052
2053         return WERR_OK;
2054 }
2055
2056 /****************************************************************
2057  _spoolss_DeletePrinter
2058 ****************************************************************/
2059
2060 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2061                               struct spoolss_DeletePrinter *r)
2062 {
2063         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2064         WERROR result;
2065
2066         if (Printer && Printer->document_started)
2067                 _spoolss_enddocprinter_internal(p, r->in.handle);  /* print job was not closed */
2068
2069         result = delete_printer_handle(p, r->in.handle);
2070
2071         update_c_setprinter(false);
2072
2073         return result;
2074 }
2075
2076 /*******************************************************************
2077  * static function to lookup the version id corresponding to an
2078  * long architecture string
2079  ******************************************************************/
2080
2081 static int get_version_id(const char *arch)
2082 {
2083         int i;
2084         struct print_architecture_table_node archi_table[]= {
2085
2086                 {"Windows 4.0",          "WIN40",       0 },
2087                 {"Windows NT x86",       "W32X86",      2 },
2088                 {"Windows NT R4000",     "W32MIPS",     2 },
2089                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2090                 {"Windows NT PowerPC",   "W32PPC",      2 },
2091                 {"Windows IA64",         "IA64",        3 },
2092                 {"Windows x64",          "x64",         3 },
2093                 {NULL,                   "",            -1 }
2094         };
2095
2096         for (i=0; archi_table[i].long_archi != NULL; i++)
2097         {
2098                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2099                         return (archi_table[i].version);
2100         }
2101
2102         return -1;
2103 }
2104
2105 /****************************************************************
2106  _spoolss_DeletePrinterDriver
2107 ****************************************************************/
2108
2109 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2110                                     struct spoolss_DeletePrinterDriver *r)
2111 {
2112         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2113         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2114         int                             version;
2115         WERROR                          status;
2116         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2117         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2118
2119         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2120            and not a printer admin, then fail */
2121
2122         if ( (p->server_info->utok.uid != sec_initial_uid())
2123                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2124                 && !token_contains_name_in_list(
2125                         uidtoname(p->server_info->utok.uid), NULL,
2126                         NULL, p->server_info->ptok,
2127                         lp_printer_admin(-1)) )
2128         {
2129                 return WERR_ACCESS_DENIED;
2130         }
2131
2132         /* check that we have a valid driver name first */
2133
2134         if ((version = get_version_id(r->in.architecture)) == -1)
2135                 return WERR_INVALID_ENVIRONMENT;
2136
2137         ZERO_STRUCT(info);
2138         ZERO_STRUCT(info_win2k);
2139
2140         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2141                                                 r->in.architecture,
2142                                                 version)))
2143         {
2144                 /* try for Win2k driver if "Windows NT x86" */
2145
2146                 if ( version == 2 ) {
2147                         version = 3;
2148                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2149                                                                 r->in.driver,
2150                                                                 r->in.architecture,
2151                                                                 version))) {
2152                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2153                                 goto done;
2154                         }
2155                 }
2156                 /* otherwise it was a failure */
2157                 else {
2158                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2159                         goto done;
2160                 }
2161
2162         }
2163
2164         if (printer_driver_in_use(info.info_3)) {
2165                 status = WERR_PRINTER_DRIVER_IN_USE;
2166                 goto done;
2167         }
2168
2169         if ( version == 2 )
2170         {
2171                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2172                                                        r->in.driver,
2173                                                        r->in.architecture, 3)))
2174                 {
2175                         /* if we get to here, we now have 2 driver info structures to remove */
2176                         /* remove the Win2k driver first*/
2177
2178                         status_win2k = delete_printer_driver(
2179                                 p, info_win2k.info_3, 3, false);
2180                         free_a_printer_driver( info_win2k, 3 );
2181
2182                         /* this should not have failed---if it did, report to client */
2183                         if ( !W_ERROR_IS_OK(status_win2k) )
2184                         {
2185                                 status = status_win2k;
2186                                 goto done;
2187                         }
2188                 }
2189         }
2190
2191         status = delete_printer_driver(p, info.info_3, version, false);
2192
2193         /* if at least one of the deletes succeeded return OK */
2194
2195         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2196                 status = WERR_OK;
2197
2198 done:
2199         free_a_printer_driver( info, 3 );
2200
2201         return status;
2202 }
2203
2204 /****************************************************************
2205  _spoolss_DeletePrinterDriverEx
2206 ****************************************************************/
2207
2208 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2209                                       struct spoolss_DeletePrinterDriverEx *r)
2210 {
2211         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2212         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2213         int                             version;
2214         bool                            delete_files;
2215         WERROR                          status;
2216         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2217         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2218
2219         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2220            and not a printer admin, then fail */
2221
2222         if ( (p->server_info->utok.uid != sec_initial_uid())
2223                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2224                 && !token_contains_name_in_list(
2225                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2226                         p->server_info->ptok, lp_printer_admin(-1)) )
2227         {
2228                 return WERR_ACCESS_DENIED;
2229         }
2230
2231         /* check that we have a valid driver name first */
2232         if ((version = get_version_id(r->in.architecture)) == -1) {
2233                 /* this is what NT returns */
2234                 return WERR_INVALID_ENVIRONMENT;
2235         }
2236
2237         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2238                 version = r->in.version;
2239
2240         ZERO_STRUCT(info);
2241         ZERO_STRUCT(info_win2k);
2242
2243         status = get_a_printer_driver(&info, 3, r->in.driver,
2244                                       r->in.architecture, version);
2245
2246         if ( !W_ERROR_IS_OK(status) )
2247         {
2248                 /*
2249                  * if the client asked for a specific version,
2250                  * or this is something other than Windows NT x86,
2251                  * then we've failed
2252                  */
2253
2254                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2255                         goto done;
2256
2257                 /* try for Win2k driver if "Windows NT x86" */
2258
2259                 version = 3;
2260                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2261                                                         r->in.architecture,
2262                                                         version))) {
2263                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2264                         goto done;
2265                 }
2266         }
2267
2268         if ( printer_driver_in_use(info.info_3) ) {
2269                 status = WERR_PRINTER_DRIVER_IN_USE;
2270                 goto done;
2271         }
2272
2273         /*
2274          * we have a couple of cases to consider.
2275          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2276          *     then the delete should fail if **any** files overlap with
2277          *     other drivers
2278          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2279          *     non-overlapping files
2280          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2281          *     is set, the do not delete any files
2282          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2283          */
2284
2285         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2286
2287         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2288
2289         if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2290                 /* no idea of the correct error here */
2291                 status = WERR_ACCESS_DENIED;
2292                 goto done;
2293         }
2294
2295
2296         /* also check for W32X86/3 if necessary; maybe we already have? */
2297
2298         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2299                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2300                                                        r->in.driver,
2301                                                        r->in.architecture, 3)))
2302                 {
2303
2304                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2305                                 /* no idea of the correct error here */
2306                                 free_a_printer_driver( info_win2k, 3 );
2307                                 status = WERR_ACCESS_DENIED;
2308                                 goto done;
2309                         }
2310
2311                         /* if we get to here, we now have 2 driver info structures to remove */
2312                         /* remove the Win2k driver first*/
2313
2314                         status_win2k = delete_printer_driver(
2315                                 p, info_win2k.info_3, 3, delete_files);
2316                         free_a_printer_driver( info_win2k, 3 );
2317
2318                         /* this should not have failed---if it did, report to client */
2319
2320                         if ( !W_ERROR_IS_OK(status_win2k) )
2321                                 goto done;
2322                 }
2323         }
2324
2325         status = delete_printer_driver(p, info.info_3, version, delete_files);
2326
2327         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2328                 status = WERR_OK;
2329 done:
2330         free_a_printer_driver( info, 3 );
2331
2332         return status;
2333 }
2334
2335
2336 /****************************************************************************
2337  Internal routine for removing printerdata
2338  ***************************************************************************/
2339
2340 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2341 {
2342         return delete_printer_data( printer->info_2, key, value );
2343 }
2344
2345 /****************************************************************************
2346  Internal routine for storing printerdata
2347  ***************************************************************************/
2348
2349 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2350                           const char *key, const char *value,
2351                           uint32_t type, uint8_t *data, int real_len)
2352 {
2353         /* the registry objects enforce uniqueness based on value name */
2354
2355         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2356 }
2357
2358 /********************************************************************
2359  GetPrinterData on a printer server Handle.
2360 ********************************************************************/
2361
2362 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2363                                             const char *value,
2364                                             enum winreg_Type *type,
2365                                             union spoolss_PrinterData *data)
2366 {
2367         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2368
2369         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2370                 *type = REG_DWORD;
2371                 data->value = 0x00;
2372                 return WERR_OK;
2373         }
2374
2375         if (!StrCaseCmp(value, "BeepEnabled")) {
2376                 *type = REG_DWORD;
2377                 data->value = 0x00;
2378                 return WERR_OK;
2379         }
2380
2381         if (!StrCaseCmp(value, "EventLog")) {
2382                 *type = REG_DWORD;
2383                 /* formally was 0x1b */
2384                 data->value = 0x00;
2385                 return WERR_OK;
2386         }
2387
2388         if (!StrCaseCmp(value, "NetPopup")) {
2389                 *type = REG_DWORD;
2390                 data->value = 0x00;
2391                 return WERR_OK;
2392         }
2393
2394         if (!StrCaseCmp(value, "MajorVersion")) {
2395                 *type = REG_DWORD;
2396
2397                 /* Windows NT 4.0 seems to not allow uploading of drivers
2398                    to a server that reports 0x3 as the MajorVersion.
2399                    need to investigate more how Win2k gets around this .
2400                    -- jerry */
2401
2402                 if (RA_WINNT == get_remote_arch()) {
2403                         data->value = 0x02;
2404                 } else {
2405                         data->value = 0x03;
2406                 }
2407
2408                 return WERR_OK;
2409         }
2410
2411         if (!StrCaseCmp(value, "MinorVersion")) {
2412                 *type = REG_DWORD;
2413                 data->value = 0x00;
2414                 return WERR_OK;
2415         }
2416
2417         /* REG_BINARY
2418          *  uint32_t size        = 0x114
2419          *  uint32_t major       = 5
2420          *  uint32_t minor       = [0|1]
2421          *  uint32_t build       = [2195|2600]
2422          *  extra unicode string = e.g. "Service Pack 3"
2423          */
2424         if (!StrCaseCmp(value, "OSVersion")) {
2425                 DATA_BLOB blob;
2426                 enum ndr_err_code ndr_err;
2427                 struct spoolss_OSVersion os;
2428
2429                 os.major                = 5;    /* Windows 2000 == 5.0 */
2430                 os.minor                = 0;
2431                 os.build                = 2195; /* build */
2432                 os.extra_string         = "";   /* leave extra string empty */
2433
2434                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2435                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2436                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2437                         return WERR_GENERAL_FAILURE;
2438                 }
2439
2440                 *type = REG_BINARY;
2441                 data->binary = blob;
2442
2443                 return WERR_OK;
2444         }
2445
2446
2447         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2448                 *type = REG_SZ;
2449
2450                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2451                 W_ERROR_HAVE_NO_MEMORY(data->string);
2452
2453                 return WERR_OK;
2454         }
2455
2456         if (!StrCaseCmp(value, "Architecture")) {
2457                 *type = REG_SZ;
2458
2459                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2460                 W_ERROR_HAVE_NO_MEMORY(data->string);
2461
2462                 return WERR_OK;
2463         }
2464
2465         if (!StrCaseCmp(value, "DsPresent")) {
2466                 *type = REG_DWORD;
2467
2468                 /* only show the publish check box if we are a
2469                    member of a AD domain */
2470
2471                 if (lp_security() == SEC_ADS) {
2472                         data->value = 0x01;
2473                 } else {
2474                         data->value = 0x00;
2475                 }
2476                 return WERR_OK;
2477         }
2478
2479         if (!StrCaseCmp(value, "DNSMachineName")) {
2480                 const char *hostname = get_mydnsfullname();
2481
2482                 if (!hostname) {
2483                         return WERR_BADFILE;
2484                 }
2485
2486                 *type = REG_SZ;
2487                 data->string = talloc_strdup(mem_ctx, hostname);
2488                 W_ERROR_HAVE_NO_MEMORY(data->string);
2489
2490                 return WERR_OK;
2491         }
2492
2493         *type = REG_NONE;
2494
2495         return WERR_INVALID_PARAM;
2496 }
2497
2498 /****************************************************************
2499  _spoolss_GetPrinterData
2500 ****************************************************************/
2501
2502 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2503                                struct spoolss_GetPrinterData *r)
2504 {
2505         struct spoolss_GetPrinterDataEx r2;
2506
2507         r2.in.handle            = r->in.handle;
2508         r2.in.key_name          = "PrinterDriverData";
2509         r2.in.value_name        = r->in.value_name;
2510         r2.in.offered           = r->in.offered;
2511         r2.out.type             = r->out.type;
2512         r2.out.data             = r->out.data;
2513         r2.out.needed           = r->out.needed;
2514
2515         return _spoolss_GetPrinterDataEx(p, &r2);
2516 }
2517
2518 /*********************************************************
2519  Connect to the client machine.
2520 **********************************************************/
2521
2522 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2523                         struct sockaddr_storage *client_ss, const char *remote_machine)
2524 {
2525         NTSTATUS ret;
2526         struct cli_state *the_cli;
2527         struct sockaddr_storage rm_addr;
2528
2529         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2530                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2531                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2532                         return false;
2533                 }
2534
2535                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2536                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2537                         return false;
2538                 }
2539         } else {
2540                 char addr[INET6_ADDRSTRLEN];
2541                 rm_addr = *client_ss;
2542                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2543                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2544                         addr));
2545         }
2546
2547         /* setup the connection */
2548
2549         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2550                 &rm_addr, 0, "IPC$", "IPC",
2551                 "", /* username */
2552                 "", /* domain */
2553                 "", /* password */
2554                 0, lp_client_signing(), NULL );
2555
2556         if ( !NT_STATUS_IS_OK( ret ) ) {
2557                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2558                         remote_machine ));
2559                 return false;
2560         }
2561
2562         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2563                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2564                 cli_shutdown(the_cli);
2565                 return false;
2566         }
2567
2568         /*
2569          * Ok - we have an anonymous connection to the IPC$ share.
2570          * Now start the NT Domain stuff :-).
2571          */
2572
2573         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2574         if (!NT_STATUS_IS_OK(ret)) {
2575                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2576                         remote_machine, nt_errstr(ret)));
2577                 cli_shutdown(the_cli);
2578                 return false;
2579         }
2580
2581         return true;
2582 }
2583
2584 /***************************************************************************
2585  Connect to the client.
2586 ****************************************************************************/
2587
2588 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2589                                         uint32_t localprinter, uint32_t type,
2590                                         struct policy_handle *handle,
2591                                         struct sockaddr_storage *client_ss)
2592 {
2593         WERROR result;
2594         NTSTATUS status;
2595
2596         /*
2597          * If it's the first connection, contact the client
2598          * and connect to the IPC$ share anonymously
2599          */
2600         if (smb_connections==0) {
2601                 fstring unix_printer;
2602
2603                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2604
2605                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2606                         return false;
2607
2608                 messaging_register(smbd_messaging_context(), NULL,
2609                                    MSG_PRINTER_NOTIFY2,
2610                                    receive_notify2_message_list);
2611                 /* Tell the connections db we're now interested in printer
2612                  * notify messages. */
2613                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2614         }
2615
2616         /*
2617          * Tell the specific printing tdb we want messages for this printer
2618          * by registering our PID.
2619          */
2620
2621         if (!print_notify_register_pid(snum))
2622                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2623
2624         smb_connections++;
2625
2626         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2627                                                  printer,
2628                                                  localprinter,
2629                                                  type,
2630                                                  0,
2631                                                  NULL,
2632                                                  handle,
2633                                                  &result);
2634         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2635                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2636                         win_errstr(result)));
2637
2638         return (W_ERROR_IS_OK(result));
2639 }
2640
2641 /****************************************************************
2642  ****************************************************************/
2643
2644 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2645                                                              const struct spoolss_NotifyOption *r)
2646 {
2647         struct spoolss_NotifyOption *option;
2648         uint32_t i,k;
2649
2650         if (!r) {
2651                 return NULL;
2652         }
2653
2654         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2655         if (!option) {
2656                 return NULL;
2657         }
2658
2659         *option = *r;
2660
2661         if (!option->count) {
2662                 return option;
2663         }
2664
2665         option->types = talloc_zero_array(option,
2666                 struct spoolss_NotifyOptionType, option->count);
2667         if (!option->types) {
2668                 talloc_free(option);
2669                 return NULL;
2670         }
2671
2672         for (i=0; i < option->count; i++) {
2673                 option->types[i] = r->types[i];
2674
2675                 if (option->types[i].count) {
2676                         option->types[i].fields = talloc_zero_array(option,
2677                                 union spoolss_Field, option->types[i].count);
2678                         if (!option->types[i].fields) {
2679                                 talloc_free(option);
2680                                 return NULL;
2681                         }
2682                         for (k=0; k<option->types[i].count; k++) {
2683                                 option->types[i].fields[k] =
2684                                         r->types[i].fields[k];
2685                         }
2686                 }
2687         }
2688
2689         return option;
2690 }
2691
2692 /****************************************************************
2693  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2694  *
2695  * before replying OK: status=0 a rpc call is made to the workstation
2696  * asking ReplyOpenPrinter
2697  *
2698  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2699  * called from api_spoolss_rffpcnex
2700 ****************************************************************/
2701
2702 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2703                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2704 {
2705         int snum = -1;
2706         struct spoolss_NotifyOption *option = r->in.notify_options;
2707         struct sockaddr_storage client_ss;
2708
2709         /* store the notify value in the printer struct */
2710
2711         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2712
2713         if (!Printer) {
2714                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715                         "Invalid handle (%s:%u:%u).\n",
2716                         OUR_HANDLE(r->in.handle)));
2717                 return WERR_BADFID;
2718         }
2719
2720         Printer->notify.flags           = r->in.flags;
2721         Printer->notify.options         = r->in.options;
2722         Printer->notify.printerlocal    = r->in.printer_local;
2723
2724         TALLOC_FREE(Printer->notify.option);
2725         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2726
2727         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2728
2729         /* Connect to the client machine and send a ReplyOpenPrinter */
2730
2731         if ( Printer->printer_type == SPLHND_SERVER)
2732                 snum = -1;
2733         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2734                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2735                 return WERR_BADFID;
2736
2737         if (!interpret_string_addr(&client_ss, p->client_address,
2738                                    AI_NUMERICHOST)) {
2739                 return WERR_SERVER_UNAVAILABLE;
2740         }
2741
2742         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2743                                         Printer->notify.printerlocal, 1,
2744                                         &Printer->notify.client_hnd, &client_ss))
2745                 return WERR_SERVER_UNAVAILABLE;
2746
2747         Printer->notify.client_connected = true;
2748
2749         return WERR_OK;
2750 }
2751
2752 /*******************************************************************
2753  * fill a notify_info_data with the servername
2754  ********************************************************************/
2755
2756 void spoolss_notify_server_name(int snum,
2757                                        struct spoolss_Notify *data,
2758                                        print_queue_struct *queue,
2759                                        NT_PRINTER_INFO_LEVEL *printer,
2760                                        TALLOC_CTX *mem_ctx)
2761 {
2762         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2763 }
2764
2765 /*******************************************************************
2766  * fill a notify_info_data with the printername (not including the servername).
2767  ********************************************************************/
2768
2769 void spoolss_notify_printer_name(int snum,
2770                                         struct spoolss_Notify *data,
2771                                         print_queue_struct *queue,
2772                                         NT_PRINTER_INFO_LEVEL *printer,
2773                                         TALLOC_CTX *mem_ctx)
2774 {
2775         /* the notify name should not contain the \\server\ part */
2776         char *p = strrchr(printer->info_2->printername, '\\');
2777
2778         if (!p) {
2779                 p = printer->info_2->printername;
2780         } else {
2781                 p++;
2782         }
2783
2784         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2785 }
2786
2787 /*******************************************************************
2788  * fill a notify_info_data with the servicename
2789  ********************************************************************/
2790
2791 void spoolss_notify_share_name(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, lp_servicename(snum));
2798 }
2799
2800 /*******************************************************************
2801  * fill a notify_info_data with the port name
2802  ********************************************************************/
2803
2804 void spoolss_notify_port_name(int snum,
2805                                      struct spoolss_Notify *data,
2806                                      print_queue_struct *queue,
2807                                      NT_PRINTER_INFO_LEVEL *printer,
2808                                      TALLOC_CTX *mem_ctx)
2809 {
2810         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2811 }
2812
2813 /*******************************************************************
2814  * fill a notify_info_data with the printername
2815  * but it doesn't exist, have to see what to do
2816  ********************************************************************/
2817
2818 void spoolss_notify_driver_name(int snum,
2819                                        struct spoolss_Notify *data,
2820                                        print_queue_struct *queue,
2821                                        NT_PRINTER_INFO_LEVEL *printer,
2822                                        TALLOC_CTX *mem_ctx)
2823 {
2824         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2825 }
2826
2827 /*******************************************************************
2828  * fill a notify_info_data with the comment
2829  ********************************************************************/
2830
2831 void spoolss_notify_comment(int snum,
2832                                    struct spoolss_Notify *data,
2833                                    print_queue_struct *queue,
2834                                    NT_PRINTER_INFO_LEVEL *printer,
2835                                    TALLOC_CTX *mem_ctx)
2836 {
2837         char *p;
2838
2839         if (*printer->info_2->comment == '\0') {
2840                 p = lp_comment(snum);
2841         } else {
2842                 p = printer->info_2->comment;
2843         }
2844
2845         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2846 }
2847
2848 /*******************************************************************
2849  * fill a notify_info_data with the comment
2850  * location = "Room 1, floor 2, building 3"
2851  ********************************************************************/
2852
2853 void spoolss_notify_location(int snum,
2854                                     struct spoolss_Notify *data,
2855                                     print_queue_struct *queue,
2856                                     NT_PRINTER_INFO_LEVEL *printer,
2857                                     TALLOC_CTX *mem_ctx)
2858 {
2859         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2860 }
2861
2862 /*******************************************************************
2863  * fill a notify_info_data with the device mode
2864  * jfm:xxxx don't to it for know but that's a real problem !!!
2865  ********************************************************************/
2866
2867 static void spoolss_notify_devmode(int snum,
2868                                    struct spoolss_Notify *data,
2869                                    print_queue_struct *queue,
2870                                    NT_PRINTER_INFO_LEVEL *printer,
2871                                    TALLOC_CTX *mem_ctx)
2872 {
2873         /* for a dummy implementation we have to zero the fields */
2874         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2875 }
2876
2877 /*******************************************************************
2878  * fill a notify_info_data with the separator file name
2879  ********************************************************************/
2880
2881 void spoolss_notify_sepfile(int snum,
2882                                    struct spoolss_Notify *data,
2883                                    print_queue_struct *queue,
2884                                    NT_PRINTER_INFO_LEVEL *printer,
2885                                    TALLOC_CTX *mem_ctx)
2886 {
2887         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2888 }
2889
2890 /*******************************************************************
2891  * fill a notify_info_data with the print processor
2892  * jfm:xxxx return always winprint to indicate we don't do anything to it
2893  ********************************************************************/
2894
2895 void spoolss_notify_print_processor(int snum,
2896                                            struct spoolss_Notify *data,
2897                                            print_queue_struct *queue,
2898                                            NT_PRINTER_INFO_LEVEL *printer,
2899                                            TALLOC_CTX *mem_ctx)
2900 {
2901         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2902 }
2903
2904 /*******************************************************************
2905  * fill a notify_info_data with the print processor options
2906  * jfm:xxxx send an empty string
2907  ********************************************************************/
2908
2909 void spoolss_notify_parameters(int snum,
2910                                       struct spoolss_Notify *data,
2911                                       print_queue_struct *queue,
2912                                       NT_PRINTER_INFO_LEVEL *printer,
2913                                       TALLOC_CTX *mem_ctx)
2914 {
2915         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2916 }
2917
2918 /*******************************************************************
2919  * fill a notify_info_data with the data type
2920  * jfm:xxxx always send RAW as data type
2921  ********************************************************************/
2922
2923 void spoolss_notify_datatype(int snum,
2924                                     struct spoolss_Notify *data,
2925                                     print_queue_struct *queue,
2926                                     NT_PRINTER_INFO_LEVEL *printer,
2927                                     TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the security descriptor
2934  * jfm:xxxx send an null pointer to say no security desc
2935  * have to implement security before !
2936  ********************************************************************/
2937
2938 static void spoolss_notify_security_desc(int snum,
2939                                          struct spoolss_Notify *data,
2940                                          print_queue_struct *queue,
2941                                          NT_PRINTER_INFO_LEVEL *printer,
2942                                          TALLOC_CTX *mem_ctx)
2943 {
2944         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2945                                           printer->info_2->secdesc_buf->sd_size,
2946                                           printer->info_2->secdesc_buf->sd);
2947 }
2948
2949 /*******************************************************************
2950  * fill a notify_info_data with the attributes
2951  * jfm:xxxx a samba printer is always shared
2952  ********************************************************************/
2953
2954 void spoolss_notify_attributes(int snum,
2955                                       struct spoolss_Notify *data,
2956                                       print_queue_struct *queue,
2957                                       NT_PRINTER_INFO_LEVEL *printer,
2958                                       TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the priority
2965  ********************************************************************/
2966
2967 static void spoolss_notify_priority(int snum,
2968                                     struct spoolss_Notify *data,
2969                                     print_queue_struct *queue,
2970                                     NT_PRINTER_INFO_LEVEL *printer,
2971                                     TALLOC_CTX *mem_ctx)
2972 {
2973         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2974 }
2975
2976 /*******************************************************************
2977  * fill a notify_info_data with the default priority
2978  ********************************************************************/
2979
2980 static void spoolss_notify_default_priority(int snum,
2981                                             struct spoolss_Notify *data,
2982                                             print_queue_struct *queue,
2983                                             NT_PRINTER_INFO_LEVEL *printer,
2984                                             TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the start time
2991  ********************************************************************/
2992
2993 static void spoolss_notify_start_time(int snum,
2994                                       struct spoolss_Notify *data,
2995                                       print_queue_struct *queue,
2996                                       NT_PRINTER_INFO_LEVEL *printer,
2997                                       TALLOC_CTX *mem_ctx)
2998 {
2999         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3000 }
3001
3002 /*******************************************************************
3003  * fill a notify_info_data with the until time
3004  ********************************************************************/
3005
3006 static void spoolss_notify_until_time(int snum,
3007                                       struct spoolss_Notify *data,
3008                                       print_queue_struct *queue,
3009                                       NT_PRINTER_INFO_LEVEL *printer,
3010                                       TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the status
3017  ********************************************************************/
3018
3019 static void spoolss_notify_status(int snum,
3020                                   struct spoolss_Notify *data,
3021                                   print_queue_struct *queue,
3022                                   NT_PRINTER_INFO_LEVEL *printer,
3023                                   TALLOC_CTX *mem_ctx)
3024 {
3025         print_status_struct status;
3026
3027         print_queue_length(snum, &status);
3028         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3029 }
3030
3031 /*******************************************************************
3032  * fill a notify_info_data with the number of jobs queued
3033  ********************************************************************/
3034
3035 void spoolss_notify_cjobs(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, print_queue_length(snum, NULL));
3042 }
3043
3044 /*******************************************************************
3045  * fill a notify_info_data with the average ppm
3046  ********************************************************************/
3047
3048 static void spoolss_notify_average_ppm(int snum,
3049                                        struct spoolss_Notify *data,
3050                                        print_queue_struct *queue,
3051                                        NT_PRINTER_INFO_LEVEL *printer,
3052                                        TALLOC_CTX *mem_ctx)
3053 {
3054         /* always respond 8 pages per minutes */
3055         /* a little hard ! */
3056         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3057 }
3058
3059 /*******************************************************************
3060  * fill a notify_info_data with username
3061  ********************************************************************/
3062
3063 static void spoolss_notify_username(int snum,
3064                                     struct spoolss_Notify *data,
3065                                     print_queue_struct *queue,
3066                                     NT_PRINTER_INFO_LEVEL *printer,
3067                                     TALLOC_CTX *mem_ctx)
3068 {
3069         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3070 }
3071
3072 /*******************************************************************
3073  * fill a notify_info_data with job status
3074  ********************************************************************/
3075
3076 static void spoolss_notify_job_status(int snum,
3077                                       struct spoolss_Notify *data,
3078                                       print_queue_struct *queue,
3079                                       NT_PRINTER_INFO_LEVEL *printer,
3080                                       TALLOC_CTX *mem_ctx)
3081 {
3082         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3083 }
3084
3085 /*******************************************************************
3086  * fill a notify_info_data with job name
3087  ********************************************************************/
3088
3089 static void spoolss_notify_job_name(int snum,
3090                                     struct spoolss_Notify *data,
3091                                     print_queue_struct *queue,
3092                                     NT_PRINTER_INFO_LEVEL *printer,
3093                                     TALLOC_CTX *mem_ctx)
3094 {
3095         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3096 }
3097
3098 /*******************************************************************
3099  * fill a notify_info_data with job status
3100  ********************************************************************/
3101
3102 static void spoolss_notify_job_status_string(int snum,
3103                                              struct spoolss_Notify *data,
3104                                              print_queue_struct *queue,
3105                                              NT_PRINTER_INFO_LEVEL *printer,
3106                                              TALLOC_CTX *mem_ctx)
3107 {
3108         /*
3109          * Now we're returning job status codes we just return a "" here. JRA.
3110          */
3111
3112         const char *p = "";
3113
3114 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3115         p = "unknown";
3116
3117         switch (queue->status) {
3118         case LPQ_QUEUED:
3119                 p = "Queued";
3120                 break;
3121         case LPQ_PAUSED:
3122                 p = "";    /* NT provides the paused string */
3123                 break;
3124         case LPQ_SPOOLING:
3125                 p = "Spooling";
3126                 break;
3127         case LPQ_PRINTING:
3128                 p = "Printing";
3129                 break;
3130         }
3131 #endif /* NO LONGER NEEDED. */
3132
3133         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3134 }
3135
3136 /*******************************************************************
3137  * fill a notify_info_data with job time
3138  ********************************************************************/
3139
3140 static void spoolss_notify_job_time(int snum,
3141                                     struct spoolss_Notify *data,
3142                                     print_queue_struct *queue,
3143                                     NT_PRINTER_INFO_LEVEL *printer,
3144                                     TALLOC_CTX *mem_ctx)
3145 {
3146         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3147 }
3148
3149 /*******************************************************************
3150  * fill a notify_info_data with job size
3151  ********************************************************************/
3152
3153 static void spoolss_notify_job_size(int snum,
3154                                     struct spoolss_Notify *data,
3155                                     print_queue_struct *queue,
3156                                     NT_PRINTER_INFO_LEVEL *printer,
3157                                     TALLOC_CTX *mem_ctx)
3158 {
3159         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with page info
3164  ********************************************************************/
3165 static void spoolss_notify_total_pages(int snum,
3166                                 struct spoolss_Notify *data,
3167                                 print_queue_struct *queue,
3168                                 NT_PRINTER_INFO_LEVEL *printer,
3169                                 TALLOC_CTX *mem_ctx)
3170 {
3171         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3172 }
3173
3174 /*******************************************************************
3175  * fill a notify_info_data with pages printed info.
3176  ********************************************************************/
3177 static void spoolss_notify_pages_printed(int snum,
3178                                 struct spoolss_Notify *data,
3179                                 print_queue_struct *queue,
3180                                 NT_PRINTER_INFO_LEVEL *printer,
3181                                 TALLOC_CTX *mem_ctx)
3182 {
3183         /* Add code when back-end tracks this */
3184         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3185 }
3186
3187 /*******************************************************************
3188  Fill a notify_info_data with job position.
3189  ********************************************************************/
3190
3191 static void spoolss_notify_job_position(int snum,
3192                                         struct spoolss_Notify *data,
3193                                         print_queue_struct *queue,
3194                                         NT_PRINTER_INFO_LEVEL *printer,
3195                                         TALLOC_CTX *mem_ctx)
3196 {
3197         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3198 }
3199
3200 /*******************************************************************
3201  Fill a notify_info_data with submitted time.
3202  ********************************************************************/
3203
3204 static void spoolss_notify_submitted_time(int snum,
3205                                           struct spoolss_Notify *data,
3206                                           print_queue_struct *queue,
3207                                           NT_PRINTER_INFO_LEVEL *printer,
3208                                           TALLOC_CTX *mem_ctx)
3209 {
3210         data->data.string.string = NULL;
3211         data->data.string.size = 0;
3212
3213         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3214                                &data->data.string.string,
3215                                &data->data.string.size);
3216
3217 }
3218
3219 struct s_notify_info_data_table
3220 {
3221         enum spoolss_NotifyType type;
3222         uint16_t field;
3223         const char *name;
3224         enum spoolss_NotifyTable variable_type;
3225         void (*fn) (int snum, struct spoolss_Notify *data,
3226                     print_queue_struct *queue,
3227                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3228 };
3229
3230 /* A table describing the various print notification constants and
3231    whether the notification data is a pointer to a variable sized
3232    buffer, a one value uint32_t or a two value uint32_t. */
3233
3234 static const struct s_notify_info_data_table notify_info_data_table[] =
3235 {
3236 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3237 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3238 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3239 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3262 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3263 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3264 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3265 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3266 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3267 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3268 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3269 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3270 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3271 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3272 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3273 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3274 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3275 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3276 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3277 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3278 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3279 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3280 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3285 };
3286
3287 /*******************************************************************
3288  Return the variable_type of info_data structure.
3289 ********************************************************************/
3290
3291 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3292                                                   uint16_t field)
3293 {
3294         int i=0;
3295
3296         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3297                 if ( (notify_info_data_table[i].type == type) &&
3298                      (notify_info_data_table[i].field == field) ) {
3299                         return notify_info_data_table[i].variable_type;
3300                 }
3301         }
3302
3303         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3304
3305         return 0;
3306 }
3307
3308 /****************************************************************************
3309 ****************************************************************************/
3310
3311 static bool search_notify(enum spoolss_NotifyType type,
3312                           uint16_t field,
3313                           int *value)
3314 {
3315         int i;
3316
3317         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3318                 if (notify_info_data_table[i].type == type &&
3319                     notify_info_data_table[i].field == field &&
3320                     notify_info_data_table[i].fn != NULL) {
3321                         *value = i;
3322                         return true;
3323                 }
3324         }
3325
3326         return false;
3327 }
3328
3329 /****************************************************************************
3330 ****************************************************************************/
3331
3332 void construct_info_data(struct spoolss_Notify *info_data,
3333                          enum spoolss_NotifyType type,
3334                          uint16_t field,
3335                          int id)
3336 {
3337         info_data->type                 = type;
3338         info_data->field.field          = field;
3339         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3340         info_data->job_id               = id;
3341 }
3342
3343 /*******************************************************************
3344  *
3345  * fill a notify_info struct with info asked
3346  *
3347  ********************************************************************/
3348
3349 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3350                                           struct spoolss_NotifyInfo *info,
3351                                           int snum,
3352                                           const struct spoolss_NotifyOptionType *option_type,
3353                                           uint32_t id,
3354                                           TALLOC_CTX *mem_ctx)
3355 {
3356         int field_num,j;
3357         enum spoolss_NotifyType type;
3358         uint16_t field;
3359
3360         struct spoolss_Notify *current_data;
3361         NT_PRINTER_INFO_LEVEL *printer = NULL;
3362         print_queue_struct *queue=NULL;
3363
3364         type = option_type->type;
3365
3366         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3367                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3368                 option_type->count, lp_servicename(snum)));
3369
3370         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3371                 return false;
3372
3373         for(field_num=0; field_num < option_type->count; field_num++) {
3374                 field = option_type->fields[field_num].field;
3375
3376                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3377
3378                 if (!search_notify(type, field, &j) )
3379                         continue;
3380
3381                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3382                                                       struct spoolss_Notify,
3383                                                       info->count + 1);
3384                 if (info->notifies == NULL) {
3385                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3386                         free_a_printer(&printer, 2);
3387                         return false;
3388                 }
3389
3390                 current_data = &info->notifies[info->count];
3391
3392                 construct_info_data(current_data, type, field, id);
3393
3394                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3395                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3396
3397                 notify_info_data_table[j].fn(snum, current_data, queue,
3398                                              printer, mem_ctx);
3399
3400                 info->count++;
3401         }
3402
3403         free_a_printer(&printer, 2);
3404         return true;
3405 }
3406
3407 /*******************************************************************
3408  *
3409  * fill a notify_info struct with info asked
3410  *
3411  ********************************************************************/
3412
3413 static bool construct_notify_jobs_info(print_queue_struct *queue,
3414                                        struct spoolss_NotifyInfo *info,
3415                                        NT_PRINTER_INFO_LEVEL *printer,
3416                                        int snum,
3417                                        const struct spoolss_NotifyOptionType *option_type,
3418                                        uint32_t id,
3419                                        TALLOC_CTX *mem_ctx)
3420 {
3421         int field_num,j;
3422         enum spoolss_NotifyType type;
3423         uint16_t field;
3424         struct spoolss_Notify *current_data;
3425
3426         DEBUG(4,("construct_notify_jobs_info\n"));
3427
3428         type = option_type->type;
3429
3430         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3431                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3432                 option_type->count));
3433
3434         for(field_num=0; field_num<option_type->count; field_num++) {
3435                 field = option_type->fields[field_num].field;
3436
3437                 if (!search_notify(type, field, &j) )
3438                         continue;
3439
3440                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3441                                                       struct spoolss_Notify,
3442                                                       info->count + 1);
3443                 if (info->notifies == NULL) {
3444                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3445                         return false;
3446                 }
3447
3448                 current_data=&(info->notifies[info->count]);
3449
3450                 construct_info_data(current_data, type, field, id);
3451                 notify_info_data_table[j].fn(snum, current_data, queue,
3452                                              printer, mem_ctx);
3453                 info->count++;
3454         }
3455
3456         return true;
3457 }
3458
3459 /*
3460  * JFM: The enumeration is not that simple, it's even non obvious.
3461  *
3462  * let's take an example: I want to monitor the PRINTER SERVER for
3463  * the printer's name and the number of jobs currently queued.
3464  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3465  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3466  *
3467  * I have 3 printers on the back of my server.
3468  *
3469  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3470  * structures.
3471  *   Number     Data                    Id
3472  *      1       printer 1 name          1
3473  *      2       printer 1 cjob          1
3474  *      3       printer 2 name          2
3475  *      4       printer 2 cjob          2
3476  *      5       printer 3 name          3
3477  *      6       printer 3 name          3
3478  *
3479  * that's the print server case, the printer case is even worse.
3480  */
3481
3482 /*******************************************************************
3483  *
3484  * enumerate all printers on the printserver
3485  * fill a notify_info struct with info asked
3486  *
3487  ********************************************************************/
3488
3489 static WERROR printserver_notify_info(pipes_struct *p,
3490                                       struct policy_handle *hnd,
3491                                       struct spoolss_NotifyInfo *info,
3492                                       TALLOC_CTX *mem_ctx)
3493 {
3494         int snum;
3495         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3496         int n_services=lp_numservices();
3497         int i;
3498         struct spoolss_NotifyOption *option;
3499         struct spoolss_NotifyOptionType option_type;
3500
3501         DEBUG(4,("printserver_notify_info\n"));
3502
3503         if (!Printer)
3504                 return WERR_BADFID;
3505
3506         option = Printer->notify.option;
3507
3508         info->version   = 2;
3509         info->notifies  = NULL;
3510         info->count     = 0;
3511
3512         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3513            sending a ffpcn() request first */
3514
3515         if ( !option )
3516                 return WERR_BADFID;
3517
3518         for (i=0; i<option->count; i++) {
3519                 option_type = option->types[i];
3520
3521                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3522                         continue;
3523
3524                 for (snum=0; snum<n_services; snum++)
3525                 {
3526                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3527                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3528                 }
3529         }
3530
3531 #if 0
3532         /*
3533          * Debugging information, don't delete.
3534          */
3535
3536         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3537         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3538         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3539
3540         for (i=0; i<info->count; i++) {
3541                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3542                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3543                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3544         }
3545 #endif
3546
3547         return WERR_OK;
3548 }
3549
3550 /*******************************************************************
3551  *
3552  * fill a notify_info struct with info asked
3553  *
3554  ********************************************************************/
3555
3556 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3557                                   struct spoolss_NotifyInfo *info,
3558                                   TALLOC_CTX *mem_ctx)
3559 {
3560         int snum;
3561         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3562         int i;
3563         uint32_t id;
3564         struct spoolss_NotifyOption *option;
3565         struct spoolss_NotifyOptionType option_type;
3566         int count,j;
3567         print_queue_struct *queue=NULL;
3568         print_status_struct status;
3569
3570         DEBUG(4,("printer_notify_info\n"));
3571
3572         if (!Printer)
3573                 return WERR_BADFID;
3574
3575         option = Printer->notify.option;
3576         id = 0x0;
3577
3578         info->version   = 2;
3579         info->notifies  = NULL;
3580         info->count     = 0;
3581
3582         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3583            sending a ffpcn() request first */
3584
3585         if ( !option )
3586                 return WERR_BADFID;
3587
3588         get_printer_snum(p, hnd, &snum, NULL);
3589
3590         for (i=0; i<option->count; i++) {
3591                 option_type = option->types[i];
3592
3593                 switch (option_type.type) {
3594                 case PRINTER_NOTIFY_TYPE:
3595                         if(construct_notify_printer_info(Printer, info, snum,
3596                                                          &option_type, id,
3597                                                          mem_ctx))
3598                                 id--;
3599                         break;
3600
3601                 case JOB_NOTIFY_TYPE: {
3602                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3603
3604                         count = print_queue_status(snum, &queue, &status);
3605
3606                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3607                                 goto done;
3608
3609                         for (j=0; j<count; j++) {
3610                                 construct_notify_jobs_info(&queue[j], info,
3611                                                            printer, snum,
3612                                                            &option_type,
3613                                                            queue[j].job,
3614                                                            mem_ctx);
3615                         }
3616
3617                         free_a_printer(&printer, 2);
3618
3619                 done:
3620                         SAFE_FREE(queue);
3621                         break;
3622                 }
3623                 }
3624         }
3625
3626         /*
3627          * Debugging information, don't delete.
3628          */
3629         /*
3630         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3631         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3632         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3633
3634         for (i=0; i<info->count; i++) {
3635                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3636                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3637                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3638         }
3639         */
3640         return WERR_OK;
3641 }
3642
3643 /****************************************************************
3644  _spoolss_RouterRefreshPrinterChangeNotify
3645 ****************************************************************/
3646
3647 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3648                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3649 {
3650         struct spoolss_NotifyInfo *info;
3651
3652         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3653         WERROR result = WERR_BADFID;
3654
3655         /* we always have a spoolss_NotifyInfo struct */
3656         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3657         if (!info) {
3658                 result = WERR_NOMEM;
3659                 goto done;
3660         }
3661
3662         *r->out.info = info;
3663
3664         if (!Printer) {
3665                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3666                         "Invalid handle (%s:%u:%u).\n",
3667                         OUR_HANDLE(r->in.handle)));
3668                 goto done;
3669         }
3670
3671         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3672
3673         /*
3674          *      We are now using the change value, and
3675          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3676          *      I don't have a global notification system, I'm sending back all the
3677          *      informations even when _NOTHING_ has changed.
3678          */
3679
3680         /* We need to keep track of the change value to send back in
3681            RRPCN replies otherwise our updates are ignored. */
3682
3683         Printer->notify.fnpcn = true;
3684
3685         if (Printer->notify.client_connected) {
3686                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3687                         "Saving change value in request [%x]\n",
3688                         r->in.change_low));
3689                 Printer->notify.change = r->in.change_low;
3690         }
3691
3692         /* just ignore the spoolss_NotifyOption */
3693
3694         switch (Printer->printer_type) {
3695                 case SPLHND_SERVER:
3696                         result = printserver_notify_info(p, r->in.handle,
3697                                                          info, p->mem_ctx);
3698                         break;
3699
3700                 case SPLHND_PRINTER:
3701                         result = printer_notify_info(p, r->in.handle,
3702                                                      info, p->mem_ctx);
3703                         break;
3704         }
3705
3706         Printer->notify.fnpcn = false;
3707
3708 done:
3709         return result;
3710 }
3711
3712 /********************************************************************
3713  * construct_printer_info_0
3714  * fill a printer_info_0 struct
3715  ********************************************************************/
3716
3717 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3718                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3719                                       struct spoolss_PrinterInfo0 *r,
3720                                       int snum)
3721 {
3722         int count;
3723         counter_printer_0 *session_counter;
3724         time_t setuptime;
3725         print_status_struct status;
3726
3727         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3728         W_ERROR_HAVE_NO_MEMORY(r->printername);
3729
3730         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3731         W_ERROR_HAVE_NO_MEMORY(r->servername);
3732
3733         count = print_queue_length(snum, &status);
3734
3735         /* check if we already have a counter for this printer */
3736         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3737                 if (session_counter->snum == snum)
3738                         break;
3739         }
3740
3741         /* it's the first time, add it to the list */
3742         if (session_counter == NULL) {
3743                 session_counter = SMB_MALLOC_P(counter_printer_0);
3744                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3745                 ZERO_STRUCTP(session_counter);
3746                 session_counter->snum           = snum;
3747                 session_counter->counter        = 0;
3748                 DLIST_ADD(counter_list, session_counter);
3749         }
3750
3751         /* increment it */
3752         session_counter->counter++;
3753
3754         r->cjobs                        = count;
3755         r->total_jobs                   = 0;
3756         r->total_bytes                  = 0;
3757
3758         setuptime = (time_t)ntprinter->info_2->setuptime;
3759
3760         init_systemtime(&r->time, gmtime(&setuptime));
3761
3762         /* JFM:
3763          * the global_counter should be stored in a TDB as it's common to all the clients
3764          * and should be zeroed on samba startup
3765          */
3766         r->global_counter               = session_counter->counter;
3767         r->total_pages                  = 0;
3768         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3769         r->version                      = 0x0005;       /* NT 5 */
3770         r->free_build                   = 0x0893;       /* build 2195 */
3771         r->spooling                     = 0;
3772         r->max_spooling                 = 0;
3773         r->session_counter              = session_counter->counter;
3774         r->num_error_out_of_paper       = 0x0;
3775         r->num_error_not_ready          = 0x0;          /* number of print failure */
3776         r->job_error                    = 0x0;
3777         r->number_of_processors         = 0x1;
3778         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3779         r->high_part_total_bytes        = 0x0;
3780         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3781         r->last_error                   = WERR_OK;
3782         r->status                       = nt_printq_status(status.status);
3783         r->enumerate_network_printers   = 0x0;
3784         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3785         r->processor_architecture       = 0x0;
3786         r->processor_level              = 0x6;          /* 6  ???*/
3787         r->ref_ic                       = 0;
3788         r->reserved2                    = 0;
3789         r->reserved3                    = 0;
3790
3791         return WERR_OK;
3792 }
3793
3794 /****************************************************************************
3795  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3796  should be valid upon entry
3797 ****************************************************************************/
3798
3799 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3800                                     struct spoolss_DeviceMode *r,
3801                                     const NT_DEVICEMODE *ntdevmode)
3802 {
3803         if (!r || !ntdevmode) {
3804                 return WERR_INVALID_PARAM;
3805         }
3806
3807         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3808         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3809
3810         r->specversion          = ntdevmode->specversion;
3811         r->driverversion        = ntdevmode->driverversion;
3812         r->size                 = ntdevmode->size;
3813         r->__driverextra_length = ntdevmode->driverextra;
3814         r->fields               = ntdevmode->fields;
3815
3816         r->orientation          = ntdevmode->orientation;
3817         r->papersize            = ntdevmode->papersize;
3818         r->paperlength          = ntdevmode->paperlength;
3819         r->paperwidth           = ntdevmode->paperwidth;
3820         r->scale                = ntdevmode->scale;
3821         r->copies               = ntdevmode->copies;
3822         r->defaultsource        = ntdevmode->defaultsource;
3823         r->printquality         = ntdevmode->printquality;
3824         r->color                = ntdevmode->color;
3825         r->duplex               = ntdevmode->duplex;
3826         r->yresolution          = ntdevmode->yresolution;
3827         r->ttoption             = ntdevmode->ttoption;
3828         r->collate              = ntdevmode->collate;
3829
3830         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3831         W_ERROR_HAVE_NO_MEMORY(r->formname);
3832
3833         /* all 0 below are values that have not been set in the old parsing/copy
3834          * function, maybe they should... - gd */
3835
3836         r->logpixels            = 0;
3837         r->bitsperpel           = 0;
3838         r->pelswidth            = 0;
3839         r->pelsheight           = 0;
3840         r->displayflags         = 0;
3841         r->displayfrequency     = 0;
3842         r->icmmethod            = ntdevmode->icmmethod;
3843         r->icmintent            = ntdevmode->icmintent;
3844         r->mediatype            = ntdevmode->mediatype;
3845         r->dithertype           = ntdevmode->dithertype;
3846         r->reserved1            = 0;
3847         r->reserved2            = 0;
3848         r->panningwidth         = 0;
3849         r->panningheight        = 0;
3850
3851         if (ntdevmode->nt_dev_private != NULL) {
3852                 r->driverextra_data = data_blob_talloc(mem_ctx,
3853                         ntdevmode->nt_dev_private,
3854                         ntdevmode->driverextra);
3855                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3856         }
3857
3858         return WERR_OK;
3859 }
3860
3861
3862 /****************************************************************************
3863  Create a spoolss_DeviceMode struct. Returns talloced memory.
3864 ****************************************************************************/
3865
3866 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3867                                               const char *servicename)
3868 {
3869         WERROR result;
3870         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3871         struct spoolss_DeviceMode *devmode = NULL;
3872
3873         DEBUG(7,("construct_dev_mode\n"));
3874
3875         DEBUGADD(8,("getting printer characteristics\n"));
3876
3877         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3878                 return NULL;
3879
3880         if (!printer->info_2->devmode) {
3881                 DEBUG(5, ("BONG! There was no device mode!\n"));
3882                 goto done;
3883         }
3884
3885         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3886         if (!devmode) {
3887                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3888                 goto done;
3889         }
3890
3891         DEBUGADD(8,("loading DEVICEMODE\n"));
3892
3893         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3894         if (!W_ERROR_IS_OK(result)) {
3895                 TALLOC_FREE(devmode);
3896         }
3897
3898 done:
3899         free_a_printer(&printer,2);
3900
3901         return devmode;
3902 }
3903
3904 /********************************************************************
3905  * construct_printer_info3
3906  * fill a spoolss_PrinterInfo3 struct
3907  ********************************************************************/
3908
3909 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3910                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3911                                       struct spoolss_PrinterInfo3 *r,
3912                                       int snum)
3913 {
3914         /* These are the components of the SD we are returning. */
3915
3916         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3917                 /* don't use talloc_steal() here unless you do a deep steal of all
3918                    the SEC_DESC members */
3919
3920                 r->secdesc = dup_sec_desc(mem_ctx,
3921                                           ntprinter->info_2->secdesc_buf->sd);
3922                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3923         }
3924
3925         return WERR_OK;
3926 }
3927
3928 /********************************************************************
3929  * construct_printer_info4
3930  * fill a spoolss_PrinterInfo4 struct
3931  ********************************************************************/
3932
3933 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3934                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3935                                       struct spoolss_PrinterInfo4 *r,
3936                                       int snum)
3937 {
3938         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3939         W_ERROR_HAVE_NO_MEMORY(r->printername);
3940         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3941         W_ERROR_HAVE_NO_MEMORY(r->servername);
3942
3943         r->attributes   = ntprinter->info_2->attributes;
3944
3945         return WERR_OK;
3946 }
3947
3948 /********************************************************************
3949  * construct_printer_info5
3950  * fill a spoolss_PrinterInfo5 struct
3951  ********************************************************************/
3952
3953 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3954                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3955                                       struct spoolss_PrinterInfo5 *r,
3956                                       int snum)
3957 {
3958         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3959         W_ERROR_HAVE_NO_MEMORY(r->printername);
3960         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3961         W_ERROR_HAVE_NO_MEMORY(r->portname);
3962
3963         r->attributes   = ntprinter->info_2->attributes;
3964
3965         /* these two are not used by NT+ according to MSDN */
3966
3967         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3968         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3969
3970         return WERR_OK;
3971 }
3972
3973 /********************************************************************
3974  * construct_printer_info_6
3975  * fill a spoolss_PrinterInfo6 struct
3976  ********************************************************************/
3977
3978 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3979                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3980                                       struct spoolss_PrinterInfo6 *r,
3981                                       int snum)
3982 {
3983         int count;
3984         print_status_struct status;
3985
3986         count = print_queue_length(snum, &status);
3987
3988         r->status = nt_printq_status(status.status);
3989
3990         return WERR_OK;
3991 }
3992
3993 /********************************************************************
3994  * construct_printer_info7
3995  * fill a spoolss_PrinterInfo7 struct
3996  ********************************************************************/
3997
3998 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3999                                       Printer_entry *print_hnd,
4000                                       struct spoolss_PrinterInfo7 *r,
4001                                       int snum)
4002 {
4003         struct GUID guid;
4004
4005         if (is_printer_published(print_hnd, snum, &guid)) {
4006                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4007                 r->action = DSPRINT_PUBLISH;
4008         } else {
4009                 r->guid = talloc_strdup(mem_ctx, "");
4010                 r->action = DSPRINT_UNPUBLISH;
4011         }
4012         W_ERROR_HAVE_NO_MEMORY(r->guid);
4013
4014         return WERR_OK;
4015 }
4016
4017 /********************************************************************
4018  * construct_printer_info8
4019  * fill a spoolss_PrinterInfo8 struct
4020  ********************************************************************/
4021
4022 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4023                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4024                                       struct spoolss_DeviceModeInfo *r,
4025                                       int snum)
4026 {
4027         struct spoolss_DeviceMode *devmode;
4028         WERROR result;
4029
4030         if (!ntprinter->info_2->devmode) {
4031                 r->devmode = NULL;
4032                 return WERR_OK;
4033         }
4034
4035         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4036         W_ERROR_HAVE_NO_MEMORY(devmode);
4037
4038         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4039         if (!W_ERROR_IS_OK(result)) {
4040                 TALLOC_FREE(devmode);
4041                 return result;
4042         }
4043
4044         r->devmode      = devmode;
4045
4046         return WERR_OK;
4047 }
4048
4049
4050 /********************************************************************
4051  * construct_printer_info1
4052  * fill a spoolss_PrinterInfo1 struct
4053 ********************************************************************/
4054
4055 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4056                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4057                                       uint32_t flags,
4058                                       struct spoolss_PrinterInfo1 *r,
4059                                       int snum)
4060 {
4061         r->flags                = flags;
4062
4063         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4064                                                   ntprinter->info_2->printername,
4065                                                   ntprinter->info_2->drivername,
4066                                                   ntprinter->info_2->location);
4067         W_ERROR_HAVE_NO_MEMORY(r->description);
4068
4069         if (*ntprinter->info_2->comment == '\0') {
4070                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4071         } else {
4072                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4073         }
4074         W_ERROR_HAVE_NO_MEMORY(r->comment);
4075
4076         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4077         W_ERROR_HAVE_NO_MEMORY(r->name);
4078
4079         return WERR_OK;
4080 }
4081
4082 /********************************************************************
4083  * construct_printer_info2
4084  * fill a spoolss_PrinterInfo2 struct
4085 ********************************************************************/
4086
4087 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4088                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4089                                       struct spoolss_PrinterInfo2 *r,
4090                                       int snum)
4091 {
4092         int count;
4093
4094         print_status_struct status;
4095
4096         count = print_queue_length(snum, &status);
4097
4098         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4099         W_ERROR_HAVE_NO_MEMORY(r->servername);
4100         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4101         W_ERROR_HAVE_NO_MEMORY(r->printername);
4102         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4103         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4104         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4105         W_ERROR_HAVE_NO_MEMORY(r->portname);
4106         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4107         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4108
4109         if (*ntprinter->info_2->comment == '\0') {
4110                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4111         } else {
4112                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4113         }
4114         W_ERROR_HAVE_NO_MEMORY(r->comment);
4115
4116         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4117         W_ERROR_HAVE_NO_MEMORY(r->location);
4118         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4119         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4120         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4121         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4122         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4123         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4124         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4125         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4126
4127         r->attributes           = ntprinter->info_2->attributes;
4128
4129         r->priority             = ntprinter->info_2->priority;
4130         r->defaultpriority      = ntprinter->info_2->default_priority;
4131         r->starttime            = ntprinter->info_2->starttime;
4132         r->untiltime            = ntprinter->info_2->untiltime;
4133         r->status               = nt_printq_status(status.status);
4134         r->cjobs                = count;
4135         r->averageppm           = ntprinter->info_2->averageppm;
4136
4137         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4138         if (!r->devmode) {
4139                 DEBUG(8,("Returning NULL Devicemode!\n"));
4140         }
4141
4142         r->secdesc              = NULL;
4143
4144         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4145                 /* don't use talloc_steal() here unless you do a deep steal of all
4146                    the SEC_DESC members */
4147
4148                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4149         }
4150
4151         return WERR_OK;
4152 }
4153
4154 /********************************************************************
4155 ********************************************************************/
4156
4157 static bool snum_is_shared_printer(int snum)
4158 {
4159         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4160 }
4161
4162 /********************************************************************
4163  Spoolss_enumprinters.
4164 ********************************************************************/
4165
4166 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4167                                            uint32_t level,
4168                                            uint32_t flags,
4169                                            union spoolss_PrinterInfo **info_p,
4170                                            uint32_t *count_p)
4171 {
4172         int snum;
4173         int n_services = lp_numservices();
4174         union spoolss_PrinterInfo *info = NULL;
4175         uint32_t count = 0;
4176         WERROR result = WERR_OK;
4177
4178         *count_p = 0;
4179         *info_p = NULL;
4180
4181         for (snum = 0; snum < n_services; snum++) {
4182
4183                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4184
4185                 if (!snum_is_shared_printer(snum)) {
4186                         continue;
4187                 }
4188
4189                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4190                         lp_servicename(snum), snum));
4191
4192                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4193                                             union spoolss_PrinterInfo,
4194                                             count + 1);
4195                 if (!info) {
4196                         result = WERR_NOMEM;
4197                         goto out;
4198                 }
4199
4200                 result = get_a_printer(NULL, &ntprinter, 2,
4201                                        lp_const_servicename(snum));
4202                 if (!W_ERROR_IS_OK(result)) {
4203                         goto out;
4204                 }
4205
4206                 switch (level) {
4207                 case 0:
4208                         result = construct_printer_info0(info, ntprinter,
4209                                                          &info[count].info0, snum);
4210                         break;
4211                 case 1:
4212                         result = construct_printer_info1(info, ntprinter, flags,
4213                                                          &info[count].info1, snum);
4214                         break;
4215                 case 2:
4216                         result = construct_printer_info2(info, ntprinter,
4217                                                          &info[count].info2, snum);
4218                         break;
4219                 case 4:
4220                         result = construct_printer_info4(info, ntprinter,
4221                                                          &info[count].info4, snum);
4222                         break;
4223                 case 5:
4224                         result = construct_printer_info5(info, ntprinter,
4225                                                          &info[count].info5, snum);
4226                         break;
4227
4228                 default:
4229                         result = WERR_UNKNOWN_LEVEL;
4230                         free_a_printer(&ntprinter, 2);
4231                         goto out;
4232                 }
4233
4234                 free_a_printer(&ntprinter, 2);
4235                 if (!W_ERROR_IS_OK(result)) {
4236                         goto out;
4237                 }
4238
4239                 count++;
4240         }
4241
4242         *count_p = count;
4243         *info_p = info;
4244
4245  out:
4246         if (!W_ERROR_IS_OK(result)) {
4247                 TALLOC_FREE(info);
4248                 return result;
4249         }
4250
4251         *info_p = info;
4252
4253         return WERR_OK;
4254 }
4255
4256 /********************************************************************
4257  * handle enumeration of printers at level 0
4258  ********************************************************************/
4259
4260 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4261                                   uint32_t flags,
4262                                   const char *servername,
4263                                   union spoolss_PrinterInfo **info,
4264                                   uint32_t *count)
4265 {
4266         DEBUG(4,("enum_all_printers_info_0\n"));
4267
4268         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4269 }
4270
4271
4272 /********************************************************************
4273 ********************************************************************/
4274
4275 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4276                                        uint32_t flags,
4277                                        union spoolss_PrinterInfo **info,
4278                                        uint32_t *count)
4279 {
4280         DEBUG(4,("enum_all_printers_info_1\n"));
4281
4282         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4283 }
4284
4285 /********************************************************************
4286  enum_all_printers_info_1_local.
4287 *********************************************************************/
4288
4289 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4290                                              union spoolss_PrinterInfo **info,
4291                                              uint32_t *count)
4292 {
4293         DEBUG(4,("enum_all_printers_info_1_local\n"));
4294
4295         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4296 }
4297
4298 /********************************************************************
4299  enum_all_printers_info_1_name.
4300 *********************************************************************/
4301
4302 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4303                                             const char *name,
4304                                             union spoolss_PrinterInfo **info,
4305                                             uint32_t *count)
4306 {
4307         const char *s = name;
4308
4309         DEBUG(4,("enum_all_printers_info_1_name\n"));
4310
4311         if ((name[0] == '\\') && (name[1] == '\\')) {
4312                 s = name + 2;
4313         }
4314
4315         if (!is_myname_or_ipaddr(s)) {
4316                 return WERR_INVALID_NAME;
4317         }
4318
4319         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4320 }
4321
4322 /********************************************************************
4323  enum_all_printers_info_1_network.
4324 *********************************************************************/
4325
4326 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4327                                                const char *name,
4328                                                union spoolss_PrinterInfo **info,
4329                                                uint32_t *count)
4330 {
4331         const char *s = name;
4332
4333         DEBUG(4,("enum_all_printers_info_1_network\n"));
4334
4335         /* If we respond to a enum_printers level 1 on our name with flags
4336            set to PRINTER_ENUM_REMOTE with a list of printers then these
4337            printers incorrectly appear in the APW browse list.
4338            Specifically the printers for the server appear at the workgroup
4339            level where all the other servers in the domain are
4340            listed. Windows responds to this call with a
4341            WERR_CAN_NOT_COMPLETE so we should do the same. */
4342
4343         if (name[0] == '\\' && name[1] == '\\') {
4344                  s = name + 2;
4345         }
4346
4347         if (is_myname_or_ipaddr(s)) {
4348                  return WERR_CAN_NOT_COMPLETE;
4349         }
4350
4351         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4352 }
4353
4354 /********************************************************************
4355  * api_spoolss_enumprinters
4356  *
4357  * called from api_spoolss_enumprinters (see this to understand)
4358  ********************************************************************/
4359
4360 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4361                                        union spoolss_PrinterInfo **info,
4362                                        uint32_t *count)
4363 {
4364         DEBUG(4,("enum_all_printers_info_2\n"));
4365
4366         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4367 }
4368
4369 /********************************************************************
4370  * handle enumeration of printers at level 1
4371  ********************************************************************/
4372
4373 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4374                                   uint32_t flags,
4375                                   const char *name,
4376                                   union spoolss_PrinterInfo **info,
4377                                   uint32_t *count)
4378 {
4379         /* Not all the flags are equals */
4380
4381         if (flags & PRINTER_ENUM_LOCAL) {
4382                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4383         }
4384
4385         if (flags & PRINTER_ENUM_NAME) {
4386                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4387         }
4388
4389         if (flags & PRINTER_ENUM_NETWORK) {
4390                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4391         }
4392
4393         return WERR_OK; /* NT4sp5 does that */
4394 }
4395
4396 /********************************************************************
4397  * handle enumeration of printers at level 2
4398  ********************************************************************/
4399
4400 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4401                                   uint32_t flags,
4402                                   const char *servername,
4403                                   union spoolss_PrinterInfo **info,
4404                                   uint32_t *count)
4405 {
4406         if (flags & PRINTER_ENUM_LOCAL) {
4407                 return enum_all_printers_info_2(mem_ctx, info, count);
4408         }
4409
4410         if (flags & PRINTER_ENUM_NAME) {
4411                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4412                         return WERR_INVALID_NAME;
4413                 }
4414
4415                 return enum_all_printers_info_2(mem_ctx, info, count);
4416         }
4417
4418         if (flags & PRINTER_ENUM_REMOTE) {
4419                 return WERR_UNKNOWN_LEVEL;
4420         }
4421
4422         return WERR_OK;
4423 }
4424
4425 /********************************************************************
4426  * handle enumeration of printers at level 4
4427  ********************************************************************/
4428
4429 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4430                                   uint32_t flags,
4431                                   const char *servername,
4432                                   union spoolss_PrinterInfo **info,
4433                                   uint32_t *count)
4434 {
4435         DEBUG(4,("enum_all_printers_info_4\n"));
4436
4437         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4438 }
4439
4440
4441 /********************************************************************
4442  * handle enumeration of printers at level 5
4443  ********************************************************************/
4444
4445 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4446                                   uint32_t flags,
4447                                   const char *servername,
4448                                   union spoolss_PrinterInfo **info,
4449                                   uint32_t *count)
4450 {
4451         DEBUG(4,("enum_all_printers_info_5\n"));
4452
4453         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4454 }
4455
4456 /****************************************************************
4457  _spoolss_EnumPrinters
4458 ****************************************************************/
4459
4460 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4461                              struct spoolss_EnumPrinters *r)
4462 {
4463         const char *name = NULL;
4464         WERROR result;
4465
4466         /* that's an [in out] buffer */
4467
4468         if (!r->in.buffer && (r->in.offered != 0)) {
4469                 return WERR_INVALID_PARAM;
4470         }
4471
4472         DEBUG(4,("_spoolss_EnumPrinters\n"));
4473
4474         *r->out.needed = 0;
4475         *r->out.count = 0;
4476         *r->out.info = NULL;
4477
4478         /*
4479          * Level 1:
4480          *          flags==PRINTER_ENUM_NAME
4481          *           if name=="" then enumerates all printers
4482          *           if name!="" then enumerate the printer
4483          *          flags==PRINTER_ENUM_REMOTE
4484          *          name is NULL, enumerate printers
4485          * Level 2: name!="" enumerates printers, name can't be NULL
4486          * Level 3: doesn't exist
4487          * Level 4: does a local registry lookup
4488          * Level 5: same as Level 2
4489          */
4490
4491         if (name) {
4492                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4493                 W_ERROR_HAVE_NO_MEMORY(name);
4494         }
4495
4496         switch (r->in.level) {
4497         case 0:
4498                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4499                                              r->out.info, r->out.count);
4500                 break;
4501         case 1:
4502                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4503                                              r->out.info, r->out.count);
4504                 break;
4505         case 2:
4506                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4507                                              r->out.info, r->out.count);
4508                 break;
4509         case 4:
4510                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4511                                              r->out.info, r->out.count);
4512                 break;
4513         case 5:
4514                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4515                                              r->out.info, r->out.count);
4516                 break;
4517         default:
4518                 return WERR_UNKNOWN_LEVEL;
4519         }
4520
4521         if (!W_ERROR_IS_OK(result)) {
4522                 return result;
4523         }
4524
4525         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4526                                                      spoolss_EnumPrinters, NULL,
4527                                                      *r->out.info, r->in.level,
4528                                                      *r->out.count);
4529         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4530         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4531
4532         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4533 }
4534
4535 /****************************************************************
4536  _spoolss_GetPrinter
4537 ****************************************************************/
4538
4539 WERROR _spoolss_GetPrinter(pipes_struct *p,
4540                            struct spoolss_GetPrinter *r)
4541 {
4542         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4543         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4544         WERROR result = WERR_OK;
4545
4546         int snum;
4547
4548         /* that's an [in out] buffer */
4549
4550         if (!r->in.buffer && (r->in.offered != 0)) {
4551                 return WERR_INVALID_PARAM;
4552         }
4553
4554         *r->out.needed = 0;
4555
4556         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4557                 return WERR_BADFID;
4558         }
4559
4560         result = get_a_printer(Printer, &ntprinter, 2,
4561                                lp_const_servicename(snum));
4562         if (!W_ERROR_IS_OK(result)) {
4563                 return result;
4564         }
4565
4566         switch (r->in.level) {
4567         case 0:
4568                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4569                                                  &r->out.info->info0, snum);
4570                 break;
4571         case 1:
4572                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4573                                                  PRINTER_ENUM_ICON8,
4574                                                  &r->out.info->info1, snum);
4575                 break;
4576         case 2:
4577                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4578                                                  &r->out.info->info2, snum);
4579                 break;
4580         case 3:
4581                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4582                                                  &r->out.info->info3, snum);
4583                 break;
4584         case 4:
4585                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4586                                                  &r->out.info->info4, snum);
4587                 break;
4588         case 5:
4589                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4590                                                  &r->out.info->info5, snum);
4591                 break;
4592         case 6:
4593                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4594                                                  &r->out.info->info6, snum);
4595                 break;
4596         case 7:
4597                 result = construct_printer_info7(p->mem_ctx, Printer,
4598                                                  &r->out.info->info7, snum);
4599                 break;
4600         case 8:
4601                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4602                                                  &r->out.info->info8, snum);
4603                 break;
4604         default:
4605                 result = WERR_UNKNOWN_LEVEL;
4606                 break;
4607         }
4608
4609         free_a_printer(&ntprinter, 2);
4610
4611         if (!W_ERROR_IS_OK(result)) {
4612                 TALLOC_FREE(r->out.info);
4613                 return result;
4614         }
4615
4616         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4617                                                r->out.info, r->in.level);
4618         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4619
4620         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4621 }
4622
4623 /********************************************************************
4624  ********************************************************************/
4625
4626 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4627                                                   fstring *fstring_array,
4628                                                   const char *cservername)
4629 {
4630         int i, num_strings = 0;
4631         const char **array = NULL;
4632
4633         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4634
4635                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4636                                                   cservername, fstring_array[i]);
4637                 if (!str) {
4638                         TALLOC_FREE(array);
4639                         return NULL;
4640                 }
4641
4642
4643                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4644                         TALLOC_FREE(array);
4645                         return NULL;
4646                 }
4647         }
4648
4649         if (i > 0) {
4650                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4651                              &array, &num_strings);
4652         }
4653
4654         return array;
4655 }
4656
4657 /********************************************************************
4658  * fill a spoolss_DriverInfo1 struct
4659  ********************************************************************/
4660
4661 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4662                                         struct spoolss_DriverInfo1 *r,
4663                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4664                                         const char *servername,
4665                                         const char *architecture)
4666 {
4667         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4668         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4669
4670         return WERR_OK;
4671 }
4672
4673 /********************************************************************
4674  * fill a spoolss_DriverInfo2 struct
4675  ********************************************************************/
4676
4677 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4678                                         struct spoolss_DriverInfo2 *r,
4679                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4680                                         const char *servername)
4681
4682 {
4683         const char *cservername = canon_servername(servername);
4684
4685         r->version              = driver->info_3->cversion;
4686
4687         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4688         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4689         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4690         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4691
4692         if (strlen(driver->info_3->driverpath)) {
4693                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4694                                 cservername, driver->info_3->driverpath);
4695         } else {
4696                 r->driver_path  = talloc_strdup(mem_ctx, "");
4697         }
4698         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4699
4700         if (strlen(driver->info_3->datafile)) {
4701                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4702                                 cservername, driver->info_3->datafile);
4703         } else {
4704                 r->data_file    = talloc_strdup(mem_ctx, "");
4705         }
4706         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4707
4708         if (strlen(driver->info_3->configfile)) {
4709                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4710                                 cservername, driver->info_3->configfile);
4711         } else {
4712                 r->config_file  = talloc_strdup(mem_ctx, "");
4713         }
4714         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4715
4716         return WERR_OK;
4717 }
4718
4719 /********************************************************************
4720  * fill a spoolss_DriverInfo3 struct
4721  ********************************************************************/
4722
4723 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4724                                         struct spoolss_DriverInfo3 *r,
4725                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4726                                         const char *servername)
4727 {
4728         const char *cservername = canon_servername(servername);
4729
4730         r->version              = driver->info_3->cversion;
4731
4732         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4733         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4734         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4735         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4736
4737         if (strlen(driver->info_3->driverpath)) {
4738                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4739                                 cservername, driver->info_3->driverpath);
4740         } else {
4741                 r->driver_path  = talloc_strdup(mem_ctx, "");
4742         }
4743         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4744
4745         if (strlen(driver->info_3->datafile)) {
4746                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4747                                 cservername, driver->info_3->datafile);
4748         } else {
4749                 r->data_file    = talloc_strdup(mem_ctx, "");
4750         }
4751         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4752
4753         if (strlen(driver->info_3->configfile)) {
4754                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4755                                 cservername, driver->info_3->configfile);
4756         } else {
4757                 r->config_file  = talloc_strdup(mem_ctx, "");
4758         }
4759         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4760
4761         if (strlen(driver->info_3->helpfile)) {
4762                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4763                                 cservername, driver->info_3->helpfile);
4764         } else {
4765                 r->help_file    = talloc_strdup(mem_ctx, "");
4766         }
4767         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4768
4769         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4770         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4771         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4772         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4773
4774         r->dependent_files = string_array_from_driver_info(mem_ctx,
4775                                                            driver->info_3->dependentfiles,
4776                                                            cservername);
4777         return WERR_OK;
4778 }
4779
4780 /********************************************************************
4781  * fill a spoolss_DriverInfo4 struct
4782  ********************************************************************/
4783
4784 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4785                                         struct spoolss_DriverInfo4 *r,
4786                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4787                                         const char *servername)
4788 {
4789         const char *cservername = canon_servername(servername);
4790
4791         r->version              = driver->info_3->cversion;
4792
4793         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4794         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4795         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4796         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4797
4798         if (strlen(driver->info_3->driverpath)) {
4799                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4800                                 cservername, driver->info_3->driverpath);
4801         } else {
4802                 r->driver_path  = talloc_strdup(mem_ctx, "");
4803         }
4804         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4805
4806         if (strlen(driver->info_3->datafile)) {
4807                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4808                                 cservername, driver->info_3->datafile);
4809         } else {
4810                 r->data_file    = talloc_strdup(mem_ctx, "");
4811         }
4812         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4813
4814         if (strlen(driver->info_3->configfile)) {
4815                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4816                                 cservername, driver->info_3->configfile);
4817         } else {
4818                 r->config_file  = talloc_strdup(mem_ctx, "");
4819         }
4820         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4821
4822         if (strlen(driver->info_3->helpfile)) {
4823                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4824                                 cservername, driver->info_3->helpfile);
4825         } else {
4826                 r->help_file    = talloc_strdup(mem_ctx, "");
4827         }
4828         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4829
4830         r->dependent_files = string_array_from_driver_info(mem_ctx,
4831                                                            driver->info_3->dependentfiles,
4832                                                            cservername);
4833
4834
4835         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4836         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4837         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4838         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4839
4840         r->previous_names = string_array_from_driver_info(mem_ctx,
4841                                                           NULL,
4842                                                           cservername);
4843
4844         return WERR_OK;
4845 }
4846
4847 /********************************************************************
4848  * fill a spoolss_DriverInfo5 struct
4849  ********************************************************************/
4850
4851 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4852                                         struct spoolss_DriverInfo5 *r,
4853                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4854                                         const char *servername)
4855 {
4856         const char *cservername = canon_servername(servername);
4857
4858         r->version              = driver->info_3->cversion;
4859
4860         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4861         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4862         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4863         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4864
4865         if (strlen(driver->info_3->driverpath)) {
4866                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4867                                 cservername, driver->info_3->driverpath);
4868         } else {
4869                 r->driver_path  = talloc_strdup(mem_ctx, "");
4870         }
4871         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4872
4873         if (strlen(driver->info_3->datafile)) {
4874                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4875                                 cservername, driver->info_3->datafile);
4876         } else {
4877                 r->data_file    = talloc_strdup(mem_ctx, "");
4878         }
4879         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4880
4881         if (strlen(driver->info_3->configfile)) {
4882                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4883                                 cservername, driver->info_3->configfile);
4884         } else {
4885                 r->config_file  = talloc_strdup(mem_ctx, "");
4886         }
4887         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4888
4889         r->driver_attributes    = 0;
4890         r->config_version       = 0;
4891         r->driver_version       = 0;
4892
4893         return WERR_OK;
4894 }
4895 /********************************************************************
4896  * fill a spoolss_DriverInfo6 struct
4897  ********************************************************************/
4898
4899 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4900                                         struct spoolss_DriverInfo6 *r,
4901                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4902                                         const char *servername)
4903 {
4904         const char *cservername = canon_servername(servername);
4905
4906         r->version              = driver->info_3->cversion;
4907
4908         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4909         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4910         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4911         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4912
4913         if (strlen(driver->info_3->driverpath)) {
4914                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4915                                 cservername, driver->info_3->driverpath);
4916         } else {
4917                 r->driver_path  = talloc_strdup(mem_ctx, "");
4918         }
4919         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4920
4921         if (strlen(driver->info_3->datafile)) {
4922                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4923                                 cservername, driver->info_3->datafile);
4924         } else {
4925                 r->data_file    = talloc_strdup(mem_ctx, "");
4926         }
4927         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4928
4929         if (strlen(driver->info_3->configfile)) {
4930                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4931                                 cservername, driver->info_3->configfile);
4932         } else {
4933                 r->config_file  = talloc_strdup(mem_ctx, "");
4934         }
4935         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4936
4937         if (strlen(driver->info_3->helpfile)) {
4938                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4939                                 cservername, driver->info_3->helpfile);
4940         } else {
4941                 r->help_file    = talloc_strdup(mem_ctx, "");
4942         }
4943         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4944
4945         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4946         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4947         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4948         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4949
4950         r->dependent_files = string_array_from_driver_info(mem_ctx,
4951                                                            driver->info_3->dependentfiles,
4952                                                            cservername);
4953         r->previous_names = string_array_from_driver_info(mem_ctx,
4954                                                           NULL,
4955                                                           cservername);
4956
4957         r->driver_date          = 0;
4958         r->driver_version       = 0;
4959
4960         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
4961         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
4962         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
4963         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
4964         r->hardware_id          = talloc_strdup(mem_ctx, "");
4965         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
4966         r->provider             = talloc_strdup(mem_ctx, "");
4967         W_ERROR_HAVE_NO_MEMORY(r->provider);
4968
4969         return WERR_OK;
4970 }
4971
4972 /********************************************************************
4973  ********************************************************************/
4974 #if 0 /* disabled until marshalling issues are resolved - gd */
4975 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4976                                           struct spoolss_DriverFileInfo *r,
4977                                           const char *cservername,
4978                                           const char *file_name,
4979                                           enum spoolss_DriverFileType file_type,
4980                                           uint32_t file_version)
4981 {
4982         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4983                                           cservername, file_name);
4984         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4985         r->file_type    = file_type;
4986         r->file_version = file_version;
4987
4988         return WERR_OK;
4989 }
4990
4991 /********************************************************************
4992  ********************************************************************/
4993
4994 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4995                                                  const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4996                                                  const char *cservername,
4997                                                  struct spoolss_DriverFileInfo **info_p,
4998                                                  uint32_t *count_p)
4999 {
5000         struct spoolss_DriverFileInfo *info = NULL;
5001         uint32_t count = 0;
5002         WERROR result;
5003         uint32_t i;
5004
5005         *info_p = NULL;
5006         *count_p = 0;
5007
5008         if (strlen(driver->info_3->driverpath)) {
5009                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5010                                             struct spoolss_DriverFileInfo,
5011                                             count + 1);
5012                 W_ERROR_HAVE_NO_MEMORY(info);
5013                 result = fill_spoolss_DriverFileInfo(info,
5014                                                      &info[count],
5015                                                      cservername,
5016                                                      driver->info_3->driverpath,
5017                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5018                                                      0);
5019                 W_ERROR_NOT_OK_RETURN(result);
5020                 count++;
5021         }
5022
5023         if (strlen(driver->info_3->configfile)) {
5024                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5025                                             struct spoolss_DriverFileInfo,
5026                                             count + 1);
5027                 W_ERROR_HAVE_NO_MEMORY(info);
5028                 result = fill_spoolss_DriverFileInfo(info,
5029                                                      &info[count],
5030                                                      cservername,
5031                                                      driver->info_3->configfile,
5032                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5033                                                      0);
5034                 W_ERROR_NOT_OK_RETURN(result);
5035                 count++;
5036         }
5037
5038         if (strlen(driver->info_3->datafile)) {
5039                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5040                                             struct spoolss_DriverFileInfo,
5041                                             count + 1);
5042                 W_ERROR_HAVE_NO_MEMORY(info);
5043                 result = fill_spoolss_DriverFileInfo(info,
5044                                                      &info[count],
5045                                                      cservername,
5046                                                      driver->info_3->datafile,
5047                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5048                                                      0);
5049                 W_ERROR_NOT_OK_RETURN(result);
5050                 count++;
5051         }
5052
5053         if (strlen(driver->info_3->helpfile)) {
5054                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5055                                             struct spoolss_DriverFileInfo,
5056                                             count + 1);
5057                 W_ERROR_HAVE_NO_MEMORY(info);
5058                 result = fill_spoolss_DriverFileInfo(info,
5059                                                      &info[count],
5060                                                      cservername,
5061                                                      driver->info_3->helpfile,
5062                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5063                                                      0);
5064                 W_ERROR_NOT_OK_RETURN(result);
5065                 count++;
5066         }
5067
5068         for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5069                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5070                                             struct spoolss_DriverFileInfo,
5071                                             count + 1);
5072                 W_ERROR_HAVE_NO_MEMORY(info);
5073                 result = fill_spoolss_DriverFileInfo(info,
5074                                                      &info[count],
5075                                                      cservername,
5076                                                      driver->info_3->dependentfiles[i],
5077                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5078                                                      0);
5079                 W_ERROR_NOT_OK_RETURN(result);
5080                 count++;
5081         }
5082
5083         *info_p = info;
5084         *count_p = count;
5085
5086         return WERR_OK;
5087 }
5088
5089 /********************************************************************
5090  * fill a spoolss_DriverInfo101 struct
5091  ********************************************************************/
5092
5093 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5094                                           struct spoolss_DriverInfo101 *r,
5095                                           const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5096                                           const char *servername)
5097 {
5098         const char *cservername = canon_servername(servername);
5099         WERROR result;
5100
5101         r->version              = driver->info_3->cversion;
5102
5103         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5104         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5105         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5106         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5107
5108         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5109                                                     cservername,
5110                                                     &r->file_info,
5111                                                     &r->file_count);
5112         if (!W_ERROR_IS_OK(result)) {
5113                 return result;
5114         }
5115
5116         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5117         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5118
5119         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5120         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5121
5122         r->previous_names = string_array_from_driver_info(mem_ctx,
5123                                                           NULL,
5124                                                           cservername);
5125         r->driver_date          = 0;
5126         r->driver_version       = 0;
5127
5128         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5129         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5130         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5131         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5132         r->hardware_id          = talloc_strdup(mem_ctx, "");
5133         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5134         r->provider             = talloc_strdup(mem_ctx, "");
5135         W_ERROR_HAVE_NO_MEMORY(r->provider);
5136
5137         return WERR_OK;
5138 }
5139 #endif
5140 /********************************************************************
5141  * construct_printer_driver_info_1
5142  ********************************************************************/
5143
5144 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5145                                               struct spoolss_DriverInfo1 *r,
5146                                               int snum,
5147                                               const char *servername,
5148                                               const char *architecture,
5149                                               uint32_t version)
5150 {
5151         NT_PRINTER_INFO_LEVEL *printer = NULL;
5152         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5153         WERROR result;
5154
5155         ZERO_STRUCT(driver);
5156
5157         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5158                 return WERR_INVALID_PRINTER_NAME;
5159
5160         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5161                 free_a_printer(&printer, 2);
5162                 return WERR_UNKNOWN_PRINTER_DRIVER;
5163         }
5164
5165         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5166
5167         free_a_printer(&printer,2);
5168
5169         return result;
5170 }
5171
5172 /********************************************************************
5173  * construct_printer_driver_info_2
5174  * fill a printer_info_2 struct
5175  ********************************************************************/
5176
5177 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5178                                               struct spoolss_DriverInfo2 *r,
5179                                               int snum,
5180                                               const char *servername,
5181                                               const char *architecture,
5182                                               uint32_t version)
5183 {
5184         NT_PRINTER_INFO_LEVEL *printer = NULL;
5185         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5186         WERROR result;
5187
5188         ZERO_STRUCT(printer);
5189         ZERO_STRUCT(driver);
5190
5191         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5192                 return WERR_INVALID_PRINTER_NAME;
5193
5194         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5195                 free_a_printer(&printer, 2);
5196                 return WERR_UNKNOWN_PRINTER_DRIVER;
5197         }
5198
5199         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5200
5201         free_a_printer(&printer,2);
5202
5203         return result;
5204 }
5205
5206 /********************************************************************
5207  * construct_printer_info_3
5208  * fill a printer_info_3 struct
5209  ********************************************************************/
5210
5211 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5212                                               struct spoolss_DriverInfo3 *r,
5213                                               int snum,
5214                                               const char *servername,
5215                                               const char *architecture,
5216                                               uint32_t version)
5217 {
5218         NT_PRINTER_INFO_LEVEL *printer = NULL;
5219         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5220         WERROR status;
5221         ZERO_STRUCT(driver);
5222
5223         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5224         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5225         if (!W_ERROR_IS_OK(status))
5226                 return WERR_INVALID_PRINTER_NAME;
5227
5228         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5229         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5230
5231 #if 0   /* JERRY */
5232
5233         /*
5234          * I put this code in during testing.  Helpful when commenting out the
5235          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5236          * as win2k always queries the driver using an infor level of 6.
5237          * I've left it in (but ifdef'd out) because I'll probably
5238          * use it in experimentation again in the future.   --jerry 22/01/2002
5239          */
5240
5241         if (!W_ERROR_IS_OK(status)) {
5242                 /*
5243                  * Is this a W2k client ?
5244                  */
5245                 if (version == 3) {
5246                         /* Yes - try again with a WinNT driver. */
5247                         version = 2;
5248                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5249                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5250                 }
5251 #endif
5252
5253                 if (!W_ERROR_IS_OK(status)) {
5254                         free_a_printer(&printer,2);
5255                         return WERR_UNKNOWN_PRINTER_DRIVER;
5256                 }
5257
5258 #if 0   /* JERRY */
5259         }
5260 #endif
5261
5262
5263         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5264
5265         free_a_printer(&printer,2);
5266
5267         return status;
5268 }
5269
5270 /********************************************************************
5271  * construct_printer_info_6
5272  * fill a printer_info_6 struct
5273  ********************************************************************/
5274
5275 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5276                                               struct spoolss_DriverInfo6 *r,
5277                                               int snum,
5278                                               const char *servername,
5279                                               const char *architecture,
5280                                               uint32_t version)
5281 {
5282         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5283         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5284         WERROR                          status;
5285
5286         ZERO_STRUCT(driver);
5287
5288         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5289
5290         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5291
5292         if (!W_ERROR_IS_OK(status))
5293                 return WERR_INVALID_PRINTER_NAME;
5294
5295         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5296
5297         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5298
5299         if (!W_ERROR_IS_OK(status))
5300         {
5301                 /*
5302                  * Is this a W2k client ?
5303                  */
5304
5305                 if (version < 3) {
5306                         free_a_printer(&printer,2);
5307                         return WERR_UNKNOWN_PRINTER_DRIVER;
5308                 }
5309
5310                 /* Yes - try again with a WinNT driver. */
5311                 version = 2;
5312                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5313                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5314                 if (!W_ERROR_IS_OK(status)) {
5315                         free_a_printer(&printer,2);
5316                         return WERR_UNKNOWN_PRINTER_DRIVER;
5317                 }
5318         }
5319
5320         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5321
5322         free_a_printer(&printer,2);
5323         free_a_printer_driver(driver, 3);
5324
5325         return status;
5326 }
5327 #if 0 /* disabled until marshalling issues are resolved - gd */
5328 /********************************************************************
5329  * construct_printer_info_101
5330  * fill a printer_info_101 struct
5331  ********************************************************************/
5332
5333 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5334                                                 struct spoolss_DriverInfo101 *r,
5335                                                 int snum,
5336                                                 const char *servername,
5337                                                 const char *architecture,
5338                                                 uint32_t version)
5339 {
5340         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5341         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5342         WERROR                          result;
5343
5344         ZERO_STRUCT(driver);
5345
5346         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5347
5348         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5349                 win_errstr(result)));
5350
5351         if (!W_ERROR_IS_OK(result)) {
5352                 return WERR_INVALID_PRINTER_NAME;
5353         }
5354
5355         result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5356                                       architecture, version);
5357
5358         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5359                 win_errstr(result)));
5360
5361         if (!W_ERROR_IS_OK(result)) {
5362                 /*
5363                  * Is this a W2k client ?
5364                  */
5365
5366                 if (version < 3) {
5367                         free_a_printer(&printer, 2);
5368                         return WERR_UNKNOWN_PRINTER_DRIVER;
5369                 }
5370
5371                 /* Yes - try again with a WinNT driver. */
5372                 version = 2;
5373                 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5374                                               architecture, version);
5375                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5376                         win_errstr(result)));
5377                 if (!W_ERROR_IS_OK(result)) {
5378                         free_a_printer(&printer, 2);
5379                         return WERR_UNKNOWN_PRINTER_DRIVER;
5380                 }
5381         }
5382
5383         result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5384
5385         free_a_printer(&printer, 2);
5386         free_a_printer_driver(driver, 3);
5387
5388         return result;
5389 }
5390 #endif
5391 /****************************************************************
5392  _spoolss_GetPrinterDriver2
5393 ****************************************************************/
5394
5395 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5396                                   struct spoolss_GetPrinterDriver2 *r)
5397 {
5398         Printer_entry *printer;
5399         WERROR result;
5400
5401         const char *servername;
5402         int snum;
5403
5404         /* that's an [in out] buffer */
5405
5406         if (!r->in.buffer && (r->in.offered != 0)) {
5407                 return WERR_INVALID_PARAM;
5408         }
5409
5410         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5411
5412         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5413                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5414                 return WERR_INVALID_PRINTER_NAME;
5415         }
5416
5417         *r->out.needed = 0;
5418         *r->out.server_major_version = 0;
5419         *r->out.server_minor_version = 0;
5420
5421         servername = get_server_name(printer);
5422
5423         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5424                 return WERR_BADFID;
5425         }
5426
5427         switch (r->in.level) {
5428         case 1:
5429                 result = construct_printer_driver_info_1(p->mem_ctx,
5430                                                          &r->out.info->info1,
5431                                                          snum,
5432                                                          servername,
5433                                                          r->in.architecture,
5434                                                          r->in.client_major_version);
5435                 break;
5436         case 2:
5437                 result = construct_printer_driver_info_2(p->mem_ctx,
5438                                                          &r->out.info->info2,
5439                                                          snum,
5440                                                          servername,
5441                                                          r->in.architecture,
5442                                                          r->in.client_major_version);
5443                 break;
5444         case 3:
5445                 result = construct_printer_driver_info_3(p->mem_ctx,
5446                                                          &r->out.info->info3,
5447                                                          snum,
5448                                                          servername,
5449                                                          r->in.architecture,
5450                                                          r->in.client_major_version);
5451                 break;
5452         case 6:
5453                 result = construct_printer_driver_info_6(p->mem_ctx,
5454                                                          &r->out.info->info6,
5455                                                          snum,
5456                                                          servername,
5457                                                          r->in.architecture,
5458                                                          r->in.client_major_version);
5459                 break;
5460 #if 0 /* disabled until marshalling issues are resolved - gd */
5461         case 101:
5462                 result = construct_printer_driver_info_101(p->mem_ctx,
5463                                                            &r->out.info->info101,
5464                                                            snum,
5465                                                            servername,
5466                                                            r->in.architecture,
5467                                                            r->in.client_major_version);
5468                 break;
5469 #endif
5470         default:
5471                 result = WERR_UNKNOWN_LEVEL;
5472                 break;
5473         }
5474
5475         if (!W_ERROR_IS_OK(result)) {
5476                 TALLOC_FREE(r->out.info);
5477                 return result;
5478         }
5479
5480         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5481                                                r->out.info, r->in.level);
5482         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5483
5484         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5485 }
5486
5487
5488 /****************************************************************
5489  _spoolss_StartPagePrinter
5490 ****************************************************************/
5491
5492 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5493                                  struct spoolss_StartPagePrinter *r)
5494 {
5495         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5496
5497         if (!Printer) {
5498                 DEBUG(3,("_spoolss_StartPagePrinter: "
5499                         "Error in startpageprinter printer handle\n"));
5500                 return WERR_BADFID;
5501         }
5502
5503         Printer->page_started = true;
5504         return WERR_OK;
5505 }
5506
5507 /****************************************************************
5508  _spoolss_EndPagePrinter
5509 ****************************************************************/
5510
5511 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5512                                struct spoolss_EndPagePrinter *r)
5513 {
5514         int snum;
5515
5516         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5517
5518         if (!Printer) {
5519                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5520                         OUR_HANDLE(r->in.handle)));
5521                 return WERR_BADFID;
5522         }
5523
5524         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5525                 return WERR_BADFID;
5526
5527         Printer->page_started = false;
5528         print_job_endpage(snum, Printer->jobid);
5529
5530         return WERR_OK;
5531 }
5532
5533 /****************************************************************
5534  _spoolss_StartDocPrinter
5535 ****************************************************************/
5536
5537 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5538                                 struct spoolss_StartDocPrinter *r)
5539 {
5540         struct spoolss_DocumentInfo1 *info_1;
5541         int snum;
5542         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5543
5544         if (!Printer) {
5545                 DEBUG(2,("_spoolss_StartDocPrinter: "
5546                         "Invalid handle (%s:%u:%u)\n",
5547                         OUR_HANDLE(r->in.handle)));
5548                 return WERR_BADFID;
5549         }
5550
5551         if (r->in.level != 1) {
5552                 return WERR_UNKNOWN_LEVEL;
5553         }
5554
5555         info_1 = r->in.info.info1;
5556
5557         /*
5558          * a nice thing with NT is it doesn't listen to what you tell it.
5559          * when asked to send _only_ RAW datas, it tries to send datas
5560          * in EMF format.
5561          *
5562          * So I add checks like in NT Server ...
5563          */
5564
5565         if (info_1->datatype) {
5566                 if (strcmp(info_1->datatype, "RAW") != 0) {
5567                         *r->out.job_id = 0;
5568                         return WERR_INVALID_DATATYPE;
5569                 }
5570         }
5571
5572         /* get the share number of the printer */
5573         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5574                 return WERR_BADFID;
5575         }
5576
5577         Printer->jobid = print_job_start(p->server_info, snum,
5578                                          info_1->document_name,
5579                                          Printer->nt_devmode);
5580
5581         /* An error occured in print_job_start() so return an appropriate
5582            NT error code. */
5583
5584         if (Printer->jobid == -1) {
5585                 return map_werror_from_unix(errno);
5586         }
5587
5588         Printer->document_started = true;
5589         *r->out.job_id = Printer->jobid;
5590
5591         return WERR_OK;
5592 }
5593
5594 /****************************************************************
5595  _spoolss_EndDocPrinter
5596 ****************************************************************/
5597
5598 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5599                               struct spoolss_EndDocPrinter *r)
5600 {
5601         return _spoolss_enddocprinter_internal(p, r->in.handle);
5602 }
5603
5604 /****************************************************************
5605  _spoolss_WritePrinter
5606 ****************************************************************/
5607
5608 WERROR _spoolss_WritePrinter(pipes_struct *p,
5609                              struct spoolss_WritePrinter *r)
5610 {
5611         uint32_t buffer_written;
5612         int snum;
5613         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5614
5615         if (!Printer) {
5616                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5617                         OUR_HANDLE(r->in.handle)));
5618                 *r->out.num_written = r->in._data_size;
5619                 return WERR_BADFID;
5620         }
5621
5622         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5623                 return WERR_BADFID;
5624
5625         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5626                                                    (const char *)r->in.data.data,
5627                                                    (SMB_OFF_T)-1,
5628                                                    (size_t)r->in._data_size);
5629         if (buffer_written == (uint32_t)-1) {
5630                 *r->out.num_written = 0;
5631                 if (errno == ENOSPC)
5632                         return WERR_NO_SPOOL_SPACE;
5633                 else
5634                         return WERR_ACCESS_DENIED;
5635         }
5636
5637         *r->out.num_written = r->in._data_size;
5638
5639         return WERR_OK;
5640 }
5641
5642 /********************************************************************
5643  * api_spoolss_getprinter
5644  * called from the spoolss dispatcher
5645  *
5646  ********************************************************************/
5647
5648 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5649                               pipes_struct *p)
5650 {
5651         int snum;
5652         WERROR errcode = WERR_BADFUNC;
5653         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5654
5655         if (!Printer) {
5656                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5657                         OUR_HANDLE(handle)));
5658                 return WERR_BADFID;
5659         }
5660
5661         if (!get_printer_snum(p, handle, &snum, NULL))
5662                 return WERR_BADFID;
5663
5664         switch (command) {
5665         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5666                 errcode = print_queue_pause(p->server_info, snum);
5667                 break;
5668         case SPOOLSS_PRINTER_CONTROL_RESUME:
5669         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5670                 errcode = print_queue_resume(p->server_info, snum);
5671                 break;
5672         case SPOOLSS_PRINTER_CONTROL_PURGE:
5673                 errcode = print_queue_purge(p->server_info, snum);
5674                 break;
5675         default:
5676                 return WERR_UNKNOWN_LEVEL;
5677         }
5678
5679         return errcode;
5680 }
5681
5682
5683 /****************************************************************
5684  _spoolss_AbortPrinter
5685  * From MSDN: "Deletes printer's spool file if printer is configured
5686  * for spooling"
5687 ****************************************************************/
5688
5689 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5690                              struct spoolss_AbortPrinter *r)
5691 {
5692         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5693         int             snum;
5694         WERROR          errcode = WERR_OK;
5695
5696         if (!Printer) {
5697                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5698                         OUR_HANDLE(r->in.handle)));
5699                 return WERR_BADFID;
5700         }
5701
5702         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5703                 return WERR_BADFID;
5704
5705         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5706
5707         return errcode;
5708 }
5709
5710 /********************************************************************
5711  * called by spoolss_api_setprinter
5712  * when updating a printer description
5713  ********************************************************************/
5714
5715 static WERROR update_printer_sec(struct policy_handle *handle,
5716                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5717 {
5718         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5719         WERROR result;
5720         int snum;
5721
5722         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5723
5724         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5725                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5726                          OUR_HANDLE(handle)));
5727
5728                 result = WERR_BADFID;
5729                 goto done;
5730         }
5731
5732         if (!secdesc_ctr) {
5733                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5734                 result = WERR_INVALID_PARAM;
5735                 goto done;
5736         }
5737
5738         /* Check the user has permissions to change the security
5739            descriptor.  By experimentation with two NT machines, the user
5740            requires Full Access to the printer to change security
5741            information. */
5742
5743         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5744                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5745                 result = WERR_ACCESS_DENIED;
5746                 goto done;
5747         }
5748
5749         /* NT seems to like setting the security descriptor even though
5750            nothing may have actually changed. */
5751
5752         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5753                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5754                 result = WERR_BADFID;
5755                 goto done;
5756         }
5757
5758         if (DEBUGLEVEL >= 10) {
5759                 SEC_ACL *the_acl;
5760                 int i;
5761
5762                 the_acl = old_secdesc_ctr->sd->dacl;
5763                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5764                            PRINTERNAME(snum), the_acl->num_aces));
5765
5766                 for (i = 0; i < the_acl->num_aces; i++) {
5767                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5768                                            &the_acl->aces[i].trustee),
5769                                   the_acl->aces[i].access_mask));
5770                 }
5771
5772                 the_acl = secdesc_ctr->sd->dacl;
5773
5774                 if (the_acl) {
5775                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5776                                    PRINTERNAME(snum), the_acl->num_aces));
5777
5778                         for (i = 0; i < the_acl->num_aces; i++) {
5779                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5780                                                    &the_acl->aces[i].trustee),
5781                                            the_acl->aces[i].access_mask));
5782                         }
5783                 } else {
5784                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5785                 }
5786         }
5787
5788         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5789         if (!new_secdesc_ctr) {
5790                 result = WERR_NOMEM;
5791                 goto done;
5792         }
5793
5794         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5795                 result = WERR_OK;
5796                 goto done;
5797         }
5798
5799         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5800
5801  done:
5802
5803         return result;
5804 }
5805
5806 /********************************************************************
5807  Canonicalize printer info from a client
5808
5809  ATTN: It does not matter what we set the servername to hear
5810  since we do the necessary work in get_a_printer() to set it to
5811  the correct value based on what the client sent in the
5812  _spoolss_open_printer_ex().
5813  ********************************************************************/
5814
5815 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5816 {
5817         fstring printername;
5818         const char *p;
5819
5820         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5821                 "portname=%s drivername=%s comment=%s location=%s\n",
5822                 info->servername, info->printername, info->sharename,
5823                 info->portname, info->drivername, info->comment, info->location));
5824
5825         /* we force some elements to "correct" values */
5826         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5827         fstrcpy(info->sharename, lp_servicename(snum));
5828
5829         /* check to see if we allow printername != sharename */
5830
5831         if ( lp_force_printername(snum) ) {
5832                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5833                         global_myname(), info->sharename );
5834         } else {
5835
5836                 /* make sure printername is in \\server\printername format */
5837
5838                 fstrcpy( printername, info->printername );
5839                 p = printername;
5840                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5841                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5842                                 p++;
5843                 }
5844
5845                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5846                          global_myname(), p );
5847         }
5848
5849         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5850         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5851
5852
5853
5854         return true;
5855 }
5856
5857 /****************************************************************************
5858 ****************************************************************************/
5859
5860 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5861 {
5862         char *cmd = lp_addport_cmd();
5863         char *command = NULL;
5864         int ret;
5865         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5866         bool is_print_op = false;
5867
5868         if ( !*cmd ) {
5869                 return WERR_ACCESS_DENIED;
5870         }
5871
5872         command = talloc_asprintf(ctx,
5873                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5874         if (!command) {
5875                 return WERR_NOMEM;
5876         }
5877
5878         if ( token )
5879                 is_print_op = user_has_privileges( token, &se_printop );
5880
5881         DEBUG(10,("Running [%s]\n", command));
5882
5883         /********* BEGIN SePrintOperatorPrivilege **********/
5884
5885         if ( is_print_op )
5886                 become_root();
5887
5888         ret = smbrun(command, NULL);
5889
5890         if ( is_print_op )
5891                 unbecome_root();
5892
5893         /********* END SePrintOperatorPrivilege **********/
5894
5895         DEBUGADD(10,("returned [%d]\n", ret));
5896
5897         TALLOC_FREE(command);
5898
5899         if ( ret != 0 ) {
5900                 return WERR_ACCESS_DENIED;
5901         }
5902
5903         return WERR_OK;
5904 }
5905
5906 /****************************************************************************
5907 ****************************************************************************/
5908
5909 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5910 {
5911         char *cmd = lp_addprinter_cmd();
5912         char **qlines;
5913         char *command = NULL;
5914         int numlines;
5915         int ret;
5916         int fd;
5917         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5918         bool is_print_op = false;
5919         char *remote_machine = talloc_strdup(ctx, "%m");
5920
5921         if (!remote_machine) {
5922                 return false;
5923         }
5924         remote_machine = talloc_sub_basic(ctx,
5925                                 current_user_info.smb_name,
5926                                 current_user_info.domain,
5927                                 remote_machine);
5928         if (!remote_machine) {
5929                 return false;
5930         }
5931
5932         command = talloc_asprintf(ctx,
5933                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5934                         cmd, printer->info_2->printername, printer->info_2->sharename,
5935                         printer->info_2->portname, printer->info_2->drivername,
5936                         printer->info_2->location, printer->info_2->comment, remote_machine);
5937         if (!command) {
5938                 return false;
5939         }
5940
5941         if ( token )
5942                 is_print_op = user_has_privileges( token, &se_printop );
5943
5944         DEBUG(10,("Running [%s]\n", command));
5945
5946         /********* BEGIN SePrintOperatorPrivilege **********/
5947
5948         if ( is_print_op )
5949                 become_root();
5950
5951         if ( (ret = smbrun(command, &fd)) == 0 ) {
5952                 /* Tell everyone we updated smb.conf. */
5953                 message_send_all(smbd_messaging_context(),
5954                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5955         }
5956
5957         if ( is_print_op )
5958                 unbecome_root();
5959
5960         /********* END SePrintOperatorPrivilege **********/
5961
5962         DEBUGADD(10,("returned [%d]\n", ret));
5963
5964         TALLOC_FREE(command);
5965         TALLOC_FREE(remote_machine);
5966
5967         if ( ret != 0 ) {
5968                 if (fd != -1)
5969                         close(fd);
5970                 return false;
5971         }
5972
5973         /* reload our services immediately */
5974         become_root();
5975         reload_services(false);
5976         unbecome_root();
5977
5978         numlines = 0;
5979         /* Get lines and convert them back to dos-codepage */
5980         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5981         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5982         close(fd);
5983
5984         /* Set the portname to what the script says the portname should be. */
5985         /* but don't require anything to be return from the script exit a good error code */
5986
5987         if (numlines) {
5988                 /* Set the portname to what the script says the portname should be. */
5989                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5990                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5991         }
5992
5993         TALLOC_FREE(qlines);
5994         return true;
5995 }
5996
5997
5998 /********************************************************************
5999  * Called by spoolss_api_setprinter
6000  * when updating a printer description.
6001  ********************************************************************/
6002
6003 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6004                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6005                              struct spoolss_DeviceMode *devmode)
6006 {
6007         int snum;
6008         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6009         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6010         WERROR result;
6011         UNISTR2 buffer;
6012         fstring asc_buffer;
6013
6014         DEBUG(8,("update_printer\n"));
6015
6016         result = WERR_OK;
6017
6018         if (!Printer) {
6019                 result = WERR_BADFID;
6020                 goto done;
6021         }
6022
6023         if (!get_printer_snum(p, handle, &snum, NULL)) {
6024                 result = WERR_BADFID;
6025                 goto done;
6026         }
6027
6028         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6029             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6030                 result = WERR_BADFID;
6031                 goto done;
6032         }
6033
6034         DEBUGADD(8,("Converting info_2 struct\n"));
6035
6036         /*
6037          * convert_printer_info converts the incoming
6038          * info from the client and overwrites the info
6039          * just read from the tdb in the pointer 'printer'.
6040          */
6041
6042         if (!convert_printer_info(info_ctr, printer)) {
6043                 result =  WERR_NOMEM;
6044                 goto done;
6045         }
6046
6047         if (devmode) {
6048                 /* we have a valid devmode
6049                    convert it and link it*/
6050
6051                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6052                 if (!convert_devicemode(printer->info_2->printername, devmode,
6053                                         &printer->info_2->devmode)) {
6054                         result =  WERR_NOMEM;
6055                         goto done;
6056                 }
6057         }
6058
6059         /* Do sanity check on the requested changes for Samba */
6060
6061         if (!check_printer_ok(printer->info_2, snum)) {
6062                 result = WERR_INVALID_PARAM;
6063                 goto done;
6064         }
6065
6066         /* FIXME!!! If the driver has changed we really should verify that
6067            it is installed before doing much else   --jerry */
6068
6069         /* Check calling user has permission to update printer description */
6070
6071         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6072                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6073                 result = WERR_ACCESS_DENIED;
6074                 goto done;
6075         }
6076
6077         /* Call addprinter hook */
6078         /* Check changes to see if this is really needed */
6079
6080         if ( *lp_addprinter_cmd()
6081                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6082                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6083                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6084                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6085         {
6086                 /* add_printer_hook() will call reload_services() */
6087
6088                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6089                                        printer) ) {
6090                         result = WERR_ACCESS_DENIED;
6091                         goto done;
6092                 }
6093         }
6094
6095         /*
6096          * When a *new* driver is bound to a printer, the drivername is used to
6097          * lookup previously saved driver initialization info, which is then
6098          * bound to the printer, simulating what happens in the Windows arch.
6099          */
6100         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6101         {
6102                 if (!set_driver_init(printer, 2))
6103                 {
6104                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6105                                 printer->info_2->drivername));
6106                 }
6107
6108                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6109                         printer->info_2->drivername));
6110
6111                 notify_printer_driver(snum, printer->info_2->drivername);
6112         }
6113
6114         /*
6115          * flag which changes actually occured.  This is a small subset of
6116          * all the possible changes.  We also have to update things in the
6117          * DsSpooler key.
6118          */
6119
6120         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6121                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6122                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6123                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6124
6125                 notify_printer_comment(snum, printer->info_2->comment);
6126         }
6127
6128         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6129                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6130                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6131                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6132
6133                 notify_printer_sharename(snum, printer->info_2->sharename);
6134         }
6135
6136         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6137                 char *pname;
6138
6139                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6140                         pname++;
6141                 else
6142                         pname = printer->info_2->printername;
6143
6144
6145                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6146                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6147                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6148
6149                 notify_printer_printername( snum, pname );
6150         }
6151
6152         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6153                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6154                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6155                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6156
6157                 notify_printer_port(snum, printer->info_2->portname);
6158         }
6159
6160         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6161                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6162                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6163                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6164
6165                 notify_printer_location(snum, printer->info_2->location);
6166         }
6167
6168         /* here we need to update some more DsSpooler keys */
6169         /* uNCName, serverName, shortServerName */
6170
6171         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6172         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6173                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6174         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6175                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6176
6177         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6178                  global_myname(), printer->info_2->sharename );
6179         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6180         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6181                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6182
6183         /* Update printer info */
6184         result = mod_a_printer(printer, 2);
6185
6186 done:
6187         free_a_printer(&printer, 2);
6188         free_a_printer(&old_printer, 2);
6189
6190
6191         return result;
6192 }
6193
6194 /****************************************************************************
6195 ****************************************************************************/
6196 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6197                                            struct policy_handle *handle,
6198                                            struct spoolss_SetPrinterInfo7 *info7)
6199 {
6200 #ifdef HAVE_ADS
6201         int snum;
6202         Printer_entry *Printer;
6203
6204         if ( lp_security() != SEC_ADS ) {
6205                 return WERR_UNKNOWN_LEVEL;
6206         }
6207
6208         Printer = find_printer_index_by_hnd(p, handle);
6209
6210         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6211
6212         if (!Printer)
6213                 return WERR_BADFID;
6214
6215         if (!get_printer_snum(p, handle, &snum, NULL))
6216                 return WERR_BADFID;
6217
6218         nt_printer_publish(Printer, snum, info7->action);
6219
6220         return WERR_OK;
6221 #else
6222         return WERR_UNKNOWN_LEVEL;
6223 #endif
6224 }
6225
6226 /****************************************************************
6227  _spoolss_SetPrinter
6228 ****************************************************************/
6229
6230 WERROR _spoolss_SetPrinter(pipes_struct *p,
6231                            struct spoolss_SetPrinter *r)
6232 {
6233         WERROR result;
6234
6235         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6236
6237         if (!Printer) {
6238                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6239                         OUR_HANDLE(r->in.handle)));
6240                 return WERR_BADFID;
6241         }
6242
6243         /* check the level */
6244         switch (r->in.info_ctr->level) {
6245                 case 0:
6246                         return control_printer(r->in.handle, r->in.command, p);
6247                 case 2:
6248                         result = update_printer(p, r->in.handle,
6249                                                 r->in.info_ctr,
6250                                                 r->in.devmode_ctr->devmode);
6251                         if (!W_ERROR_IS_OK(result))
6252                                 return result;
6253                         if (r->in.secdesc_ctr->sd)
6254                                 result = update_printer_sec(r->in.handle, p,
6255                                                             r->in.secdesc_ctr);
6256                         return result;
6257                 case 3:
6258                         return update_printer_sec(r->in.handle, p,
6259                                                   r->in.secdesc_ctr);
6260                 case 7:
6261                         return publish_or_unpublish_printer(p, r->in.handle,
6262                                                             r->in.info_ctr->info.info7);
6263                 default:
6264                         return WERR_UNKNOWN_LEVEL;
6265         }
6266 }
6267
6268 /****************************************************************
6269  _spoolss_FindClosePrinterNotify
6270 ****************************************************************/
6271
6272 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6273                                        struct spoolss_FindClosePrinterNotify *r)
6274 {
6275         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6276
6277         if (!Printer) {
6278                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6279                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6280                 return WERR_BADFID;
6281         }
6282
6283         if (Printer->notify.client_connected == true) {
6284                 int snum = -1;
6285
6286                 if ( Printer->printer_type == SPLHND_SERVER)
6287                         snum = -1;
6288                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6289                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6290                         return WERR_BADFID;
6291
6292                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6293         }
6294
6295         Printer->notify.flags=0;
6296         Printer->notify.options=0;
6297         Printer->notify.localmachine[0]='\0';
6298         Printer->notify.printerlocal=0;
6299         TALLOC_FREE(Printer->notify.option);
6300         Printer->notify.client_connected = false;
6301
6302         return WERR_OK;
6303 }
6304
6305 /****************************************************************
6306  _spoolss_AddJob
6307 ****************************************************************/
6308
6309 WERROR _spoolss_AddJob(pipes_struct *p,
6310                        struct spoolss_AddJob *r)
6311 {
6312         if (!r->in.buffer && (r->in.offered != 0)) {
6313                 return WERR_INVALID_PARAM;
6314         }
6315
6316         /* this is what a NT server returns for AddJob. AddJob must fail on
6317          * non-local printers */
6318
6319         if (r->in.level != 1) {
6320                 return WERR_UNKNOWN_LEVEL;
6321         }
6322
6323         return WERR_INVALID_PARAM;
6324 }
6325
6326 /****************************************************************************
6327 fill_job_info1
6328 ****************************************************************************/
6329
6330 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6331                              struct spoolss_JobInfo1 *r,
6332                              const print_queue_struct *queue,
6333                              int position, int snum,
6334                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6335 {
6336         struct tm *t;
6337
6338         t = gmtime(&queue->time);
6339
6340         r->job_id               = queue->job;
6341
6342         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6343         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6344         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6345         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6346         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6347         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6348         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6349         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6350         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6351         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6352         r->text_status          = talloc_strdup(mem_ctx, "");
6353         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6354
6355         r->status               = nt_printj_status(queue->status);
6356         r->priority             = queue->priority;
6357         r->position             = position;
6358         r->total_pages          = queue->page_count;
6359         r->pages_printed        = 0; /* ??? */
6360
6361         init_systemtime(&r->submitted, t);
6362
6363         return WERR_OK;
6364 }
6365
6366 /****************************************************************************
6367 fill_job_info2
6368 ****************************************************************************/
6369
6370 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6371                              struct spoolss_JobInfo2 *r,
6372                              const print_queue_struct *queue,
6373                              int position, int snum,
6374                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6375                              struct spoolss_DeviceMode *devmode)
6376 {
6377         struct tm *t;
6378
6379         t = gmtime(&queue->time);
6380
6381         r->job_id               = queue->job;
6382
6383         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6384         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6385         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6386         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6387         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6388         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6389         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6390         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6391         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6392         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6393         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6394         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6395         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6396         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6397         r->parameters           = talloc_strdup(mem_ctx, "");
6398         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6399         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6400         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6401
6402         r->devmode              = devmode;
6403
6404         r->text_status          = talloc_strdup(mem_ctx, "");
6405         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6406
6407         r->secdesc              = NULL;
6408
6409         r->status               = nt_printj_status(queue->status);
6410         r->priority             = queue->priority;
6411         r->position             = position;
6412         r->start_time           = 0;
6413         r->until_time           = 0;
6414         r->total_pages          = queue->page_count;
6415         r->size                 = queue->size;
6416         init_systemtime(&r->submitted, t);
6417         r->time                 = 0;
6418         r->pages_printed        = 0; /* ??? */
6419
6420         return WERR_OK;
6421 }
6422
6423 /****************************************************************************
6424 fill_job_info3
6425 ****************************************************************************/
6426
6427 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6428                              struct spoolss_JobInfo3 *r,
6429                              const print_queue_struct *queue,
6430                              const print_queue_struct *next_queue,
6431                              int position, int snum,
6432                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6433 {
6434         r->job_id               = queue->job;
6435         r->next_job_id          = 0;
6436         if (next_queue) {
6437                 r->next_job_id  = next_queue->job;
6438         }
6439         r->reserved             = 0;
6440
6441         return WERR_OK;
6442 }
6443
6444 /****************************************************************************
6445  Enumjobs at level 1.
6446 ****************************************************************************/
6447
6448 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6449                               const print_queue_struct *queue,
6450                               uint32_t num_queues, int snum,
6451                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6452                               union spoolss_JobInfo **info_p,
6453                               uint32_t *count)
6454 {
6455         union spoolss_JobInfo *info;
6456         int i;
6457         WERROR result = WERR_OK;
6458
6459         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6460         W_ERROR_HAVE_NO_MEMORY(info);
6461
6462         *count = num_queues;
6463
6464         for (i=0; i<*count; i++) {
6465                 result = fill_job_info1(info,
6466                                         &info[i].info1,
6467                                         &queue[i],
6468                                         i,
6469                                         snum,
6470                                         ntprinter);
6471                 if (!W_ERROR_IS_OK(result)) {
6472                         goto out;
6473                 }
6474         }
6475
6476  out:
6477         if (!W_ERROR_IS_OK(result)) {
6478                 TALLOC_FREE(info);
6479                 *count = 0;
6480                 return result;
6481         }
6482
6483         *info_p = info;
6484
6485         return WERR_OK;
6486 }
6487
6488 /****************************************************************************
6489  Enumjobs at level 2.
6490 ****************************************************************************/
6491
6492 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6493                               const print_queue_struct *queue,
6494                               uint32_t num_queues, int snum,
6495                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6496                               union spoolss_JobInfo **info_p,
6497                               uint32_t *count)
6498 {
6499         union spoolss_JobInfo *info;
6500         int i;
6501         WERROR result = WERR_OK;
6502
6503         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6504         W_ERROR_HAVE_NO_MEMORY(info);
6505
6506         *count = num_queues;
6507
6508         for (i=0; i<*count; i++) {
6509
6510                 struct spoolss_DeviceMode *devmode;
6511
6512                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6513                 if (!devmode) {
6514                         result = WERR_NOMEM;
6515                         goto out;
6516                 }
6517
6518                 result = fill_job_info2(info,
6519                                         &info[i].info2,
6520                                         &queue[i],
6521                                         i,
6522                                         snum,
6523                                         ntprinter,
6524                                         devmode);
6525                 if (!W_ERROR_IS_OK(result)) {
6526                         goto out;
6527                 }
6528         }
6529
6530  out:
6531         if (!W_ERROR_IS_OK(result)) {
6532                 TALLOC_FREE(info);
6533                 *count = 0;
6534                 return result;
6535         }
6536
6537         *info_p = info;
6538
6539         return WERR_OK;
6540 }
6541
6542 /****************************************************************************
6543  Enumjobs at level 3.
6544 ****************************************************************************/
6545
6546 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6547                               const print_queue_struct *queue,
6548                               uint32_t num_queues, int snum,
6549                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6550                               union spoolss_JobInfo **info_p,
6551                               uint32_t *count)
6552 {
6553         union spoolss_JobInfo *info;
6554         int i;
6555         WERROR result = WERR_OK;
6556
6557         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6558         W_ERROR_HAVE_NO_MEMORY(info);
6559
6560         *count = num_queues;
6561
6562         for (i=0; i<*count; i++) {
6563                 const print_queue_struct *next_queue = NULL;
6564
6565                 if (i+1 < *count) {
6566                         next_queue = &queue[i+1];
6567                 }
6568
6569                 result = fill_job_info3(info,
6570                                         &info[i].info3,
6571                                         &queue[i],
6572                                         next_queue,
6573                                         i,
6574                                         snum,
6575                                         ntprinter);
6576                 if (!W_ERROR_IS_OK(result)) {
6577                         goto out;
6578                 }
6579         }
6580
6581  out:
6582         if (!W_ERROR_IS_OK(result)) {
6583                 TALLOC_FREE(info);
6584                 *count = 0;
6585                 return result;
6586         }
6587
6588         *info_p = info;
6589
6590         return WERR_OK;
6591 }
6592
6593 /****************************************************************
6594  _spoolss_EnumJobs
6595 ****************************************************************/
6596
6597 WERROR _spoolss_EnumJobs(pipes_struct *p,
6598                          struct spoolss_EnumJobs *r)
6599 {
6600         WERROR result;
6601         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6602         int snum;
6603         print_status_struct prt_status;
6604         print_queue_struct *queue = NULL;
6605         uint32_t count;
6606
6607         /* that's an [in out] buffer */
6608
6609         if (!r->in.buffer && (r->in.offered != 0)) {
6610                 return WERR_INVALID_PARAM;
6611         }
6612
6613         DEBUG(4,("_spoolss_EnumJobs\n"));
6614
6615         *r->out.needed = 0;
6616         *r->out.count = 0;
6617         *r->out.info = NULL;
6618
6619         /* lookup the printer snum and tdb entry */
6620
6621         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6622                 return WERR_BADFID;
6623         }
6624
6625         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6626         if (!W_ERROR_IS_OK(result)) {
6627                 return result;
6628         }
6629
6630         count = print_queue_status(snum, &queue, &prt_status);
6631         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6632                 count, prt_status.status, prt_status.message));
6633
6634         if (count == 0) {
6635                 SAFE_FREE(queue);
6636                 free_a_printer(&ntprinter, 2);
6637                 return WERR_OK;
6638         }
6639
6640         switch (r->in.level) {
6641         case 1:
6642                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6643                                          ntprinter, r->out.info, r->out.count);
6644                 break;
6645         case 2:
6646                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6647                                          ntprinter, r->out.info, r->out.count);
6648                 break;
6649         case 3:
6650                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6651                                          ntprinter, r->out.info, r->out.count);
6652                 break;
6653         default:
6654                 result = WERR_UNKNOWN_LEVEL;
6655                 break;
6656         }
6657
6658         SAFE_FREE(queue);
6659         free_a_printer(&ntprinter, 2);
6660
6661         if (!W_ERROR_IS_OK(result)) {
6662                 return result;
6663         }
6664
6665         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6666                                                      spoolss_EnumJobs, NULL,
6667                                                      *r->out.info, r->in.level,
6668                                                      *r->out.count);
6669         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6670         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6671
6672         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6673 }
6674
6675 /****************************************************************
6676  _spoolss_ScheduleJob
6677 ****************************************************************/
6678
6679 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6680                             struct spoolss_ScheduleJob *r)
6681 {
6682         return WERR_OK;
6683 }
6684
6685 /****************************************************************
6686  _spoolss_SetJob
6687 ****************************************************************/
6688
6689 WERROR _spoolss_SetJob(pipes_struct *p,
6690                        struct spoolss_SetJob *r)
6691 {
6692         int snum;
6693         WERROR errcode = WERR_BADFUNC;
6694
6695         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6696                 return WERR_BADFID;
6697         }
6698
6699         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6700                 return WERR_INVALID_PRINTER_NAME;
6701         }
6702
6703         switch (r->in.command) {
6704         case SPOOLSS_JOB_CONTROL_CANCEL:
6705         case SPOOLSS_JOB_CONTROL_DELETE:
6706                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6707                         errcode = WERR_OK;
6708                 }
6709                 break;
6710         case SPOOLSS_JOB_CONTROL_PAUSE:
6711                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6712                         errcode = WERR_OK;
6713                 }
6714                 break;
6715         case SPOOLSS_JOB_CONTROL_RESTART:
6716         case SPOOLSS_JOB_CONTROL_RESUME:
6717                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6718                         errcode = WERR_OK;
6719                 }
6720                 break;
6721         default:
6722                 return WERR_UNKNOWN_LEVEL;
6723         }
6724
6725         return errcode;
6726 }
6727
6728 /****************************************************************************
6729  Enumerates all printer drivers by level.
6730 ****************************************************************************/
6731
6732 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6733                                        const char *servername,
6734                                        const char *architecture,
6735                                        uint32_t level,
6736                                        union spoolss_DriverInfo **info_p,
6737                                        uint32_t *count_p)
6738 {
6739         int i;
6740         int ndrivers;
6741         uint32_t version;
6742         fstring *list = NULL;
6743         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6744         union spoolss_DriverInfo *info = NULL;
6745         uint32_t count = 0;
6746         WERROR result = WERR_OK;
6747
6748         *count_p = 0;
6749         *info_p = NULL;
6750
6751         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6752                 list = NULL;
6753                 ndrivers = get_ntdrivers(&list, architecture, version);
6754                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6755                         ndrivers, architecture, version));
6756
6757                 if (ndrivers == -1) {
6758                         result = WERR_NOMEM;
6759                         goto out;
6760                 }
6761
6762                 if (ndrivers != 0) {
6763                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6764                                                     union spoolss_DriverInfo,
6765                                                     count + ndrivers);
6766                         if (!info) {
6767                                 DEBUG(0,("enumprinterdrivers_level1: "
6768                                         "failed to enlarge driver info buffer!\n"));
6769                                 result = WERR_NOMEM;
6770                                 goto out;
6771                         }
6772                 }
6773
6774                 for (i=0; i<ndrivers; i++) {
6775                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6776                         ZERO_STRUCT(driver);
6777                         result = get_a_printer_driver(&driver, 3, list[i],
6778                                                       architecture, version);
6779                         if (!W_ERROR_IS_OK(result)) {
6780                                 goto out;
6781                         }
6782
6783                         switch (level) {
6784                         case 1:
6785                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6786                                                                    &driver, servername,
6787                                                                    architecture);
6788                                 break;
6789                         case 2:
6790                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6791                                                                    &driver, servername);
6792                                 break;
6793                         case 3:
6794                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6795                                                                    &driver, servername);
6796                                 break;
6797                         case 4:
6798                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6799                                                                    &driver, servername);
6800                                 break;
6801                         case 5:
6802                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6803                                                                    &driver, servername);
6804                                 break;
6805                         case 6:
6806                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6807                                                                    &driver, servername);
6808                                 break;
6809                         default:
6810                                 result = WERR_UNKNOWN_LEVEL;
6811                                 break;
6812                         }
6813
6814                         if (!W_ERROR_IS_OK(result)) {
6815                                 free_a_printer_driver(driver, 3);
6816                                 goto out;
6817                         }
6818                         free_a_printer_driver(driver, 3);
6819                 }
6820
6821                 count += ndrivers;
6822                 SAFE_FREE(list);
6823         }
6824
6825  out:
6826         SAFE_FREE(list);
6827
6828         if (!W_ERROR_IS_OK(result)) {
6829                 TALLOC_FREE(info);
6830                 return result;
6831         }
6832
6833         *info_p = info;
6834         *count_p = count;
6835
6836         return WERR_OK;
6837 }
6838
6839 /****************************************************************************
6840  Enumerates all printer drivers at level 1.
6841 ****************************************************************************/
6842
6843 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6844                                         const char *servername,
6845                                         const char *architecture,
6846                                         union spoolss_DriverInfo **info_p,
6847                                         uint32_t *count)
6848 {
6849         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6850                                         info_p, count);
6851 }
6852
6853 /****************************************************************************
6854  Enumerates all printer drivers at level 2.
6855 ****************************************************************************/
6856
6857 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6858                                         const char *servername,
6859                                         const char *architecture,
6860                                         union spoolss_DriverInfo **info_p,
6861                                         uint32_t *count)
6862 {
6863         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6864                                         info_p, count);
6865 }
6866
6867 /****************************************************************************
6868  Enumerates all printer drivers at level 3.
6869 ****************************************************************************/
6870
6871 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6872                                         const char *servername,
6873                                         const char *architecture,
6874                                         union spoolss_DriverInfo **info_p,
6875                                         uint32_t *count)
6876 {
6877         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6878                                         info_p, count);
6879 }
6880
6881 /****************************************************************************
6882  Enumerates all printer drivers at level 4.
6883 ****************************************************************************/
6884
6885 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6886                                         const char *servername,
6887                                         const char *architecture,
6888                                         union spoolss_DriverInfo **info_p,
6889                                         uint32_t *count)
6890 {
6891         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6892                                         info_p, count);
6893 }
6894
6895 /****************************************************************************
6896  Enumerates all printer drivers at level 5.
6897 ****************************************************************************/
6898
6899 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6900                                         const char *servername,
6901                                         const char *architecture,
6902                                         union spoolss_DriverInfo **info_p,
6903                                         uint32_t *count)
6904 {
6905         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6906                                         info_p, count);
6907 }
6908
6909 /****************************************************************************
6910  Enumerates all printer drivers at level 6.
6911 ****************************************************************************/
6912
6913 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6914                                         const char *servername,
6915                                         const char *architecture,
6916                                         union spoolss_DriverInfo **info_p,
6917                                         uint32_t *count)
6918 {
6919         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6920                                         info_p, count);
6921 }
6922
6923
6924 /****************************************************************
6925  _spoolss_EnumPrinterDrivers
6926 ****************************************************************/
6927
6928 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6929                                    struct spoolss_EnumPrinterDrivers *r)
6930 {
6931         const char *cservername;
6932         WERROR result;
6933
6934         /* that's an [in out] buffer */
6935
6936         if (!r->in.buffer && (r->in.offered != 0)) {
6937                 return WERR_INVALID_PARAM;
6938         }
6939
6940         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6941
6942         *r->out.needed = 0;
6943         *r->out.count = 0;
6944         *r->out.info = NULL;
6945
6946         cservername = canon_servername(r->in.server);
6947
6948         if (!is_myname_or_ipaddr(cservername)) {
6949                 return WERR_UNKNOWN_PRINTER_DRIVER;
6950         }
6951
6952         switch (r->in.level) {
6953         case 1:
6954                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6955                                                    r->in.environment,
6956                                                    r->out.info, r->out.count);
6957                 break;
6958         case 2:
6959                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6960                                                    r->in.environment,
6961                                                    r->out.info, r->out.count);
6962                 break;
6963         case 3:
6964                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6965                                                    r->in.environment,
6966                                                    r->out.info, r->out.count);
6967                 break;
6968         case 4:
6969                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6970                                                    r->in.environment,
6971                                                    r->out.info, r->out.count);
6972                 break;
6973         case 5:
6974                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6975                                                    r->in.environment,
6976                                                    r->out.info, r->out.count);
6977                 break;
6978         case 6:
6979                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6980                                                    r->in.environment,
6981                                                    r->out.info, r->out.count);
6982                 break;
6983         default:
6984                 return WERR_UNKNOWN_LEVEL;
6985         }
6986
6987         if (!W_ERROR_IS_OK(result)) {
6988                 return result;
6989         }
6990
6991         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6992                                                      spoolss_EnumPrinterDrivers, NULL,
6993                                                      *r->out.info, r->in.level,
6994                                                      *r->out.count);
6995         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6996         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6997
6998         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6999 }
7000
7001 /****************************************************************************
7002 ****************************************************************************/
7003
7004 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7005                                struct spoolss_FormInfo1 *r,
7006                                const nt_forms_struct *form)
7007 {
7008         r->form_name    = talloc_strdup(mem_ctx, form->name);
7009         W_ERROR_HAVE_NO_MEMORY(r->form_name);
7010
7011         r->flags        = form->flag;
7012         r->size.width   = form->width;
7013         r->size.height  = form->length;
7014         r->area.left    = form->left;
7015         r->area.top     = form->top;
7016         r->area.right   = form->right;
7017         r->area.bottom  = form->bottom;
7018
7019         return WERR_OK;
7020 }
7021
7022 /****************************************************************
7023  spoolss_enumforms_level1
7024 ****************************************************************/
7025
7026 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7027                                        const nt_forms_struct *builtin_forms,
7028                                        uint32_t num_builtin_forms,
7029                                        const nt_forms_struct *user_forms,
7030                                        uint32_t num_user_forms,
7031                                        union spoolss_FormInfo **info_p,
7032                                        uint32_t *count)
7033 {
7034         union spoolss_FormInfo *info;
7035         WERROR result = WERR_OK;
7036         int i;
7037
7038         *count = num_builtin_forms + num_user_forms;
7039
7040         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7041         W_ERROR_HAVE_NO_MEMORY(info);
7042
7043         /* construct the list of form structures */
7044         for (i=0; i<num_builtin_forms; i++) {
7045                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7046                 result = fill_form_info_1(info, &info[i].info1,
7047                                           &builtin_forms[i]);
7048                 if (!W_ERROR_IS_OK(result)) {
7049                         goto out;
7050                 }
7051         }
7052
7053         for (i=0; i<num_user_forms; i++) {
7054                 DEBUGADD(6,("Filling user form number [%d]\n",i));
7055                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7056                                           &user_forms[i]);
7057                 if (!W_ERROR_IS_OK(result)) {
7058                         goto out;
7059                 }
7060         }
7061
7062  out:
7063         if (!W_ERROR_IS_OK(result)) {
7064                 TALLOC_FREE(info);
7065                 *count = 0;
7066                 return result;
7067         }
7068
7069         *info_p = info;
7070
7071         return WERR_OK;
7072 }
7073
7074 /****************************************************************
7075  _spoolss_EnumForms
7076 ****************************************************************/
7077
7078 WERROR _spoolss_EnumForms(pipes_struct *p,
7079                           struct spoolss_EnumForms *r)
7080 {
7081         WERROR result;
7082         nt_forms_struct *user_forms = NULL;
7083         nt_forms_struct *builtin_forms = NULL;
7084         uint32_t num_user_forms;
7085         uint32_t num_builtin_forms;
7086
7087         *r->out.count = 0;
7088         *r->out.needed = 0;
7089         *r->out.info = NULL;
7090
7091         /* that's an [in out] buffer */
7092
7093         if (!r->in.buffer && (r->in.offered != 0) ) {
7094                 return WERR_INVALID_PARAM;
7095         }
7096
7097         DEBUG(4,("_spoolss_EnumForms\n"));
7098         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7099         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7100
7101         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7102         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7103         num_user_forms = get_ntforms(&user_forms);
7104         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7105
7106         if (num_user_forms + num_builtin_forms == 0) {
7107                 SAFE_FREE(builtin_forms);
7108                 SAFE_FREE(user_forms);
7109                 return WERR_NO_MORE_ITEMS;
7110         }
7111
7112         switch (r->in.level) {
7113         case 1:
7114                 result = spoolss_enumforms_level1(p->mem_ctx,
7115                                                   builtin_forms,
7116                                                   num_builtin_forms,
7117                                                   user_forms,
7118                                                   num_user_forms,
7119                                                   r->out.info,
7120                                                   r->out.count);
7121                 break;
7122         default:
7123                 result = WERR_UNKNOWN_LEVEL;
7124                 break;
7125         }
7126
7127         SAFE_FREE(user_forms);
7128         SAFE_FREE(builtin_forms);
7129
7130         if (!W_ERROR_IS_OK(result)) {
7131                 return result;
7132         }
7133
7134         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7135                                                      spoolss_EnumForms, NULL,
7136                                                      *r->out.info, r->in.level,
7137                                                      *r->out.count);
7138         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7139         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7140
7141         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7142 }
7143
7144 /****************************************************************
7145 ****************************************************************/
7146
7147 static WERROR find_form_byname(const char *name,
7148                                nt_forms_struct *form)
7149 {
7150         nt_forms_struct *list = NULL;
7151         int num_forms = 0, i = 0;
7152
7153         if (get_a_builtin_ntform_by_string(name, form)) {
7154                 return WERR_OK;
7155         }
7156
7157         num_forms = get_ntforms(&list);
7158         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7159
7160         if (num_forms == 0) {
7161                 return WERR_BADFID;
7162         }
7163
7164         /* Check if the requested name is in the list of form structures */
7165         for (i = 0; i < num_forms; i++) {
7166
7167                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7168
7169                 if (strequal(name, list[i].name)) {
7170                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7171                         *form = list[i];
7172                         SAFE_FREE(list);
7173                         return WERR_OK;
7174                 }
7175         }
7176
7177         SAFE_FREE(list);
7178
7179         return WERR_BADFID;
7180 }
7181
7182 /****************************************************************
7183  _spoolss_GetForm
7184 ****************************************************************/
7185
7186 WERROR _spoolss_GetForm(pipes_struct *p,
7187                         struct spoolss_GetForm *r)
7188 {
7189         WERROR result;
7190         nt_forms_struct form;
7191
7192         /* that's an [in out] buffer */
7193
7194         if (!r->in.buffer && (r->in.offered != 0)) {
7195                 return WERR_INVALID_PARAM;
7196         }
7197
7198         DEBUG(4,("_spoolss_GetForm\n"));
7199         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7200         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7201
7202         result = find_form_byname(r->in.form_name, &form);
7203         if (!W_ERROR_IS_OK(result)) {
7204                 TALLOC_FREE(r->out.info);
7205                 return result;
7206         }
7207
7208         switch (r->in.level) {
7209         case 1:
7210                 result = fill_form_info_1(p->mem_ctx,
7211                                           &r->out.info->info1,
7212                                           &form);
7213                 break;
7214
7215         default:
7216                 result = WERR_UNKNOWN_LEVEL;
7217                 break;
7218         }
7219
7220         if (!W_ERROR_IS_OK(result)) {
7221                 TALLOC_FREE(r->out.info);
7222                 return result;
7223         }
7224
7225         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7226                                                r->out.info, r->in.level);
7227         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7228
7229         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7230 }
7231
7232 /****************************************************************************
7233 ****************************************************************************/
7234
7235 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7236                           struct spoolss_PortInfo1 *r,
7237                           const char *name)
7238 {
7239         r->port_name = talloc_strdup(mem_ctx, name);
7240         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7241
7242         return WERR_OK;
7243 }
7244
7245 /****************************************************************************
7246  TODO: This probably needs distinguish between TCP/IP and Local ports
7247  somehow.
7248 ****************************************************************************/
7249
7250 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7251                           struct spoolss_PortInfo2 *r,
7252                           const char *name)
7253 {
7254         r->port_name = talloc_strdup(mem_ctx, name);
7255         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7256
7257         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7258         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7259
7260         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7261         W_ERROR_HAVE_NO_MEMORY(r->description);
7262
7263         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7264         r->reserved = 0;
7265
7266         return WERR_OK;
7267 }
7268
7269
7270 /****************************************************************************
7271  wrapper around the enumer ports command
7272 ****************************************************************************/
7273
7274 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7275 {
7276         char *cmd = lp_enumports_cmd();
7277         char **qlines = NULL;
7278         char *command = NULL;
7279         int numlines;
7280         int ret;
7281         int fd;
7282
7283         *count = 0;
7284         *lines = NULL;
7285
7286         /* if no hook then just fill in the default port */
7287
7288         if ( !*cmd ) {
7289                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7290                         return WERR_NOMEM;
7291                 }
7292                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7293                         TALLOC_FREE(qlines);
7294                         return WERR_NOMEM;
7295                 }
7296                 qlines[1] = NULL;
7297                 numlines = 1;
7298         }
7299         else {
7300                 /* we have a valid enumport command */
7301
7302                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7303                 if (!command) {
7304                         return WERR_NOMEM;
7305                 }
7306
7307                 DEBUG(10,("Running [%s]\n", command));
7308                 ret = smbrun(command, &fd);
7309                 DEBUG(10,("Returned [%d]\n", ret));
7310                 TALLOC_FREE(command);
7311                 if (ret != 0) {
7312                         if (fd != -1) {
7313                                 close(fd);
7314                         }
7315                         return WERR_ACCESS_DENIED;
7316                 }
7317
7318                 numlines = 0;
7319                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7320                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7321                 close(fd);
7322         }
7323
7324         *count = numlines;
7325         *lines = qlines;
7326
7327         return WERR_OK;
7328 }
7329
7330 /****************************************************************************
7331  enumports level 1.
7332 ****************************************************************************/
7333
7334 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7335                                 union spoolss_PortInfo **info_p,
7336                                 uint32_t *count)
7337 {
7338         union spoolss_PortInfo *info = NULL;
7339         int i=0;
7340         WERROR result = WERR_OK;
7341         char **qlines = NULL;
7342         int numlines = 0;
7343
7344         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7345         if (!W_ERROR_IS_OK(result)) {
7346                 goto out;
7347         }
7348
7349         if (numlines) {
7350                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7351                 if (!info) {
7352                         DEBUG(10,("Returning WERR_NOMEM\n"));
7353                         result = WERR_NOMEM;
7354                         goto out;
7355                 }
7356
7357                 for (i=0; i<numlines; i++) {
7358                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7359                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7360                         if (!W_ERROR_IS_OK(result)) {
7361                                 goto out;
7362                         }
7363                 }
7364         }
7365         TALLOC_FREE(qlines);
7366
7367 out:
7368         if (!W_ERROR_IS_OK(result)) {
7369                 TALLOC_FREE(info);
7370                 TALLOC_FREE(qlines);
7371                 *count = 0;
7372                 *info_p = NULL;
7373                 return result;
7374         }
7375
7376         *info_p = info;
7377         *count = numlines;
7378
7379         return WERR_OK;
7380 }
7381
7382 /****************************************************************************
7383  enumports level 2.
7384 ****************************************************************************/
7385
7386 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7387                                 union spoolss_PortInfo **info_p,
7388                                 uint32_t *count)
7389 {
7390         union spoolss_PortInfo *info = NULL;
7391         int i=0;
7392         WERROR result = WERR_OK;
7393         char **qlines = NULL;
7394         int numlines = 0;
7395
7396         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7397         if (!W_ERROR_IS_OK(result)) {
7398                 goto out;
7399         }
7400
7401         if (numlines) {
7402                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7403                 if (!info) {
7404                         DEBUG(10,("Returning WERR_NOMEM\n"));
7405                         result = WERR_NOMEM;
7406                         goto out;
7407                 }
7408
7409                 for (i=0; i<numlines; i++) {
7410                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7411                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7412                         if (!W_ERROR_IS_OK(result)) {
7413                                 goto out;
7414                         }
7415                 }
7416         }
7417         TALLOC_FREE(qlines);
7418
7419 out:
7420         if (!W_ERROR_IS_OK(result)) {
7421                 TALLOC_FREE(info);
7422                 TALLOC_FREE(qlines);
7423                 *count = 0;
7424                 *info_p = NULL;
7425                 return result;
7426         }
7427
7428         *info_p = info;
7429         *count = numlines;
7430
7431         return WERR_OK;
7432 }
7433
7434 /****************************************************************
7435  _spoolss_EnumPorts
7436 ****************************************************************/
7437
7438 WERROR _spoolss_EnumPorts(pipes_struct *p,
7439                           struct spoolss_EnumPorts *r)
7440 {
7441         WERROR result;
7442
7443         /* that's an [in out] buffer */
7444
7445         if (!r->in.buffer && (r->in.offered != 0)) {
7446                 return WERR_INVALID_PARAM;
7447         }
7448
7449         DEBUG(4,("_spoolss_EnumPorts\n"));
7450
7451         *r->out.count = 0;
7452         *r->out.needed = 0;
7453         *r->out.info = NULL;
7454
7455         switch (r->in.level) {
7456         case 1:
7457                 result = enumports_level_1(p->mem_ctx, r->out.info,
7458                                            r->out.count);
7459                 break;
7460         case 2:
7461                 result = enumports_level_2(p->mem_ctx, r->out.info,
7462                                            r->out.count);
7463                 break;
7464         default:
7465                 return WERR_UNKNOWN_LEVEL;
7466         }
7467
7468         if (!W_ERROR_IS_OK(result)) {
7469                 return result;
7470         }
7471
7472         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7473                                                      spoolss_EnumPorts, NULL,
7474                                                      *r->out.info, r->in.level,
7475                                                      *r->out.count);
7476         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7477         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7478
7479         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7480 }
7481
7482 /****************************************************************************
7483 ****************************************************************************/
7484
7485 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7486                                            const char *server,
7487                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7488                                            struct spoolss_DeviceMode *devmode,
7489                                            struct security_descriptor *sec_desc,
7490                                            struct spoolss_UserLevelCtr *user_ctr,
7491                                            struct policy_handle *handle)
7492 {
7493         NT_PRINTER_INFO_LEVEL *printer = NULL;
7494         fstring name;
7495         int     snum;
7496         WERROR err = WERR_OK;
7497
7498         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7499                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7500                 return WERR_NOMEM;
7501         }
7502
7503         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7504         if (!convert_printer_info(info_ctr, printer)) {
7505                 free_a_printer(&printer, 2);
7506                 return WERR_NOMEM;
7507         }
7508
7509         /* check to see if the printer already exists */
7510
7511         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7512                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7513                         printer->info_2->sharename));
7514                 free_a_printer(&printer, 2);
7515                 return WERR_PRINTER_ALREADY_EXISTS;
7516         }
7517
7518         /* FIXME!!!  smbd should check to see if the driver is installed before
7519            trying to add a printer like this  --jerry */
7520
7521         if (*lp_addprinter_cmd() ) {
7522                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7523                                        printer) ) {
7524                         free_a_printer(&printer,2);
7525                         return WERR_ACCESS_DENIED;
7526                 }
7527         } else {
7528                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7529                         "smb.conf parameter \"addprinter command\" is defined. This"
7530                         "parameter must exist for this call to succeed\n",
7531                         printer->info_2->sharename ));
7532         }
7533
7534         /* use our primary netbios name since get_a_printer() will convert
7535            it to what the client expects on a case by case basis */
7536
7537         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7538              printer->info_2->sharename);
7539
7540
7541         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7542                 free_a_printer(&printer,2);
7543                 return WERR_ACCESS_DENIED;
7544         }
7545
7546         /* you must be a printer admin to add a new printer */
7547         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7548                 free_a_printer(&printer,2);
7549                 return WERR_ACCESS_DENIED;
7550         }
7551
7552         /*
7553          * Do sanity check on the requested changes for Samba.
7554          */
7555
7556         if (!check_printer_ok(printer->info_2, snum)) {
7557                 free_a_printer(&printer,2);
7558                 return WERR_INVALID_PARAM;
7559         }
7560
7561         /*
7562          * When a printer is created, the drivername bound to the printer is used
7563          * to lookup previously saved driver initialization info, which is then
7564          * bound to the new printer, simulating what happens in the Windows arch.
7565          */
7566
7567         if (!devmode)
7568         {
7569                 set_driver_init(printer, 2);
7570         }
7571         else
7572         {
7573                 /* A valid devmode was included, convert and link it
7574                 */
7575                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7576
7577                 if (!convert_devicemode(printer->info_2->printername, devmode,
7578                                         &printer->info_2->devmode)) {
7579                         return  WERR_NOMEM;
7580                 }
7581         }
7582
7583         /* write the ASCII on disk */
7584         err = mod_a_printer(printer, 2);
7585         if (!W_ERROR_IS_OK(err)) {
7586                 free_a_printer(&printer,2);
7587                 return err;
7588         }
7589
7590         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7591                 /* Handle open failed - remove addition. */
7592                 del_a_printer(printer->info_2->sharename);
7593                 free_a_printer(&printer,2);
7594                 ZERO_STRUCTP(handle);
7595                 return WERR_ACCESS_DENIED;
7596         }
7597
7598         update_c_setprinter(false);
7599         free_a_printer(&printer,2);
7600
7601         return WERR_OK;
7602 }
7603
7604 /****************************************************************
7605  _spoolss_AddPrinterEx
7606 ****************************************************************/
7607
7608 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7609                              struct spoolss_AddPrinterEx *r)
7610 {
7611         switch (r->in.info_ctr->level) {
7612         case 1:
7613                 /* we don't handle yet */
7614                 /* but I know what to do ... */
7615                 return WERR_UNKNOWN_LEVEL;
7616         case 2:
7617                 return spoolss_addprinterex_level_2(p, r->in.server,
7618                                                     r->in.info_ctr,
7619                                                     r->in.devmode_ctr->devmode,
7620                                                     r->in.secdesc_ctr->sd,
7621                                                     r->in.userlevel_ctr,
7622                                                     r->out.handle);
7623         default:
7624                 return WERR_UNKNOWN_LEVEL;
7625         }
7626 }
7627
7628 /****************************************************************
7629  _spoolss_AddPrinterDriver
7630 ****************************************************************/
7631
7632 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7633                                  struct spoolss_AddPrinterDriver *r)
7634 {
7635         uint32_t level = r->in.info_ctr->level;
7636         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7637         WERROR err = WERR_OK;
7638         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7639         const char *driver_name = NULL;
7640         uint32_t version;
7641         const char *fn;
7642
7643         switch (p->hdr_req.opnum) {
7644                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7645                         fn = "_spoolss_AddPrinterDriver";
7646                         break;
7647                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7648                         fn = "_spoolss_AddPrinterDriverEx";
7649                         break;
7650                 default:
7651                         return WERR_INVALID_PARAM;
7652         }
7653
7654
7655         /* FIXME */
7656         if (level != 3 && level != 6) {
7657                 /* Clever hack from Martin Zielinski <mz@seh.de>
7658                  * to allow downgrade from level 8 (Vista).
7659                  */
7660                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7661                 return WERR_UNKNOWN_LEVEL;
7662         }
7663
7664         ZERO_STRUCT(driver);
7665
7666         if (!convert_printer_driver_info(info, &driver, level)) {
7667                 err = WERR_NOMEM;
7668                 goto done;
7669         }
7670
7671         DEBUG(5,("Cleaning driver's information\n"));
7672         err = clean_up_driver_struct(p, driver, level);
7673         if (!W_ERROR_IS_OK(err))
7674                 goto done;
7675
7676         DEBUG(5,("Moving driver to final destination\n"));
7677         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7678                                                               &err)) ) {
7679                 goto done;
7680         }
7681
7682         if (add_a_printer_driver(driver, level)!=0) {
7683                 err = WERR_ACCESS_DENIED;
7684                 goto done;
7685         }
7686
7687         switch(level) {
7688         case 3:
7689                 driver_name = driver.info_3->name ? driver.info_3->name : "";
7690                 break;
7691         case 6:
7692                 driver_name = driver.info_6->name ? driver.info_6->name : "";
7693                 break;
7694         }
7695
7696         /*
7697          * I think this is where he DrvUpgradePrinter() hook would be
7698          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7699          * server.  Right now, we just need to send ourselves a message
7700          * to update each printer bound to this driver.   --jerry
7701          */
7702
7703         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7704                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7705                         fn, driver_name));
7706         }
7707
7708         /*
7709          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7710          * decide if the driver init data should be deleted. The rules are:
7711          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7712          *  2) delete init data only if there is no 2k/Xp driver
7713          *  3) always delete init data
7714          * The generalized rule is always use init data from the highest order driver.
7715          * It is necessary to follow the driver install by an initialization step to
7716          * finish off this process.
7717         */
7718         if (level == 3)
7719                 version = driver.info_3->cversion;
7720         else if (level == 6)
7721                 version = driver.info_6->version;
7722         else
7723                 version = -1;
7724         switch (version) {
7725                 /*
7726                  * 9x printer driver - never delete init data
7727                 */
7728                 case 0:
7729                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7730                                 fn, driver_name));
7731                         break;
7732
7733                 /*
7734                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7735                  * there is no 2k/Xp driver init data for this driver name.
7736                 */
7737                 case 2:
7738                 {
7739                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7740
7741                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7742                                 /*
7743                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7744                                 */
7745                                 if (!del_driver_init(driver_name))
7746                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7747                                                 fn, driver_name));
7748                         } else {
7749                                 /*
7750                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7751                                 */
7752                                 free_a_printer_driver(driver1,3);
7753                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7754                                         fn, driver_name));
7755                         }
7756                 }
7757                 break;
7758
7759                 /*
7760                  * 2k or Xp printer driver - always delete init data
7761                 */
7762                 case 3:
7763                         if (!del_driver_init(driver_name))
7764                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7765                                         fn, driver_name));
7766                         break;
7767
7768                 default:
7769                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7770                         break;
7771         }
7772
7773
7774 done:
7775         free_a_printer_driver(driver, level);
7776         return err;
7777 }
7778
7779 /****************************************************************
7780  _spoolss_AddPrinterDriverEx
7781 ****************************************************************/
7782
7783 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7784                                    struct spoolss_AddPrinterDriverEx *r)
7785 {
7786         struct spoolss_AddPrinterDriver a;
7787
7788         /*
7789          * we only support the semantics of AddPrinterDriver()
7790          * i.e. only copy files that are newer than existing ones
7791          */
7792
7793         if (r->in.flags != APD_COPY_NEW_FILES) {
7794                 return WERR_ACCESS_DENIED;
7795         }
7796
7797         a.in.servername         = r->in.servername;
7798         a.in.info_ctr           = r->in.info_ctr;
7799
7800         return _spoolss_AddPrinterDriver(p, &a);
7801 }
7802
7803 /****************************************************************************
7804 ****************************************************************************/
7805
7806 struct _spoolss_paths {
7807         int type;
7808         const char *share;
7809         const char *dir;
7810 };
7811
7812 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7813
7814 static const struct _spoolss_paths spoolss_paths[]= {
7815         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7816         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7817 };
7818
7819 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7820                                           const char *servername,
7821                                           const char *environment,
7822                                           int component,
7823                                           char **path)
7824 {
7825         const char *pservername = NULL;
7826         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7827         const char *short_archi;
7828
7829         *path = NULL;
7830
7831         /* environment may be empty */
7832         if (environment && strlen(environment)) {
7833                 long_archi = environment;
7834         }
7835
7836         /* servername may be empty */
7837         if (servername && strlen(servername)) {
7838                 pservername = canon_servername(servername);
7839
7840                 if (!is_myname_or_ipaddr(pservername)) {
7841                         return WERR_INVALID_PARAM;
7842                 }
7843         }
7844
7845         if (!(short_archi = get_short_archi(long_archi))) {
7846                 return WERR_INVALID_ENVIRONMENT;
7847         }
7848
7849         switch (component) {
7850         case SPOOLSS_PRTPROCS_PATH:
7851         case SPOOLSS_DRIVER_PATH:
7852                 if (pservername) {
7853                         *path = talloc_asprintf(mem_ctx,
7854                                         "\\\\%s\\%s\\%s",
7855                                         pservername,
7856                                         spoolss_paths[component].share,
7857                                         short_archi);
7858                 } else {
7859                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7860                                         SPOOLSS_DEFAULT_SERVER_PATH,
7861                                         spoolss_paths[component].dir,
7862                                         short_archi);
7863                 }
7864                 break;
7865         default:
7866                 return WERR_INVALID_PARAM;
7867         }
7868
7869         if (!*path) {
7870                 return WERR_NOMEM;
7871         }
7872
7873         return WERR_OK;
7874 }
7875
7876 /****************************************************************************
7877 ****************************************************************************/
7878
7879 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7880                                           const char *servername,
7881                                           const char *environment,
7882                                           struct spoolss_DriverDirectoryInfo1 *r)
7883 {
7884         WERROR werr;
7885         char *path = NULL;
7886
7887         werr = compose_spoolss_server_path(mem_ctx,
7888                                            servername,
7889                                            environment,
7890                                            SPOOLSS_DRIVER_PATH,
7891                                            &path);
7892         if (!W_ERROR_IS_OK(werr)) {
7893                 return werr;
7894         }
7895
7896         DEBUG(4,("printer driver directory: [%s]\n", path));
7897
7898         r->directory_name = path;
7899
7900         return WERR_OK;
7901 }
7902
7903 /****************************************************************
7904  _spoolss_GetPrinterDriverDirectory
7905 ****************************************************************/
7906
7907 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7908                                           struct spoolss_GetPrinterDriverDirectory *r)
7909 {
7910         WERROR werror;
7911
7912         /* that's an [in out] buffer */
7913
7914         if (!r->in.buffer && (r->in.offered != 0)) {
7915                 return WERR_INVALID_PARAM;
7916         }
7917
7918         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7919                 r->in.level));
7920
7921         *r->out.needed = 0;
7922
7923         /* r->in.level is ignored */
7924
7925         werror = getprinterdriverdir_level_1(p->mem_ctx,
7926                                              r->in.server,
7927                                              r->in.environment,
7928                                              &r->out.info->info1);
7929         if (!W_ERROR_IS_OK(werror)) {
7930                 TALLOC_FREE(r->out.info);
7931                 return werror;
7932         }
7933
7934         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7935                                                r->out.info, r->in.level);
7936         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7937
7938         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7939 }
7940
7941 /****************************************************************
7942  _spoolss_EnumPrinterData
7943 ****************************************************************/
7944
7945 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7946                                 struct spoolss_EnumPrinterData *r)
7947 {
7948         NT_PRINTER_INFO_LEVEL *printer = NULL;
7949         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7950         int             snum;
7951         WERROR          result;
7952         REGISTRY_VALUE  *val = NULL;
7953         NT_PRINTER_DATA *p_data;
7954         int             i, key_index, num_values;
7955         int             name_length;
7956
7957         *r->out.value_needed    = 0;
7958         *r->out.type            = REG_NONE;
7959         *r->out.data_needed     = 0;
7960
7961         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7962
7963         if (!Printer) {
7964                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7965                         OUR_HANDLE(r->in.handle)));
7966                 return WERR_BADFID;
7967         }
7968
7969         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7970                 return WERR_BADFID;
7971         }
7972
7973         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7974         if (!W_ERROR_IS_OK(result)) {
7975                 return result;
7976         }
7977
7978         p_data = printer->info_2->data;
7979         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7980
7981         result = WERR_OK;
7982
7983         /*
7984          * The NT machine wants to know the biggest size of value and data
7985          *
7986          * cf: MSDN EnumPrinterData remark section
7987          */
7988
7989         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7990
7991                 uint32_t biggest_valuesize = 0;
7992                 uint32_t biggest_datasize = 0;
7993
7994                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7995
7996                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7997
7998                 for ( i=0; i<num_values; i++ )
7999                 {
8000                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8001
8002                         name_length = strlen(val->valuename);
8003                         if ( strlen(val->valuename) > biggest_valuesize )
8004                                 biggest_valuesize = name_length;
8005
8006                         if ( val->size > biggest_datasize )
8007                                 biggest_datasize = val->size;
8008
8009                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8010                                 biggest_datasize));
8011                 }
8012
8013                 /* the value is an UNICODE string but real_value_size is the length
8014                    in bytes including the trailing 0 */
8015
8016                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8017                 *r->out.data_needed  = biggest_datasize;
8018
8019                 DEBUG(6,("final values: [%d], [%d]\n",
8020                         *r->out.value_needed, *r->out.data_needed));
8021
8022                 goto done;
8023         }
8024
8025         /*
8026          * the value len is wrong in NT sp3
8027          * that's the number of bytes not the number of unicode chars
8028          */
8029
8030         if (key_index != -1) {
8031                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8032                                                 r->in.enum_index);
8033         }
8034
8035         if (!val) {
8036
8037                 /* out_value should default to "" or else NT4 has
8038                    problems unmarshalling the response */
8039
8040                 if (r->in.value_offered) {
8041                         *r->out.value_needed = 1;
8042                         r->out.value_name = talloc_strdup(r, "");
8043                         if (!r->out.value_name) {
8044                                 result = WERR_NOMEM;
8045                                 goto done;
8046                         }
8047                 } else {
8048                         r->out.value_name = NULL;
8049                         *r->out.value_needed = 0;
8050                 }
8051
8052                 /* the data is counted in bytes */
8053
8054                 *r->out.data_needed = r->in.data_offered;
8055
8056                 result = WERR_NO_MORE_ITEMS;
8057         } else {
8058                 /*
8059                  * the value is:
8060                  * - counted in bytes in the request
8061                  * - counted in UNICODE chars in the max reply
8062                  * - counted in bytes in the real size
8063                  *
8064                  * take a pause *before* coding not *during* coding
8065                  */
8066
8067                 /* name */
8068                 if (r->in.value_offered) {
8069                         r->out.value_name = talloc_strdup(r, regval_name(val));
8070                         if (!r->out.value_name) {
8071                                 result = WERR_NOMEM;
8072                                 goto done;
8073                         }
8074                         *r->out.value_needed = strlen_m_term(regval_name(val)) * 2;
8075                 } else {
8076                         r->out.value_name = NULL;
8077                         *r->out.value_needed = 0;
8078                 }
8079
8080                 /* type */
8081
8082                 *r->out.type = regval_type(val);
8083
8084                 /* data - counted in bytes */
8085
8086                 /*
8087                  * See the section "Dynamically Typed Query Parameters"
8088                  * in MS-RPRN.
8089                  */
8090
8091                 if (r->out.data && regval_data_p(val) &&
8092                                 regval_size(val) && r->in.data_offered) {
8093                         memcpy(r->out.data, regval_data_p(val),
8094                                 MIN(regval_size(val),r->in.data_offered));
8095                 }
8096
8097                 *r->out.data_needed = regval_size(val);
8098         }
8099
8100 done:
8101         free_a_printer(&printer, 2);
8102         return result;
8103 }
8104
8105 /****************************************************************
8106  _spoolss_SetPrinterData
8107 ****************************************************************/
8108
8109 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8110                                struct spoolss_SetPrinterData *r)
8111 {
8112         struct spoolss_SetPrinterDataEx r2;
8113
8114         r2.in.handle            = r->in.handle;
8115         r2.in.key_name          = "PrinterDriverData";
8116         r2.in.value_name        = r->in.value_name;
8117         r2.in.type              = r->in.type;
8118         r2.in.data              = r->in.data;
8119         r2.in.offered           = r->in.offered;
8120
8121         return _spoolss_SetPrinterDataEx(p, &r2);
8122 }
8123
8124 /****************************************************************
8125  _spoolss_ResetPrinter
8126 ****************************************************************/
8127
8128 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8129                              struct spoolss_ResetPrinter *r)
8130 {
8131         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8132         int             snum;
8133
8134         DEBUG(5,("_spoolss_ResetPrinter\n"));
8135
8136         /*
8137          * All we do is to check to see if the handle and queue is valid.
8138          * This call really doesn't mean anything to us because we only
8139          * support RAW printing.   --jerry
8140          */
8141
8142         if (!Printer) {
8143                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8144                         OUR_HANDLE(r->in.handle)));
8145                 return WERR_BADFID;
8146         }
8147
8148         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8149                 return WERR_BADFID;
8150
8151
8152         /* blindly return success */
8153         return WERR_OK;
8154 }
8155
8156 /****************************************************************
8157  _spoolss_DeletePrinterData
8158 ****************************************************************/
8159
8160 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8161                                   struct spoolss_DeletePrinterData *r)
8162 {
8163         struct spoolss_DeletePrinterDataEx r2;
8164
8165         r2.in.handle            = r->in.handle;
8166         r2.in.key_name          = "PrinterDriverData";
8167         r2.in.value_name        = r->in.value_name;
8168
8169         return _spoolss_DeletePrinterDataEx(p, &r2);
8170 }
8171
8172 /****************************************************************
8173  _spoolss_AddForm
8174 ****************************************************************/
8175
8176 WERROR _spoolss_AddForm(pipes_struct *p,
8177                         struct spoolss_AddForm *r)
8178 {
8179         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8180         nt_forms_struct tmpForm;
8181         int snum = -1;
8182         WERROR status = WERR_OK;
8183         NT_PRINTER_INFO_LEVEL *printer = NULL;
8184         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8185
8186         int count=0;
8187         nt_forms_struct *list=NULL;
8188         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8189
8190         DEBUG(5,("_spoolss_AddForm\n"));
8191
8192         if (!Printer) {
8193                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8194                         OUR_HANDLE(r->in.handle)));
8195                 return WERR_BADFID;
8196         }
8197
8198
8199         /* forms can be added on printer of on the print server handle */
8200
8201         if ( Printer->printer_type == SPLHND_PRINTER )
8202         {
8203                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8204                         return WERR_BADFID;
8205
8206                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8207                 if (!W_ERROR_IS_OK(status))
8208                         goto done;
8209         }
8210
8211         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8212            and not a printer admin, then fail */
8213
8214         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8215              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8216              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8217                                           NULL, NULL,
8218                                           p->server_info->ptok,
8219                                           lp_printer_admin(snum))) {
8220                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8221                 return WERR_ACCESS_DENIED;
8222         }
8223
8224         /* can't add if builtin */
8225
8226         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8227                 status = WERR_FILE_EXISTS;
8228                 goto done;
8229         }
8230
8231         count = get_ntforms(&list);
8232
8233         if(!add_a_form(&list, form, &count)) {
8234                 status =  WERR_NOMEM;
8235                 goto done;
8236         }
8237
8238         become_root();
8239         write_ntforms(&list, count);
8240         unbecome_root();
8241
8242         /*
8243          * ChangeID must always be set if this is a printer
8244          */
8245
8246         if ( Printer->printer_type == SPLHND_PRINTER )
8247                 status = mod_a_printer(printer, 2);
8248
8249 done:
8250         if ( printer )
8251                 free_a_printer(&printer, 2);
8252         SAFE_FREE(list);
8253
8254         return status;
8255 }
8256
8257 /****************************************************************
8258  _spoolss_DeleteForm
8259 ****************************************************************/
8260
8261 WERROR _spoolss_DeleteForm(pipes_struct *p,
8262                            struct spoolss_DeleteForm *r)
8263 {
8264         const char *form_name = r->in.form_name;
8265         nt_forms_struct tmpForm;
8266         int count=0;
8267         nt_forms_struct *list=NULL;
8268         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8269         int snum = -1;
8270         WERROR status = WERR_OK;
8271         NT_PRINTER_INFO_LEVEL *printer = NULL;
8272         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8273         bool ret = false;
8274
8275         DEBUG(5,("_spoolss_DeleteForm\n"));
8276
8277         if (!Printer) {
8278                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8279                         OUR_HANDLE(r->in.handle)));
8280                 return WERR_BADFID;
8281         }
8282
8283         /* forms can be deleted on printer of on the print server handle */
8284
8285         if ( Printer->printer_type == SPLHND_PRINTER )
8286         {
8287                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8288                         return WERR_BADFID;
8289
8290                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8291                 if (!W_ERROR_IS_OK(status))
8292                         goto done;
8293         }
8294
8295         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8296              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8297              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8298                                           NULL, NULL,
8299                                           p->server_info->ptok,
8300                                           lp_printer_admin(snum))) {
8301                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8302                 return WERR_ACCESS_DENIED;
8303         }
8304
8305
8306         /* can't delete if builtin */
8307
8308         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8309                 status = WERR_INVALID_PARAM;
8310                 goto done;
8311         }
8312
8313         count = get_ntforms(&list);
8314
8315         become_root();
8316         ret = delete_a_form(&list, form_name, &count, &status);
8317         unbecome_root();
8318         if (ret == false) {
8319                 goto done;
8320         }
8321
8322         /*
8323          * ChangeID must always be set if this is a printer
8324          */
8325
8326         if ( Printer->printer_type == SPLHND_PRINTER )
8327                 status = mod_a_printer(printer, 2);
8328
8329 done:
8330         if ( printer )
8331                 free_a_printer(&printer, 2);
8332         SAFE_FREE(list);
8333
8334         return status;
8335 }
8336
8337 /****************************************************************
8338  _spoolss_SetForm
8339 ****************************************************************/
8340
8341 WERROR _spoolss_SetForm(pipes_struct *p,
8342                         struct spoolss_SetForm *r)
8343 {
8344         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8345         nt_forms_struct tmpForm;
8346         int snum = -1;
8347         WERROR status = WERR_OK;
8348         NT_PRINTER_INFO_LEVEL *printer = NULL;
8349         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8350
8351         int count=0;
8352         nt_forms_struct *list=NULL;
8353         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8354
8355         DEBUG(5,("_spoolss_SetForm\n"));
8356
8357         if (!Printer) {
8358                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8359                         OUR_HANDLE(r->in.handle)));
8360                 return WERR_BADFID;
8361         }
8362
8363         /* forms can be modified on printer of on the print server handle */
8364
8365         if ( Printer->printer_type == SPLHND_PRINTER )
8366         {
8367                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8368                         return WERR_BADFID;
8369
8370                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8371                 if (!W_ERROR_IS_OK(status))
8372                         goto done;
8373         }
8374
8375         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8376            and not a printer admin, then fail */
8377
8378         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8379              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8380              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8381                                           NULL, NULL,
8382                                           p->server_info->ptok,
8383                                           lp_printer_admin(snum))) {
8384                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8385                 return WERR_ACCESS_DENIED;
8386         }
8387
8388         /* can't set if builtin */
8389         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8390                 status = WERR_INVALID_PARAM;
8391                 goto done;
8392         }
8393
8394         count = get_ntforms(&list);
8395         update_a_form(&list, form, count);
8396         become_root();
8397         write_ntforms(&list, count);
8398         unbecome_root();
8399
8400         /*
8401          * ChangeID must always be set if this is a printer
8402          */
8403
8404         if ( Printer->printer_type == SPLHND_PRINTER )
8405                 status = mod_a_printer(printer, 2);
8406
8407
8408 done:
8409         if ( printer )
8410                 free_a_printer(&printer, 2);
8411         SAFE_FREE(list);
8412
8413         return status;
8414 }
8415
8416 /****************************************************************************
8417  fill_print_processor1
8418 ****************************************************************************/
8419
8420 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8421                                     struct spoolss_PrintProcessorInfo1 *r,
8422                                     const char *print_processor_name)
8423 {
8424         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8425         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8426
8427         return WERR_OK;
8428 }
8429
8430 /****************************************************************************
8431  enumprintprocessors level 1.
8432 ****************************************************************************/
8433
8434 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8435                                           union spoolss_PrintProcessorInfo **info_p,
8436                                           uint32_t *count)
8437 {
8438         union spoolss_PrintProcessorInfo *info;
8439         WERROR result;
8440
8441         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8442         W_ERROR_HAVE_NO_MEMORY(info);
8443
8444         *count = 1;
8445
8446         result = fill_print_processor1(info, &info[0].info1, "winprint");
8447         if (!W_ERROR_IS_OK(result)) {
8448                 goto out;
8449         }
8450
8451  out:
8452         if (!W_ERROR_IS_OK(result)) {
8453                 TALLOC_FREE(info);
8454                 *count = 0;
8455                 return result;
8456         }
8457
8458         *info_p = info;
8459
8460         return WERR_OK;
8461 }
8462
8463 /****************************************************************
8464  _spoolss_EnumPrintProcessors
8465 ****************************************************************/
8466
8467 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8468                                     struct spoolss_EnumPrintProcessors *r)
8469 {
8470         WERROR result;
8471
8472         /* that's an [in out] buffer */
8473
8474         if (!r->in.buffer && (r->in.offered != 0)) {
8475                 return WERR_INVALID_PARAM;
8476         }
8477
8478         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8479
8480         /*
8481          * Enumerate the print processors ...
8482          *
8483          * Just reply with "winprint", to keep NT happy
8484          * and I can use my nice printer checker.
8485          */
8486
8487         *r->out.count = 0;
8488         *r->out.needed = 0;
8489         *r->out.info = NULL;
8490
8491         switch (r->in.level) {
8492         case 1:
8493                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8494                                                      r->out.count);
8495                 break;
8496         default:
8497                 return WERR_UNKNOWN_LEVEL;
8498         }
8499
8500         if (!W_ERROR_IS_OK(result)) {
8501                 return result;
8502         }
8503
8504         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8505                                                      spoolss_EnumPrintProcessors, NULL,
8506                                                      *r->out.info, r->in.level,
8507                                                      *r->out.count);
8508         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8509         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8510
8511         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8512 }
8513
8514 /****************************************************************************
8515  fill_printprocdatatype1
8516 ****************************************************************************/
8517
8518 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8519                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8520                                       const char *name_array)
8521 {
8522         r->name_array = talloc_strdup(mem_ctx, name_array);
8523         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8524
8525         return WERR_OK;
8526 }
8527
8528 /****************************************************************************
8529  enumprintprocdatatypes level 1.
8530 ****************************************************************************/
8531
8532 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8533                                              union spoolss_PrintProcDataTypesInfo **info_p,
8534                                              uint32_t *count)
8535 {
8536         WERROR result;
8537         union spoolss_PrintProcDataTypesInfo *info;
8538
8539         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8540         W_ERROR_HAVE_NO_MEMORY(info);
8541
8542         *count = 1;
8543
8544         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8545         if (!W_ERROR_IS_OK(result)) {
8546                 goto out;
8547         }
8548
8549  out:
8550         if (!W_ERROR_IS_OK(result)) {
8551                 TALLOC_FREE(info);
8552                 *count = 0;
8553                 return result;
8554         }
8555
8556         *info_p = info;
8557
8558         return WERR_OK;
8559 }
8560
8561 /****************************************************************
8562  _spoolss_EnumPrintProcDataTypes
8563 ****************************************************************/
8564
8565 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8566                                        struct spoolss_EnumPrintProcDataTypes *r)
8567 {
8568         WERROR result;
8569
8570         /* that's an [in out] buffer */
8571
8572         if (!r->in.buffer && (r->in.offered != 0)) {
8573                 return WERR_INVALID_PARAM;
8574         }
8575
8576         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8577
8578         *r->out.count = 0;
8579         *r->out.needed = 0;
8580         *r->out.info = NULL;
8581
8582         switch (r->in.level) {
8583         case 1:
8584                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8585                                                         r->out.count);
8586                 break;
8587         default:
8588                 return WERR_UNKNOWN_LEVEL;
8589         }
8590
8591         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8592                                                      spoolss_EnumPrintProcDataTypes, NULL,
8593                                                      *r->out.info, r->in.level,
8594                                                      *r->out.count);
8595         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8596         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8597
8598         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8599 }
8600
8601 /****************************************************************************
8602  fill_monitor_1
8603 ****************************************************************************/
8604
8605 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8606                              struct spoolss_MonitorInfo1 *r,
8607                              const char *monitor_name)
8608 {
8609         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8610         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8611
8612         return WERR_OK;
8613 }
8614
8615 /****************************************************************************
8616  fill_monitor_2
8617 ****************************************************************************/
8618
8619 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8620                              struct spoolss_MonitorInfo2 *r,
8621                              const char *monitor_name,
8622                              const char *environment,
8623                              const char *dll_name)
8624 {
8625         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8626         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8627         r->environment                  = talloc_strdup(mem_ctx, environment);
8628         W_ERROR_HAVE_NO_MEMORY(r->environment);
8629         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8630         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8631
8632         return WERR_OK;
8633 }
8634
8635 /****************************************************************************
8636  enumprintmonitors level 1.
8637 ****************************************************************************/
8638
8639 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8640                                         union spoolss_MonitorInfo **info_p,
8641                                         uint32_t *count)
8642 {
8643         union spoolss_MonitorInfo *info;
8644         WERROR result = WERR_OK;
8645
8646         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8647         W_ERROR_HAVE_NO_MEMORY(info);
8648
8649         *count = 2;
8650
8651         result = fill_monitor_1(info, &info[0].info1,
8652                                 SPL_LOCAL_PORT);
8653         if (!W_ERROR_IS_OK(result)) {
8654                 goto out;
8655         }
8656
8657         result = fill_monitor_1(info, &info[1].info1,
8658                                 SPL_TCPIP_PORT);
8659         if (!W_ERROR_IS_OK(result)) {
8660                 goto out;
8661         }
8662
8663 out:
8664         if (!W_ERROR_IS_OK(result)) {
8665                 TALLOC_FREE(info);
8666                 *count = 0;
8667                 return result;
8668         }
8669
8670         *info_p = info;
8671
8672         return WERR_OK;
8673 }
8674
8675 /****************************************************************************
8676  enumprintmonitors level 2.
8677 ****************************************************************************/
8678
8679 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8680                                         union spoolss_MonitorInfo **info_p,
8681                                         uint32_t *count)
8682 {
8683         union spoolss_MonitorInfo *info;
8684         WERROR result = WERR_OK;
8685
8686         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8687         W_ERROR_HAVE_NO_MEMORY(info);
8688
8689         *count = 2;
8690
8691         result = fill_monitor_2(info, &info[0].info2,
8692                                 SPL_LOCAL_PORT,
8693                                 "Windows NT X86", /* FIXME */
8694                                 "localmon.dll");
8695         if (!W_ERROR_IS_OK(result)) {
8696                 goto out;
8697         }
8698
8699         result = fill_monitor_2(info, &info[1].info2,
8700                                 SPL_TCPIP_PORT,
8701                                 "Windows NT X86", /* FIXME */
8702                                 "tcpmon.dll");
8703         if (!W_ERROR_IS_OK(result)) {
8704                 goto out;
8705         }
8706
8707 out:
8708         if (!W_ERROR_IS_OK(result)) {
8709                 TALLOC_FREE(info);
8710                 *count = 0;
8711                 return result;
8712         }
8713
8714         *info_p = info;
8715
8716         return WERR_OK;
8717 }
8718
8719 /****************************************************************
8720  _spoolss_EnumMonitors
8721 ****************************************************************/
8722
8723 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8724                              struct spoolss_EnumMonitors *r)
8725 {
8726         WERROR result;
8727
8728         /* that's an [in out] buffer */
8729
8730         if (!r->in.buffer && (r->in.offered != 0)) {
8731                 return WERR_INVALID_PARAM;
8732         }
8733
8734         DEBUG(5,("_spoolss_EnumMonitors\n"));
8735
8736         /*
8737          * Enumerate the print monitors ...
8738          *
8739          * Just reply with "Local Port", to keep NT happy
8740          * and I can use my nice printer checker.
8741          */
8742
8743         *r->out.count = 0;
8744         *r->out.needed = 0;
8745         *r->out.info = NULL;
8746
8747         switch (r->in.level) {
8748         case 1:
8749                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8750                                                    r->out.count);
8751                 break;
8752         case 2:
8753                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8754                                                    r->out.count);
8755                 break;
8756         default:
8757                 return WERR_UNKNOWN_LEVEL;
8758         }
8759
8760         if (!W_ERROR_IS_OK(result)) {
8761                 return result;
8762         }
8763
8764         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8765                                                      spoolss_EnumMonitors, NULL,
8766                                                      *r->out.info, r->in.level,
8767                                                      *r->out.count);
8768         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8769         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8770
8771         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8772 }
8773
8774 /****************************************************************************
8775 ****************************************************************************/
8776
8777 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8778                              const print_queue_struct *queue,
8779                              int count, int snum,
8780                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8781                              uint32_t jobid,
8782                              struct spoolss_JobInfo1 *r)
8783 {
8784         int i = 0;
8785         bool found = false;
8786
8787         for (i=0; i<count && found == false; i++) {
8788                 if (queue[i].job == (int)jobid) {
8789                         found = true;
8790                 }
8791         }
8792
8793         if (found == false) {
8794                 /* NT treats not found as bad param... yet another bad choice */
8795                 return WERR_INVALID_PARAM;
8796         }
8797
8798         return fill_job_info1(mem_ctx,
8799                               r,
8800                               &queue[i-1],
8801                               i,
8802                               snum,
8803                               ntprinter);
8804 }
8805
8806 /****************************************************************************
8807 ****************************************************************************/
8808
8809 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8810                              const print_queue_struct *queue,
8811                              int count, int snum,
8812                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8813                              uint32_t jobid,
8814                              struct spoolss_JobInfo2 *r)
8815 {
8816         int i = 0;
8817         bool found = false;
8818         struct spoolss_DeviceMode *devmode;
8819         NT_DEVICEMODE *nt_devmode;
8820         WERROR result;
8821
8822         for (i=0; i<count && found == false; i++) {
8823                 if (queue[i].job == (int)jobid) {
8824                         found = true;
8825                 }
8826         }
8827
8828         if (found == false) {
8829                 /* NT treats not found as bad param... yet another bad
8830                    choice */
8831                 return WERR_INVALID_PARAM;
8832         }
8833
8834         /*
8835          * if the print job does not have a DEVMODE associated with it,
8836          * just use the one for the printer. A NULL devicemode is not
8837          *  a failure condition
8838          */
8839
8840         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8841         if (nt_devmode) {
8842                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8843                 W_ERROR_HAVE_NO_MEMORY(devmode);
8844                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8845                 if (!W_ERROR_IS_OK(result)) {
8846                         return result;
8847                 }
8848         } else {
8849                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8850                 W_ERROR_HAVE_NO_MEMORY(devmode);
8851         }
8852
8853         return fill_job_info2(mem_ctx,
8854                               r,
8855                               &queue[i-1],
8856                               i,
8857                               snum,
8858                               ntprinter,
8859                               devmode);
8860 }
8861
8862 /****************************************************************
8863  _spoolss_GetJob
8864 ****************************************************************/
8865
8866 WERROR _spoolss_GetJob(pipes_struct *p,
8867                        struct spoolss_GetJob *r)
8868 {
8869         WERROR result = WERR_OK;
8870         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8871         int snum;
8872         int count;
8873         print_queue_struct      *queue = NULL;
8874         print_status_struct prt_status;
8875
8876         /* that's an [in out] buffer */
8877
8878         if (!r->in.buffer && (r->in.offered != 0)) {
8879                 return WERR_INVALID_PARAM;
8880         }
8881
8882         DEBUG(5,("_spoolss_GetJob\n"));
8883
8884         *r->out.needed = 0;
8885
8886         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8887                 return WERR_BADFID;
8888         }
8889
8890         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8891         if (!W_ERROR_IS_OK(result)) {
8892                 return result;
8893         }
8894
8895         count = print_queue_status(snum, &queue, &prt_status);
8896
8897         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8898                      count, prt_status.status, prt_status.message));
8899
8900         switch (r->in.level) {
8901         case 1:
8902                 result = getjob_level_1(p->mem_ctx,
8903                                         queue, count, snum, ntprinter,
8904                                         r->in.job_id, &r->out.info->info1);
8905                 break;
8906         case 2:
8907                 result = getjob_level_2(p->mem_ctx,
8908                                         queue, count, snum, ntprinter,
8909                                         r->in.job_id, &r->out.info->info2);
8910                 break;
8911         default:
8912                 result = WERR_UNKNOWN_LEVEL;
8913                 break;
8914         }
8915
8916         SAFE_FREE(queue);
8917         free_a_printer(&ntprinter, 2);
8918
8919         if (!W_ERROR_IS_OK(result)) {
8920                 TALLOC_FREE(r->out.info);
8921                 return result;
8922         }
8923
8924         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8925                                                r->out.info, r->in.level);
8926         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8927
8928         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8929 }
8930
8931 /****************************************************************
8932  _spoolss_GetPrinterDataEx
8933 ****************************************************************/
8934
8935 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8936                                  struct spoolss_GetPrinterDataEx *r)
8937 {
8938
8939         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8940         REGISTRY_VALUE          *val = NULL;
8941         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8942         int                     snum = 0;
8943         WERROR result = WERR_OK;
8944         DATA_BLOB blob;
8945
8946         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8947
8948         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8949                 r->in.key_name, r->in.value_name));
8950
8951         /* in case of problem, return some default values */
8952
8953         *r->out.needed  = 0;
8954         *r->out.type    = REG_NONE;
8955
8956         if (!Printer) {
8957                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8958                         OUR_HANDLE(r->in.handle)));
8959                 result = WERR_BADFID;
8960                 goto done;
8961         }
8962
8963         /* Is the handle to a printer or to the server? */
8964
8965         if (Printer->printer_type == SPLHND_SERVER) {
8966
8967                 union spoolss_PrinterData data;
8968
8969                 result = getprinterdata_printer_server(p->mem_ctx,
8970                                                        r->in.value_name,
8971                                                        r->out.type,
8972                                                        &data);
8973                 if (!W_ERROR_IS_OK(result)) {
8974                         goto done;
8975                 }
8976
8977                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8978                                                   *r->out.type, &data);
8979                 if (!W_ERROR_IS_OK(result)) {
8980                         goto done;
8981                 }
8982
8983                 *r->out.needed = blob.length;
8984
8985                 if (r->in.offered >= *r->out.needed) {
8986                         memcpy(r->out.data, blob.data, blob.length);
8987                 }
8988
8989                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8990         }
8991
8992         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8993                 result = WERR_BADFID;
8994                 goto done;
8995         }
8996
8997         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8998         if (!W_ERROR_IS_OK(result)) {
8999                 goto done;
9000         }
9001
9002         /* check to see if the keyname is valid */
9003         if (!strlen(r->in.key_name)) {
9004                 result = WERR_INVALID_PARAM;
9005                 goto done;
9006         }
9007
9008         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
9009
9010         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9011             strequal(r->in.value_name, "ChangeId")) {
9012                 *r->out.type = REG_DWORD;
9013                 *r->out.needed = 4;
9014                 if (r->in.offered >= *r->out.needed) {
9015                         SIVAL(r->out.data, 0, printer->info_2->changeid);
9016                         result = WERR_OK;
9017                 }
9018                 goto done;
9019         }
9020
9021         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9022                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9023                         "Invalid keyname [%s]\n", r->in.key_name ));
9024                 result = WERR_BADFILE;
9025                 goto done;
9026         }
9027
9028         val = get_printer_data(printer->info_2,
9029                                r->in.key_name, r->in.value_name);
9030         if (!val) {
9031                 result = WERR_BADFILE;
9032                 goto done;
9033         }
9034
9035         *r->out.needed = regval_size(val);
9036         *r->out.type = regval_type(val);
9037
9038         if (r->in.offered >= *r->out.needed) {
9039                 memcpy(r->out.data, regval_data_p(val), regval_size(val));
9040         }
9041  done:
9042         if (printer) {
9043                 free_a_printer(&printer, 2);
9044         }
9045
9046         if (!W_ERROR_IS_OK(result)) {
9047                 return result;
9048         }
9049
9050         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
9051         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9052
9053         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9054 }
9055
9056 /****************************************************************
9057  _spoolss_SetPrinterDataEx
9058 ****************************************************************/
9059
9060 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9061                                  struct spoolss_SetPrinterDataEx *r)
9062 {
9063         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9064         int                     snum = 0;
9065         WERROR                  result = WERR_OK;
9066         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9067         char                    *oid_string;
9068
9069         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9070
9071         /* From MSDN documentation of SetPrinterDataEx: pass request to
9072            SetPrinterData if key is "PrinterDriverData" */
9073
9074         if (!Printer) {
9075                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9076                         OUR_HANDLE(r->in.handle)));
9077                 return WERR_BADFID;
9078         }
9079
9080         if (Printer->printer_type == SPLHND_SERVER) {
9081                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9082                         "Not implemented for server handles yet\n"));
9083                 return WERR_INVALID_PARAM;
9084         }
9085
9086         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9087                 return WERR_BADFID;
9088         }
9089
9090         /*
9091          * Access check : NT returns "access denied" if you make a
9092          * SetPrinterData call without the necessary privildge.
9093          * we were originally returning OK if nothing changed
9094          * which made Win2k issue **a lot** of SetPrinterData
9095          * when connecting to a printer  --jerry
9096          */
9097
9098         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9099                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9100                         "change denied by handle access permissions\n"));
9101                 return WERR_ACCESS_DENIED;
9102         }
9103
9104         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9105         if (!W_ERROR_IS_OK(result)) {
9106                 return result;
9107         }
9108
9109         /* check for OID in valuename */
9110
9111         oid_string = strchr(r->in.value_name, ',');
9112         if (oid_string) {
9113                 *oid_string = '\0';
9114                 oid_string++;
9115         }
9116
9117         /*
9118          * When client side code sets a magic printer data key, detect it and save
9119          * the current printer data and the magic key's data (its the DEVMODE) for
9120          * future printer/driver initializations.
9121          */
9122         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
9123                 /* Set devmode and printer initialization info */
9124                 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
9125
9126                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
9127
9128                 goto done;
9129         }
9130
9131         /* save the registry data */
9132
9133         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9134                                     r->in.type, r->in.data, r->in.offered);
9135
9136         if (W_ERROR_IS_OK(result)) {
9137                 /* save the OID if one was specified */
9138                 if (oid_string) {
9139                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9140                                 r->in.key_name, SPOOL_OID_KEY);
9141                         if (!str) {
9142                                 result = WERR_NOMEM;
9143                                 goto done;
9144                         }
9145
9146                         /*
9147                          * I'm not checking the status here on purpose.  Don't know
9148                          * if this is right, but I'm returning the status from the
9149                          * previous set_printer_dataex() call.  I have no idea if
9150                          * this is right.    --jerry
9151                          */
9152
9153                         set_printer_dataex(printer, str, r->in.value_name,
9154                                            REG_SZ, (uint8_t *)oid_string,
9155                                            strlen(oid_string)+1);
9156                 }
9157
9158                 result = mod_a_printer(printer, 2);
9159         }
9160
9161  done:
9162         free_a_printer(&printer, 2);
9163
9164         return result;
9165 }
9166
9167 /****************************************************************
9168  _spoolss_DeletePrinterDataEx
9169 ****************************************************************/
9170
9171 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9172                                     struct spoolss_DeletePrinterDataEx *r)
9173 {
9174         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9175         int             snum=0;
9176         WERROR          status = WERR_OK;
9177         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9178
9179         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9180
9181         if (!Printer) {
9182                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9183                         "Invalid handle (%s:%u:%u).\n",
9184                         OUR_HANDLE(r->in.handle)));
9185                 return WERR_BADFID;
9186         }
9187
9188         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9189                 return WERR_BADFID;
9190
9191         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9192                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9193                         "printer properties change denied by handle\n"));
9194                 return WERR_ACCESS_DENIED;
9195         }
9196
9197         if (!r->in.value_name || !r->in.key_name) {
9198                 return WERR_NOMEM;
9199         }
9200
9201         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9202         if (!W_ERROR_IS_OK(status))
9203                 return status;
9204
9205         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9206
9207         if ( W_ERROR_IS_OK(status) )
9208                 mod_a_printer( printer, 2 );
9209
9210         free_a_printer(&printer, 2);
9211
9212         return status;
9213 }
9214
9215 /****************************************************************
9216  _spoolss_EnumPrinterKey
9217 ****************************************************************/
9218
9219 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9220                                struct spoolss_EnumPrinterKey *r)
9221 {
9222         fstring         *keynames = NULL;
9223         int             num_keys;
9224         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9225         NT_PRINTER_DATA *data;
9226         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9227         int             snum = 0;
9228         WERROR          result = WERR_BADFILE;
9229         int i;
9230         const char **array = NULL;
9231         DATA_BLOB blob;
9232
9233         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9234
9235         if (!Printer) {
9236                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9237                         OUR_HANDLE(r->in.handle)));
9238                 return WERR_BADFID;
9239         }
9240
9241         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9242                 return WERR_BADFID;
9243         }
9244
9245         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9246         if (!W_ERROR_IS_OK(result)) {
9247                 return result;
9248         }
9249
9250         /* get the list of subkey names */
9251
9252         data = printer->info_2->data;
9253
9254         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9255         if (num_keys == -1) {
9256                 result = WERR_BADFILE;
9257                 goto done;
9258         }
9259
9260         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9261         if (!array) {
9262                 result = WERR_NOMEM;
9263                 goto done;
9264         }
9265
9266         if (!num_keys) {
9267                 array[0] = talloc_strdup(array, "");
9268                 if (!array[0]) {
9269                         result = WERR_NOMEM;
9270                         goto done;
9271                 }
9272         }
9273
9274         for (i=0; i < num_keys; i++) {
9275
9276                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9277                         keynames[i]));
9278
9279                 array[i] = talloc_strdup(array, keynames[i]);
9280                 if (!array[i]) {
9281                         result = WERR_NOMEM;
9282                         goto done;
9283                 }
9284         }
9285
9286         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9287                 result = WERR_NOMEM;
9288                 goto done;
9289         }
9290
9291         *r->out._ndr_size = r->in.offered / 2;
9292         *r->out.needed = blob.length;
9293
9294         if (r->in.offered < *r->out.needed) {
9295                 result = WERR_MORE_DATA;
9296         } else {
9297                 result = WERR_OK;
9298                 r->out.key_buffer->string_array = array;
9299         }
9300
9301  done:
9302         if (!W_ERROR_IS_OK(result)) {
9303                 TALLOC_FREE(array);
9304                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9305                         *r->out.needed = 0;
9306                 }
9307         }
9308
9309         free_a_printer(&printer, 2);
9310         SAFE_FREE(keynames);
9311
9312         return result;
9313 }
9314
9315 /****************************************************************
9316  _spoolss_DeletePrinterKey
9317 ****************************************************************/
9318
9319 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9320                                  struct spoolss_DeletePrinterKey *r)
9321 {
9322         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9323         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9324         int                     snum=0;
9325         WERROR                  status;
9326
9327         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9328
9329         if (!Printer) {
9330                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9331                         OUR_HANDLE(r->in.handle)));
9332                 return WERR_BADFID;
9333         }
9334
9335         /* if keyname == NULL, return error */
9336
9337         if ( !r->in.key_name )
9338                 return WERR_INVALID_PARAM;
9339
9340         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9341                 return WERR_BADFID;
9342
9343         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9344                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9345                         "printer properties change denied by handle\n"));
9346                 return WERR_ACCESS_DENIED;
9347         }
9348
9349         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9350         if (!W_ERROR_IS_OK(status))
9351                 return status;
9352
9353         /* delete the key and all subneys */
9354
9355         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9356
9357         if ( W_ERROR_IS_OK(status) )
9358                 status = mod_a_printer(printer, 2);
9359
9360         free_a_printer( &printer, 2 );
9361
9362         return status;
9363 }
9364
9365 /****************************************************************
9366 ****************************************************************/
9367
9368 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9369                                                    REGISTRY_VALUE *v,
9370                                                    struct spoolss_PrinterEnumValues *r)
9371 {
9372         r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9373         W_ERROR_HAVE_NO_MEMORY(r->data);
9374
9375         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9376         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9377
9378         r->type         = regval_type(v);
9379         r->data_length  = regval_size(v);
9380
9381         if (r->data_length) {
9382                 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9383         }
9384
9385         return WERR_OK;
9386 }
9387
9388 /****************************************************************
9389  _spoolss_EnumPrinterDataEx
9390 ****************************************************************/
9391
9392 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9393                                   struct spoolss_EnumPrinterDataEx *r)
9394 {
9395         uint32_t        count = 0;
9396         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9397         struct spoolss_PrinterEnumValues *info = NULL;
9398         NT_PRINTER_DATA         *p_data;
9399         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9400         int             snum;
9401         WERROR          result;
9402         int             key_index;
9403         int             i;
9404
9405         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9406
9407         *r->out.count = 0;
9408         *r->out.needed = 0;
9409         *r->out.info = NULL;
9410
9411         if (!Printer) {
9412                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9413                         OUR_HANDLE(r->in.handle)));
9414                 return WERR_BADFID;
9415         }
9416
9417         /*
9418          * first check for a keyname of NULL or "".  Win2k seems to send
9419          * this a lot and we should send back WERR_INVALID_PARAM
9420          * no need to spend time looking up the printer in this case.
9421          * --jerry
9422          */
9423
9424         if (!strlen(r->in.key_name)) {
9425                 result = WERR_INVALID_PARAM;
9426                 goto done;
9427         }
9428
9429         /* get the printer off of disk */
9430
9431         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9432                 return WERR_BADFID;
9433         }
9434
9435         ZERO_STRUCT(printer);
9436         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9437         if (!W_ERROR_IS_OK(result)) {
9438                 return result;
9439         }
9440
9441         /* now look for a match on the key name */
9442
9443         p_data = printer->info_2->data;
9444
9445         key_index = lookup_printerkey(p_data, r->in.key_name);
9446         if (key_index == -1) {
9447                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9448                         r->in.key_name));
9449                 result = WERR_INVALID_PARAM;
9450                 goto done;
9451         }
9452
9453         /* allocate the memory for the array of pointers -- if necessary */
9454
9455         count = regval_ctr_numvals(p_data->keys[key_index].values);
9456         if (!count) {
9457                 result = WERR_OK; /* ??? */
9458                 goto done;
9459         }
9460
9461         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9462                                  struct spoolss_PrinterEnumValues,
9463                                  count);
9464         if (!info) {
9465                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9466                 result = WERR_NOMEM;
9467                 goto done;
9468         }
9469
9470         /*
9471          * loop through all params and build the array to pass
9472          * back to the  client
9473          */
9474
9475         for (i=0; i < count; i++) {
9476
9477                 REGISTRY_VALUE  *val;
9478
9479                 /* lookup the registry value */
9480
9481                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9482
9483                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9484
9485                 /* copy the data */
9486
9487                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9488                 if (!W_ERROR_IS_OK(result)) {
9489                         goto done;
9490                 }
9491         }
9492
9493 #if 0 /* FIXME - gd */
9494         /* housekeeping information in the reply */
9495
9496         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9497          * the hand marshalled container size is a multiple
9498          * of 4 bytes for RPC alignment.
9499          */
9500
9501         if (needed % 4) {
9502                 needed += 4-(needed % 4);
9503         }
9504 #endif
9505         *r->out.count   = count;
9506         *r->out.info    = info;
9507
9508  done:
9509
9510         if (printer) {
9511                 free_a_printer(&printer, 2);
9512         }
9513
9514         if (!W_ERROR_IS_OK(result)) {
9515                 return result;
9516         }
9517
9518         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9519                                                spoolss_EnumPrinterDataEx, NULL,
9520                                                *r->out.info,
9521                                                *r->out.count);
9522         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9523         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9524
9525         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9526 }
9527
9528 /****************************************************************************
9529 ****************************************************************************/
9530
9531 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9532                                                  const char *servername,
9533                                                  const char *environment,
9534                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9535 {
9536         WERROR werr;
9537         char *path = NULL;
9538
9539         werr = compose_spoolss_server_path(mem_ctx,
9540                                            servername,
9541                                            environment,
9542                                            SPOOLSS_PRTPROCS_PATH,
9543                                            &path);
9544         if (!W_ERROR_IS_OK(werr)) {
9545                 return werr;
9546         }
9547
9548         DEBUG(4,("print processor directory: [%s]\n", path));
9549
9550         r->directory_name = path;
9551
9552         return WERR_OK;
9553 }
9554
9555 /****************************************************************
9556  _spoolss_GetPrintProcessorDirectory
9557 ****************************************************************/
9558
9559 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9560                                            struct spoolss_GetPrintProcessorDirectory *r)
9561 {
9562         WERROR result;
9563
9564         /* that's an [in out] buffer */
9565
9566         if (!r->in.buffer && (r->in.offered != 0)) {
9567                 return WERR_INVALID_PARAM;
9568         }
9569
9570         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9571                 r->in.level));
9572
9573         *r->out.needed = 0;
9574
9575         /* r->in.level is ignored */
9576
9577         /* We always should reply with a local print processor directory so that
9578          * users are not forced to have a [prnproc$] share on the Samba spoolss
9579          * server - Guenther */
9580
9581         result = getprintprocessordirectory_level_1(p->mem_ctx,
9582                                                     NULL, /* r->in.server */
9583                                                     r->in.environment,
9584                                                     &r->out.info->info1);
9585         if (!W_ERROR_IS_OK(result)) {
9586                 TALLOC_FREE(r->out.info);
9587                 return result;
9588         }
9589
9590         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9591                                                r->out.info, r->in.level);
9592         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9593
9594         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9595 }
9596
9597 /*******************************************************************
9598  ********************************************************************/
9599
9600 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9601                                const char *dllname)
9602 {
9603         enum ndr_err_code ndr_err;
9604         struct spoolss_MonitorUi ui;
9605
9606         ui.dll_name = dllname;
9607
9608         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9609                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9610         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9611                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9612         }
9613         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9614 }
9615
9616 /*******************************************************************
9617  Streams the monitor UI DLL name in UNICODE
9618 *******************************************************************/
9619
9620 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9621                                NT_USER_TOKEN *token, DATA_BLOB *in,
9622                                DATA_BLOB *out, uint32_t *needed)
9623 {
9624         const char *dllname = "tcpmonui.dll";
9625
9626         *needed = (strlen(dllname)+1) * 2;
9627
9628         if (out->length < *needed) {
9629                 return WERR_INSUFFICIENT_BUFFER;
9630         }
9631
9632         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9633                 return WERR_NOMEM;
9634         }
9635
9636         return WERR_OK;
9637 }
9638
9639 /*******************************************************************
9640  ********************************************************************/
9641
9642 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9643                              struct spoolss_PortData1 *port1,
9644                              const DATA_BLOB *buf)
9645 {
9646         enum ndr_err_code ndr_err;
9647         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9648                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9649         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9650                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9651         }
9652         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9653 }
9654
9655 /*******************************************************************
9656  ********************************************************************/
9657
9658 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9659                              struct spoolss_PortData2 *port2,
9660                              const DATA_BLOB *buf)
9661 {
9662         enum ndr_err_code ndr_err;
9663         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9664                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9665         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9666                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9667         }
9668         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9669 }
9670
9671 /*******************************************************************
9672  Create a new TCP/IP port
9673 *******************************************************************/
9674
9675 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9676                              NT_USER_TOKEN *token, DATA_BLOB *in,
9677                              DATA_BLOB *out, uint32_t *needed)
9678 {
9679         struct spoolss_PortData1 port1;
9680         struct spoolss_PortData2 port2;
9681         char *device_uri = NULL;
9682         uint32_t version;
9683
9684         const char *portname;
9685         const char *hostaddress;
9686         const char *queue;
9687         uint32_t port_number;
9688         uint32_t protocol;
9689
9690         /* peek for spoolss_PortData version */
9691
9692         if (!in || (in->length < (128 + 4))) {
9693                 return WERR_GENERAL_FAILURE;
9694         }
9695
9696         version = IVAL(in->data, 128);
9697
9698         switch (version) {
9699                 case 1:
9700                         ZERO_STRUCT(port1);
9701
9702                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9703                                 return WERR_NOMEM;
9704                         }
9705
9706                         portname        = port1.portname;
9707                         hostaddress     = port1.hostaddress;
9708                         queue           = port1.queue;
9709                         protocol        = port1.protocol;
9710                         port_number     = port1.port_number;
9711
9712                         break;
9713                 case 2:
9714                         ZERO_STRUCT(port2);
9715
9716                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9717                                 return WERR_NOMEM;
9718                         }
9719
9720                         portname        = port2.portname;
9721                         hostaddress     = port2.hostaddress;
9722                         queue           = port2.queue;
9723                         protocol        = port2.protocol;
9724                         port_number     = port2.port_number;
9725
9726                         break;
9727                 default:
9728                         DEBUG(1,("xcvtcp_addport: "
9729                                 "unknown version of port_data: %d\n", version));
9730                         return WERR_UNKNOWN_PORT;
9731         }
9732
9733         /* create the device URI and call the add_port_hook() */
9734
9735         switch (protocol) {
9736         case PROTOCOL_RAWTCP_TYPE:
9737                 device_uri = talloc_asprintf(mem_ctx,
9738                                 "socket://%s:%d/", hostaddress,
9739                                 port_number);
9740                 break;
9741
9742         case PROTOCOL_LPR_TYPE:
9743                 device_uri = talloc_asprintf(mem_ctx,
9744                         "lpr://%s/%s", hostaddress, queue );
9745                 break;
9746
9747         default:
9748                 return WERR_UNKNOWN_PORT;
9749         }
9750
9751         if (!device_uri) {
9752                 return WERR_NOMEM;
9753         }
9754
9755         return add_port_hook(mem_ctx, token, portname, device_uri);
9756 }
9757
9758 /*******************************************************************
9759 *******************************************************************/
9760
9761 struct xcv_api_table xcvtcp_cmds[] = {
9762         { "MonitorUI",  xcvtcp_monitorui },
9763         { "AddPort",    xcvtcp_addport},
9764         { NULL,         NULL }
9765 };
9766
9767 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9768                                      NT_USER_TOKEN *token, const char *command,
9769                                      DATA_BLOB *inbuf,
9770                                      DATA_BLOB *outbuf,
9771                                      uint32_t *needed )
9772 {
9773         int i;
9774
9775         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9776
9777         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9778                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9779                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9780         }
9781
9782         return WERR_BADFUNC;
9783 }
9784
9785 /*******************************************************************
9786 *******************************************************************/
9787 #if 0   /* don't support management using the "Local Port" monitor */
9788
9789 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9790                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9791                                  DATA_BLOB *out, uint32_t *needed)
9792 {
9793         const char *dllname = "localui.dll";
9794
9795         *needed = (strlen(dllname)+1) * 2;
9796
9797         if (out->length < *needed) {
9798                 return WERR_INSUFFICIENT_BUFFER;
9799         }
9800
9801         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9802                 return WERR_NOMEM;
9803         }
9804
9805         return WERR_OK;
9806 }
9807
9808 /*******************************************************************
9809 *******************************************************************/
9810
9811 struct xcv_api_table xcvlocal_cmds[] = {
9812         { "MonitorUI",  xcvlocal_monitorui },
9813         { NULL,         NULL }
9814 };
9815 #else
9816 struct xcv_api_table xcvlocal_cmds[] = {
9817         { NULL,         NULL }
9818 };
9819 #endif
9820
9821
9822
9823 /*******************************************************************
9824 *******************************************************************/
9825
9826 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9827                                        NT_USER_TOKEN *token, const char *command,
9828                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9829                                        uint32_t *needed)
9830 {
9831         int i;
9832
9833         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9834
9835         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9836                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9837                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9838         }
9839         return WERR_BADFUNC;
9840 }
9841
9842 /****************************************************************
9843  _spoolss_XcvData
9844 ****************************************************************/
9845
9846 WERROR _spoolss_XcvData(pipes_struct *p,
9847                         struct spoolss_XcvData *r)
9848 {
9849         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9850         DATA_BLOB out_data = data_blob_null;
9851         WERROR werror;
9852
9853         if (!Printer) {
9854                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9855                         OUR_HANDLE(r->in.handle)));
9856                 return WERR_BADFID;
9857         }
9858
9859         /* Has to be a handle to the TCP/IP port monitor */
9860
9861         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9862                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9863                 return WERR_BADFID;
9864         }
9865
9866         /* requires administrative access to the server */
9867
9868         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9869                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9870                 return WERR_ACCESS_DENIED;
9871         }
9872
9873         /* Allocate the outgoing buffer */
9874
9875         if (r->in.out_data_size) {
9876                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9877                 if (out_data.data == NULL) {
9878                         return WERR_NOMEM;
9879                 }
9880         }
9881
9882         switch ( Printer->printer_type ) {
9883         case SPLHND_PORTMON_TCP:
9884                 werror = process_xcvtcp_command(p->mem_ctx,
9885                                                 p->server_info->ptok,
9886                                                 r->in.function_name,
9887                                                 &r->in.in_data, &out_data,
9888                                                 r->out.needed);
9889                 break;
9890         case SPLHND_PORTMON_LOCAL:
9891                 werror = process_xcvlocal_command(p->mem_ctx,
9892                                                   p->server_info->ptok,
9893                                                   r->in.function_name,
9894                                                   &r->in.in_data, &out_data,
9895                                                   r->out.needed);
9896                 break;
9897         default:
9898                 werror = WERR_INVALID_PRINT_MONITOR;
9899         }
9900
9901         if (!W_ERROR_IS_OK(werror)) {
9902                 return werror;
9903         }
9904
9905         *r->out.status_code = 0;
9906
9907         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9908                 memcpy(r->out.out_data, out_data.data,
9909                         MIN(r->in.out_data_size, out_data.length));
9910         }
9911
9912         return WERR_OK;
9913 }
9914
9915 /****************************************************************
9916  _spoolss_AddPrintProcessor
9917 ****************************************************************/
9918
9919 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9920                                   struct spoolss_AddPrintProcessor *r)
9921 {
9922         /* for now, just indicate success and ignore the add.  We'll
9923            automatically set the winprint processor for printer
9924            entries later.  Used to debug the LexMark Optra S 1855 PCL
9925            driver --jerry */
9926
9927         return WERR_OK;
9928 }
9929
9930 /****************************************************************
9931  _spoolss_AddPort
9932 ****************************************************************/
9933
9934 WERROR _spoolss_AddPort(pipes_struct *p,
9935                         struct spoolss_AddPort *r)
9936 {
9937         /* do what w2k3 does */
9938
9939         return WERR_NOT_SUPPORTED;
9940 }
9941
9942 /****************************************************************
9943  _spoolss_AddPrinter
9944 ****************************************************************/
9945
9946 WERROR _spoolss_AddPrinter(pipes_struct *p,
9947                            struct spoolss_AddPrinter *r)
9948 {
9949         p->rng_fault_state = true;
9950         return WERR_NOT_SUPPORTED;
9951 }
9952
9953 /****************************************************************
9954  _spoolss_GetPrinterDriver
9955 ****************************************************************/
9956
9957 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9958                                  struct spoolss_GetPrinterDriver *r)
9959 {
9960         p->rng_fault_state = true;
9961         return WERR_NOT_SUPPORTED;
9962 }
9963
9964 /****************************************************************
9965  _spoolss_ReadPrinter
9966 ****************************************************************/
9967
9968 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9969                             struct spoolss_ReadPrinter *r)
9970 {
9971         p->rng_fault_state = true;
9972         return WERR_NOT_SUPPORTED;
9973 }
9974
9975 /****************************************************************
9976  _spoolss_WaitForPrinterChange
9977 ****************************************************************/
9978
9979 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9980                                      struct spoolss_WaitForPrinterChange *r)
9981 {
9982         p->rng_fault_state = true;
9983         return WERR_NOT_SUPPORTED;
9984 }
9985
9986 /****************************************************************
9987  _spoolss_ConfigurePort
9988 ****************************************************************/
9989
9990 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9991                               struct spoolss_ConfigurePort *r)
9992 {
9993         p->rng_fault_state = true;
9994         return WERR_NOT_SUPPORTED;
9995 }
9996
9997 /****************************************************************
9998  _spoolss_DeletePort
9999 ****************************************************************/
10000
10001 WERROR _spoolss_DeletePort(pipes_struct *p,
10002                            struct spoolss_DeletePort *r)
10003 {
10004         p->rng_fault_state = true;
10005         return WERR_NOT_SUPPORTED;
10006 }
10007
10008 /****************************************************************
10009  _spoolss_CreatePrinterIC
10010 ****************************************************************/
10011
10012 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10013                                 struct spoolss_CreatePrinterIC *r)
10014 {
10015         p->rng_fault_state = true;
10016         return WERR_NOT_SUPPORTED;
10017 }
10018
10019 /****************************************************************
10020  _spoolss_PlayGDIScriptOnPrinterIC
10021 ****************************************************************/
10022
10023 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10024                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10025 {
10026         p->rng_fault_state = true;
10027         return WERR_NOT_SUPPORTED;
10028 }
10029
10030 /****************************************************************
10031  _spoolss_DeletePrinterIC
10032 ****************************************************************/
10033
10034 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10035                                 struct spoolss_DeletePrinterIC *r)
10036 {
10037         p->rng_fault_state = true;
10038         return WERR_NOT_SUPPORTED;
10039 }
10040
10041 /****************************************************************
10042  _spoolss_AddPrinterConnection
10043 ****************************************************************/
10044
10045 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10046                                      struct spoolss_AddPrinterConnection *r)
10047 {
10048         p->rng_fault_state = true;
10049         return WERR_NOT_SUPPORTED;
10050 }
10051
10052 /****************************************************************
10053  _spoolss_DeletePrinterConnection
10054 ****************************************************************/
10055
10056 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10057                                         struct spoolss_DeletePrinterConnection *r)
10058 {
10059         p->rng_fault_state = true;
10060         return WERR_NOT_SUPPORTED;
10061 }
10062
10063 /****************************************************************
10064  _spoolss_PrinterMessageBox
10065 ****************************************************************/
10066
10067 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10068                                   struct spoolss_PrinterMessageBox *r)
10069 {
10070         p->rng_fault_state = true;
10071         return WERR_NOT_SUPPORTED;
10072 }
10073
10074 /****************************************************************
10075  _spoolss_AddMonitor
10076 ****************************************************************/
10077
10078 WERROR _spoolss_AddMonitor(pipes_struct *p,
10079                            struct spoolss_AddMonitor *r)
10080 {
10081         p->rng_fault_state = true;
10082         return WERR_NOT_SUPPORTED;
10083 }
10084
10085 /****************************************************************
10086  _spoolss_DeleteMonitor
10087 ****************************************************************/
10088
10089 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10090                               struct spoolss_DeleteMonitor *r)
10091 {
10092         p->rng_fault_state = true;
10093         return WERR_NOT_SUPPORTED;
10094 }
10095
10096 /****************************************************************
10097  _spoolss_DeletePrintProcessor
10098 ****************************************************************/
10099
10100 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10101                                      struct spoolss_DeletePrintProcessor *r)
10102 {
10103         p->rng_fault_state = true;
10104         return WERR_NOT_SUPPORTED;
10105 }
10106
10107 /****************************************************************
10108  _spoolss_AddPrintProvidor
10109 ****************************************************************/
10110
10111 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10112                                  struct spoolss_AddPrintProvidor *r)
10113 {
10114         p->rng_fault_state = true;
10115         return WERR_NOT_SUPPORTED;
10116 }
10117
10118 /****************************************************************
10119  _spoolss_DeletePrintProvidor
10120 ****************************************************************/
10121
10122 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10123                                     struct spoolss_DeletePrintProvidor *r)
10124 {
10125         p->rng_fault_state = true;
10126         return WERR_NOT_SUPPORTED;
10127 }
10128
10129 /****************************************************************
10130  _spoolss_FindFirstPrinterChangeNotification
10131 ****************************************************************/
10132
10133 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10134                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10135 {
10136         p->rng_fault_state = true;
10137         return WERR_NOT_SUPPORTED;
10138 }
10139
10140 /****************************************************************
10141  _spoolss_FindNextPrinterChangeNotification
10142 ****************************************************************/
10143
10144 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10145                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10146 {
10147         p->rng_fault_state = true;
10148         return WERR_NOT_SUPPORTED;
10149 }
10150
10151 /****************************************************************
10152  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10153 ****************************************************************/
10154
10155 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10156                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10157 {
10158         p->rng_fault_state = true;
10159         return WERR_NOT_SUPPORTED;
10160 }
10161
10162 /****************************************************************
10163  _spoolss_ReplyOpenPrinter
10164 ****************************************************************/
10165
10166 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10167                                  struct spoolss_ReplyOpenPrinter *r)
10168 {
10169         p->rng_fault_state = true;
10170         return WERR_NOT_SUPPORTED;
10171 }
10172
10173 /****************************************************************
10174  _spoolss_RouterReplyPrinter
10175 ****************************************************************/
10176
10177 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10178                                    struct spoolss_RouterReplyPrinter *r)
10179 {
10180         p->rng_fault_state = true;
10181         return WERR_NOT_SUPPORTED;
10182 }
10183
10184 /****************************************************************
10185  _spoolss_ReplyClosePrinter
10186 ****************************************************************/
10187
10188 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10189                                   struct spoolss_ReplyClosePrinter *r)
10190 {
10191         p->rng_fault_state = true;
10192         return WERR_NOT_SUPPORTED;
10193 }
10194
10195 /****************************************************************
10196  _spoolss_AddPortEx
10197 ****************************************************************/
10198
10199 WERROR _spoolss_AddPortEx(pipes_struct *p,
10200                           struct spoolss_AddPortEx *r)
10201 {
10202         p->rng_fault_state = true;
10203         return WERR_NOT_SUPPORTED;
10204 }
10205
10206 /****************************************************************
10207  _spoolss_RouterFindFirstPrinterChangeNotification
10208 ****************************************************************/
10209
10210 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10211                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10212 {
10213         p->rng_fault_state = true;
10214         return WERR_NOT_SUPPORTED;
10215 }
10216
10217 /****************************************************************
10218  _spoolss_SpoolerInit
10219 ****************************************************************/
10220
10221 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10222                             struct spoolss_SpoolerInit *r)
10223 {
10224         p->rng_fault_state = true;
10225         return WERR_NOT_SUPPORTED;
10226 }
10227
10228 /****************************************************************
10229  _spoolss_ResetPrinterEx
10230 ****************************************************************/
10231
10232 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10233                                struct spoolss_ResetPrinterEx *r)
10234 {
10235         p->rng_fault_state = true;
10236         return WERR_NOT_SUPPORTED;
10237 }
10238
10239 /****************************************************************
10240  _spoolss_RouterReplyPrinterEx
10241 ****************************************************************/
10242
10243 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10244                                      struct spoolss_RouterReplyPrinterEx *r)
10245 {
10246         p->rng_fault_state = true;
10247         return WERR_NOT_SUPPORTED;
10248 }
10249
10250 /****************************************************************
10251  _spoolss_44
10252 ****************************************************************/
10253
10254 WERROR _spoolss_44(pipes_struct *p,
10255                    struct spoolss_44 *r)
10256 {
10257         p->rng_fault_state = true;
10258         return WERR_NOT_SUPPORTED;
10259 }
10260
10261 /****************************************************************
10262  _spoolss_47
10263 ****************************************************************/
10264
10265 WERROR _spoolss_47(pipes_struct *p,
10266                    struct spoolss_47 *r)
10267 {
10268         p->rng_fault_state = true;
10269         return WERR_NOT_SUPPORTED;
10270 }
10271
10272 /****************************************************************
10273  _spoolss_4a
10274 ****************************************************************/
10275
10276 WERROR _spoolss_4a(pipes_struct *p,
10277                    struct spoolss_4a *r)
10278 {
10279         p->rng_fault_state = true;
10280         return WERR_NOT_SUPPORTED;
10281 }
10282
10283 /****************************************************************
10284  _spoolss_4b
10285 ****************************************************************/
10286
10287 WERROR _spoolss_4b(pipes_struct *p,
10288                    struct spoolss_4b *r)
10289 {
10290         p->rng_fault_state = true;
10291         return WERR_NOT_SUPPORTED;
10292 }
10293
10294 /****************************************************************
10295  _spoolss_4c
10296 ****************************************************************/
10297
10298 WERROR _spoolss_4c(pipes_struct *p,
10299                    struct spoolss_4c *r)
10300 {
10301         p->rng_fault_state = true;
10302         return WERR_NOT_SUPPORTED;
10303 }
10304
10305 /****************************************************************
10306  _spoolss_53
10307 ****************************************************************/
10308
10309 WERROR _spoolss_53(pipes_struct *p,
10310                    struct spoolss_53 *r)
10311 {
10312         p->rng_fault_state = true;
10313         return WERR_NOT_SUPPORTED;
10314 }
10315
10316 /****************************************************************
10317  _spoolss_55
10318 ****************************************************************/
10319
10320 WERROR _spoolss_55(pipes_struct *p,
10321                    struct spoolss_55 *r)
10322 {
10323         p->rng_fault_state = true;
10324         return WERR_NOT_SUPPORTED;
10325 }
10326
10327 /****************************************************************
10328  _spoolss_56
10329 ****************************************************************/
10330
10331 WERROR _spoolss_56(pipes_struct *p,
10332                    struct spoolss_56 *r)
10333 {
10334         p->rng_fault_state = true;
10335         return WERR_NOT_SUPPORTED;
10336 }
10337
10338 /****************************************************************
10339  _spoolss_57
10340 ****************************************************************/
10341
10342 WERROR _spoolss_57(pipes_struct *p,
10343                    struct spoolss_57 *r)
10344 {
10345         p->rng_fault_state = true;
10346         return WERR_NOT_SUPPORTED;
10347 }
10348
10349 /****************************************************************
10350  _spoolss_5a
10351 ****************************************************************/
10352
10353 WERROR _spoolss_5a(pipes_struct *p,
10354                    struct spoolss_5a *r)
10355 {
10356         p->rng_fault_state = true;
10357         return WERR_NOT_SUPPORTED;
10358 }
10359
10360 /****************************************************************
10361  _spoolss_5b
10362 ****************************************************************/
10363
10364 WERROR _spoolss_5b(pipes_struct *p,
10365                    struct spoolss_5b *r)
10366 {
10367         p->rng_fault_state = true;
10368         return WERR_NOT_SUPPORTED;
10369 }
10370
10371 /****************************************************************
10372  _spoolss_5c
10373 ****************************************************************/
10374
10375 WERROR _spoolss_5c(pipes_struct *p,
10376                    struct spoolss_5c *r)
10377 {
10378         p->rng_fault_state = true;
10379         return WERR_NOT_SUPPORTED;
10380 }
10381
10382 /****************************************************************
10383  _spoolss_5d
10384 ****************************************************************/
10385
10386 WERROR _spoolss_5d(pipes_struct *p,
10387                    struct spoolss_5d *r)
10388 {
10389         p->rng_fault_state = true;
10390         return WERR_NOT_SUPPORTED;
10391 }
10392
10393 /****************************************************************
10394  _spoolss_5e
10395 ****************************************************************/
10396
10397 WERROR _spoolss_5e(pipes_struct *p,
10398                    struct spoolss_5e *r)
10399 {
10400         p->rng_fault_state = true;
10401         return WERR_NOT_SUPPORTED;
10402 }
10403
10404 /****************************************************************
10405  _spoolss_5f
10406 ****************************************************************/
10407
10408 WERROR _spoolss_5f(pipes_struct *p,
10409                    struct spoolss_5f *r)
10410 {
10411         p->rng_fault_state = true;
10412         return WERR_NOT_SUPPORTED;
10413 }
10414