28c59d1feeaf4963bec69e6c136e3b87569c0e67
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33         ((info)?ndr_size_##fn(info, level, ic, 0):0)
34
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
37
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
42
43
44 extern userdom_struct current_user_info;
45
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
48
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
52
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
55
56 struct table_node {
57         const char    *long_archi;
58         const char    *short_archi;
59         int     version;
60 };
61
62 static Printer_entry *printers_list;
63
64 typedef struct _counter_printer_0 {
65         struct _counter_printer_0 *next;
66         struct _counter_printer_0 *prev;
67
68         int snum;
69         uint32_t counter;
70 } counter_printer_0;
71
72 static counter_printer_0 *counter_list;
73
74 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
75 static uint32_t smb_connections = 0;
76
77
78 /* in printing/nt_printing.c */
79
80 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
81
82 /* API table for Xcv Monitor functions */
83
84 struct xcv_api_table {
85         const char *name;
86         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
87 };
88
89 /********************************************************************
90  * Canonicalize servername.
91  ********************************************************************/
92
93 static const char *canon_servername(const char *servername)
94 {
95         const char *pservername = servername;
96         while (*pservername == '\\') {
97                 pservername++;
98         }
99         return pservername;
100 }
101
102 /* translate between internal status numbers and NT status numbers */
103 static int nt_printj_status(int v)
104 {
105         switch (v) {
106         case LPQ_QUEUED:
107                 return 0;
108         case LPQ_PAUSED:
109                 return JOB_STATUS_PAUSED;
110         case LPQ_SPOOLING:
111                 return JOB_STATUS_SPOOLING;
112         case LPQ_PRINTING:
113                 return JOB_STATUS_PRINTING;
114         case LPQ_ERROR:
115                 return JOB_STATUS_ERROR;
116         case LPQ_DELETING:
117                 return JOB_STATUS_DELETING;
118         case LPQ_OFFLINE:
119                 return JOB_STATUS_OFFLINE;
120         case LPQ_PAPEROUT:
121                 return JOB_STATUS_PAPEROUT;
122         case LPQ_PRINTED:
123                 return JOB_STATUS_PRINTED;
124         case LPQ_DELETED:
125                 return JOB_STATUS_DELETED;
126         case LPQ_BLOCKED:
127                 return JOB_STATUS_BLOCKED_DEVQ;
128         case LPQ_USER_INTERVENTION:
129                 return JOB_STATUS_USER_INTERVENTION;
130         }
131         return 0;
132 }
133
134 static int nt_printq_status(int v)
135 {
136         switch (v) {
137         case LPQ_PAUSED:
138                 return PRINTER_STATUS_PAUSED;
139         case LPQ_QUEUED:
140         case LPQ_SPOOLING:
141         case LPQ_PRINTING:
142                 return 0;
143         }
144         return 0;
145 }
146
147 /***************************************************************************
148  Disconnect from the client
149 ****************************************************************************/
150
151 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
152 {
153         WERROR result;
154         NTSTATUS status;
155
156         /*
157          * Tell the specific printing tdb we no longer want messages for this printer
158          * by deregistering our PID.
159          */
160
161         if (!print_notify_deregister_pid(snum))
162                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163
164         /* weird if the test succeds !!! */
165         if (smb_connections==0) {
166                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167                 return;
168         }
169
170         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
171                                                   handle,
172                                                   &result);
173         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
174                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
175                         win_errstr(result)));
176
177         /* if it's the last connection, deconnect the IPC$ share */
178         if (smb_connections==1) {
179
180                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
181                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182
183                 messaging_deregister(smbd_messaging_context(),
184                                      MSG_PRINTER_NOTIFY2, NULL);
185
186                 /* Tell the connections db we're no longer interested in
187                  * printer notify messages. */
188
189                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
190         }
191
192         smb_connections--;
193 }
194
195 /****************************************************************************
196  Functions to free a printer entry datastruct.
197 ****************************************************************************/
198
199 static int printer_entry_destructor(Printer_entry *Printer)
200 {
201         if (Printer->notify.client_connected == true) {
202                 int snum = -1;
203
204                 if ( Printer->printer_type == SPLHND_SERVER) {
205                         snum = -1;
206                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
207                 } else if (Printer->printer_type == SPLHND_PRINTER) {
208                         snum = print_queue_snum(Printer->sharename);
209                         if (snum != -1)
210                                 srv_spoolss_replycloseprinter(snum,
211                                                 &Printer->notify.client_hnd);
212                 }
213         }
214
215         Printer->notify.flags=0;
216         Printer->notify.options=0;
217         Printer->notify.localmachine[0]='\0';
218         Printer->notify.printerlocal=0;
219         TALLOC_FREE(Printer->notify.option);
220         Printer->notify.client_connected = false;
221
222         free_nt_devicemode( &Printer->nt_devmode );
223         free_a_printer( &Printer->printer_info, 2 );
224
225         /* Remove from the internal list. */
226         DLIST_REMOVE(printers_list, Printer);
227         return 0;
228 }
229
230 /****************************************************************************
231   find printer index by handle
232 ****************************************************************************/
233
234 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
235                                                 struct policy_handle *hnd)
236 {
237         Printer_entry *find_printer = NULL;
238
239         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
240                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
241                 return NULL;
242         }
243
244         return find_printer;
245 }
246
247 /****************************************************************************
248  Close printer index by handle.
249 ****************************************************************************/
250
251 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
252 {
253         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
254
255         if (!Printer) {
256                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
257                         OUR_HANDLE(hnd)));
258                 return false;
259         }
260
261         close_policy_hnd(p, hnd);
262
263         return true;
264 }
265
266 /****************************************************************************
267  Delete a printer given a handle.
268 ****************************************************************************/
269
270 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
271 {
272         char *cmd = lp_deleteprinter_cmd();
273         char *command = NULL;
274         int ret;
275         SE_PRIV se_printop = SE_PRINT_OPERATOR;
276         bool is_print_op = false;
277
278         /* can't fail if we don't try */
279
280         if ( !*cmd )
281                 return WERR_OK;
282
283         command = talloc_asprintf(ctx,
284                         "%s \"%s\"",
285                         cmd, sharename);
286         if (!command) {
287                 return WERR_NOMEM;
288         }
289         if ( token )
290                 is_print_op = user_has_privileges( token, &se_printop );
291
292         DEBUG(10,("Running [%s]\n", command));
293
294         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
295
296         if ( is_print_op )
297                 become_root();
298
299         if ( (ret = smbrun(command, NULL)) == 0 ) {
300                 /* Tell everyone we updated smb.conf. */
301                 message_send_all(smbd_messaging_context(),
302                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
303         }
304
305         if ( is_print_op )
306                 unbecome_root();
307
308         /********** END SePrintOperatorPrivlege BLOCK **********/
309
310         DEBUGADD(10,("returned [%d]\n", ret));
311
312         TALLOC_FREE(command);
313
314         if (ret != 0)
315                 return WERR_BADFID; /* What to return here? */
316
317         /* go ahead and re-read the services immediately */
318         reload_services(false);
319
320         if ( lp_servicenumber( sharename )  < 0 )
321                 return WERR_ACCESS_DENIED;
322
323         return WERR_OK;
324 }
325
326 /****************************************************************************
327  Delete a printer given a handle.
328 ****************************************************************************/
329
330 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
331 {
332         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
333
334         if (!Printer) {
335                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
336                         OUR_HANDLE(hnd)));
337                 return WERR_BADFID;
338         }
339
340         /*
341          * It turns out that Windows allows delete printer on a handle
342          * opened by an admin user, then used on a pipe handle created
343          * by an anonymous user..... but they're working on security.... riiight !
344          * JRA.
345          */
346
347         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
348                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
349                 return WERR_ACCESS_DENIED;
350         }
351
352         /* this does not need a become root since the access check has been
353            done on the handle already */
354
355         if (del_a_printer( Printer->sharename ) != 0) {
356                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
357                 return WERR_BADFID;
358         }
359
360         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
361                                    Printer->sharename );
362 }
363
364 /****************************************************************************
365  Return the snum of a printer corresponding to an handle.
366 ****************************************************************************/
367
368 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
369                              int *number, struct share_params **params)
370 {
371         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
372
373         if (!Printer) {
374                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
375                         OUR_HANDLE(hnd)));
376                 return false;
377         }
378
379         switch (Printer->printer_type) {
380                 case SPLHND_PRINTER:
381                         DEBUG(4,("short name:%s\n", Printer->sharename));
382                         *number = print_queue_snum(Printer->sharename);
383                         return (*number != -1);
384                 case SPLHND_SERVER:
385                         return false;
386                 default:
387                         return false;
388         }
389 }
390
391 /****************************************************************************
392  Set printer handle type.
393  Check if it's \\server or \\server\printer
394 ****************************************************************************/
395
396 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
397 {
398         DEBUG(3,("Setting printer type=%s\n", handlename));
399
400         if ( strlen(handlename) < 3 ) {
401                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
402                 return false;
403         }
404
405         /* it's a print server */
406         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
407                 DEBUGADD(4,("Printer is a print server\n"));
408                 Printer->printer_type = SPLHND_SERVER;
409         }
410         /* it's a printer (set_printer_hnd_name() will handle port monitors */
411         else {
412                 DEBUGADD(4,("Printer is a printer\n"));
413                 Printer->printer_type = SPLHND_PRINTER;
414         }
415
416         return true;
417 }
418
419 /****************************************************************************
420  Set printer handle name..  Accept names like \\server, \\server\printer,
421  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
422  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
423  XcvDataPort() interface.
424 ****************************************************************************/
425
426 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
427 {
428         int snum;
429         int n_services=lp_numservices();
430         char *aprinter, *printername;
431         const char *servername;
432         fstring sname;
433         bool found = false;
434         NT_PRINTER_INFO_LEVEL *printer = NULL;
435         WERROR result;
436
437         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
438                 (unsigned long)strlen(handlename)));
439
440         aprinter = CONST_DISCARD(char *, handlename);
441         if ( *handlename == '\\' ) {
442                 servername = canon_servername(handlename);
443                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
444                         *aprinter = '\0';
445                         aprinter++;
446                 }
447         } else {
448                 servername = global_myname();
449         }
450
451         /* save the servername to fill in replies on this handle */
452
453         if ( !is_myname_or_ipaddr( servername ) )
454                 return false;
455
456         fstrcpy( Printer->servername, servername );
457
458         if ( Printer->printer_type == SPLHND_SERVER )
459                 return true;
460
461         if ( Printer->printer_type != SPLHND_PRINTER )
462                 return false;
463
464         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
465
466         /* check for the Port Monitor Interface */
467
468         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
469                 Printer->printer_type = SPLHND_PORTMON_TCP;
470                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
471                 found = true;
472         }
473         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
474                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
475                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
476                 found = true;
477         }
478
479         /* Search all sharenames first as this is easier than pulling
480            the printer_info_2 off of disk. Don't use find_service() since
481            that calls out to map_username() */
482
483         /* do another loop to look for printernames */
484
485         for (snum=0; !found && snum<n_services; snum++) {
486
487                 /* no point going on if this is not a printer */
488
489                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
490                         continue;
491
492                 fstrcpy(sname, lp_servicename(snum));
493                 if ( strequal( aprinter, sname ) ) {
494                         found = true;
495                         break;
496                 }
497
498                 /* no point looking up the printer object if
499                    we aren't allowing printername != sharename */
500
501                 if ( lp_force_printername(snum) )
502                         continue;
503
504                 fstrcpy(sname, lp_servicename(snum));
505
506                 printer = NULL;
507
508                 /* This call doesn't fill in the location or comment from
509                  * a CUPS server for efficiency with large numbers of printers.
510                  * JRA.
511                  */
512
513                 result = get_a_printer_search( NULL, &printer, 2, sname );
514                 if ( !W_ERROR_IS_OK(result) ) {
515                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516                                 sname, win_errstr(result)));
517                         continue;
518                 }
519
520                 /* printername is always returned as \\server\printername */
521                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
522                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523                                 printer->info_2->printername));
524                         free_a_printer( &printer, 2);
525                         continue;
526                 }
527
528                 printername++;
529
530                 if ( strequal(printername, aprinter) ) {
531                         free_a_printer( &printer, 2);
532                         found = true;
533                         break;
534                 }
535
536                 DEBUGADD(10, ("printername: %s\n", printername));
537
538                 free_a_printer( &printer, 2);
539         }
540
541         free_a_printer( &printer, 2);
542
543         if ( !found ) {
544                 DEBUGADD(4,("Printer not found\n"));
545                 return false;
546         }
547
548         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
549
550         fstrcpy(Printer->sharename, sname);
551
552         return true;
553 }
554
555 /****************************************************************************
556  Find first available printer slot. creates a printer handle for you.
557  ****************************************************************************/
558
559 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
560                              const char *name, uint32_t access_granted)
561 {
562         Printer_entry *new_printer;
563
564         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
565
566         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
567         if (new_printer == NULL) {
568                 return false;
569         }
570         talloc_set_destructor(new_printer, printer_entry_destructor);
571
572         if (!create_policy_hnd(p, hnd, new_printer)) {
573                 TALLOC_FREE(new_printer);
574                 return false;
575         }
576
577         /* Add to the internal list. */
578         DLIST_ADD(printers_list, new_printer);
579
580         new_printer->notify.option=NULL;
581
582         if (!set_printer_hnd_printertype(new_printer, name)) {
583                 close_printer_handle(p, hnd);
584                 return false;
585         }
586
587         if (!set_printer_hnd_name(new_printer, name)) {
588                 close_printer_handle(p, hnd);
589                 return false;
590         }
591
592         new_printer->access_granted = access_granted;
593
594         DEBUG(5, ("%d printer handles active\n",
595                   (int)num_pipe_handles(p->pipe_handles)));
596
597         return true;
598 }
599
600 /***************************************************************************
601  check to see if the client motify handle is monitoring the notification
602  given by (notify_type, notify_field).
603  **************************************************************************/
604
605 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
606                                       uint16_t notify_field)
607 {
608         return true;
609 }
610
611 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
612                                 uint16_t notify_field)
613 {
614         struct spoolss_NotifyOption *option = p->notify.option;
615         uint32_t i, j;
616
617         /*
618          * Flags should always be zero when the change notify
619          * is registered by the client's spooler.  A user Win32 app
620          * might use the flags though instead of the NOTIFY_OPTION_INFO
621          * --jerry
622          */
623
624         if (!option) {
625                 return false;
626         }
627
628         if (p->notify.flags)
629                 return is_monitoring_event_flags(
630                         p->notify.flags, notify_type, notify_field);
631
632         for (i = 0; i < option->count; i++) {
633
634                 /* Check match for notify_type */
635
636                 if (option->types[i].type != notify_type)
637                         continue;
638
639                 /* Check match for field */
640
641                 for (j = 0; j < option->types[i].count; j++) {
642                         if (option->types[i].fields[j].field == notify_field) {
643                                 return true;
644                         }
645                 }
646         }
647
648         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
649                    p->servername, p->sharename, notify_type, notify_field));
650
651         return false;
652 }
653
654 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
655         _data->data.integer[0] = _integer; \
656         _data->data.integer[1] = 0;
657
658
659 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
660         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
661         if (!_data->data.string.string) {\
662                 _data->data.string.size = 0; \
663         } \
664         _data->data.string.size = strlen_m_term(_p) * 2;
665
666 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
667         _data->data.devmode.devmode = _devmode;
668
669 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
670         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
671         if (!_data->data.sd.sd) { \
672                 _data->data.sd.sd_size = 0; \
673         } \
674         _data->data.sd.sd_size = _size;
675
676 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
677                                    struct tm *t,
678                                    const char **pp,
679                                    uint32_t *plen)
680 {
681         struct spoolss_Time st;
682         uint32_t len = 16;
683         char *p;
684
685         if (!init_systemtime(&st, t)) {
686                 return;
687         }
688
689         p = talloc_array(mem_ctx, char, len);
690         if (!p) {
691                 return;
692         }
693
694         /*
695          * Systemtime must be linearized as a set of UINT16's.
696          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
697          */
698
699         SSVAL(p, 0, st.year);
700         SSVAL(p, 2, st.month);
701         SSVAL(p, 4, st.day_of_week);
702         SSVAL(p, 6, st.day);
703         SSVAL(p, 8, st.hour);
704         SSVAL(p, 10, st.minute);
705         SSVAL(p, 12, st.second);
706         SSVAL(p, 14, st.millisecond);
707
708         *pp = p;
709         *plen = len;
710 }
711
712 /* Convert a notification message to a struct spoolss_Notify */
713
714 static void notify_one_value(struct spoolss_notify_msg *msg,
715                              struct spoolss_Notify *data,
716                              TALLOC_CTX *mem_ctx)
717 {
718         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
719 }
720
721 static void notify_string(struct spoolss_notify_msg *msg,
722                           struct spoolss_Notify *data,
723                           TALLOC_CTX *mem_ctx)
724 {
725         /* The length of the message includes the trailing \0 */
726
727         data->data.string.size = msg->len * 2;
728         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
729         if (!data->data.string.string) {
730                 data->data.string.size = 0;
731                 return;
732         }
733 }
734
735 static void notify_system_time(struct spoolss_notify_msg *msg,
736                                struct spoolss_Notify *data,
737                                TALLOC_CTX *mem_ctx)
738 {
739         data->data.string.string = NULL;
740         data->data.string.size = 0;
741
742         if (msg->len != sizeof(time_t)) {
743                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
744                           msg->len));
745                 return;
746         }
747
748         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
749                                &data->data.string.string,
750                                &data->data.string.size);
751 }
752
753 struct notify2_message_table {
754         const char *name;
755         void (*fn)(struct spoolss_notify_msg *msg,
756                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
757 };
758
759 static struct notify2_message_table printer_notify_table[] = {
760         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
761         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
762         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
763         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
764         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
765         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
766         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
767         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
768         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
769         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
770         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
771         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
772         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
773         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
774         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
775         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
776         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
777         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
778         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
779 };
780
781 static struct notify2_message_table job_notify_table[] = {
782         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
783         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
784         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
785         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
786         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
787         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
788         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
789         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
790         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
791         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
792         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
793         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
794         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
795         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
796         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
797         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
798         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
799         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
800         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
801         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
802         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
803         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
804         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
805         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
806 };
807
808
809 /***********************************************************************
810  Allocate talloc context for container object
811  **********************************************************************/
812
813 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 {
815         if ( !ctr )
816                 return;
817
818         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
819
820         return;
821 }
822
823 /***********************************************************************
824  release all allocated memory and zero out structure
825  **********************************************************************/
826
827 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 {
829         if ( !ctr )
830                 return;
831
832         if ( ctr->ctx )
833                 talloc_destroy(ctr->ctx);
834
835         ZERO_STRUCTP(ctr);
836
837         return;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 {
845         if ( !ctr )
846                 return NULL;
847
848         return ctr->ctx;
849 }
850
851 /***********************************************************************
852  **********************************************************************/
853
854 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
855 {
856         if ( !ctr || !ctr->msg_groups )
857                 return NULL;
858
859         if ( idx >= ctr->num_groups )
860                 return NULL;
861
862         return &ctr->msg_groups[idx];
863
864 }
865
866 /***********************************************************************
867  How many groups of change messages do we have ?
868  **********************************************************************/
869
870 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
871 {
872         if ( !ctr )
873                 return 0;
874
875         return ctr->num_groups;
876 }
877
878 /***********************************************************************
879  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
880  **********************************************************************/
881
882 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
883 {
884         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
885         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
886         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
887         int                             i, new_slot;
888
889         if ( !ctr || !msg )
890                 return 0;
891
892         /* loop over all groups looking for a matching printer name */
893
894         for ( i=0; i<ctr->num_groups; i++ ) {
895                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
896                         break;
897         }
898
899         /* add a new group? */
900
901         if ( i == ctr->num_groups ) {
902                 ctr->num_groups++;
903
904                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
905                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
906                         return 0;
907                 }
908                 ctr->msg_groups = groups;
909
910                 /* clear the new entry and set the printer name */
911
912                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
913                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
914         }
915
916         /* add the change messages; 'i' is the correct index now regardless */
917
918         msg_grp = &ctr->msg_groups[i];
919
920         msg_grp->num_msgs++;
921
922         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
923                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
924                 return 0;
925         }
926         msg_grp->msgs = msg_list;
927
928         new_slot = msg_grp->num_msgs-1;
929         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
930
931         /* need to allocate own copy of data */
932
933         if ( msg->len != 0 )
934                 msg_grp->msgs[new_slot].notify.data = (char *)
935                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
936
937         return ctr->num_groups;
938 }
939
940 /***********************************************************************
941  Send a change notication message on all handles which have a call
942  back registered
943  **********************************************************************/
944
945 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
946 {
947         Printer_entry            *p;
948         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
949         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
950         SPOOLSS_NOTIFY_MSG       *messages;
951         int                      sending_msg_count;
952
953         if ( !msg_group ) {
954                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
955                 return;
956         }
957
958         messages = msg_group->msgs;
959
960         if ( !messages ) {
961                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
962                 return;
963         }
964
965         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
966
967         /* loop over all printers */
968
969         for (p = printers_list; p; p = p->next) {
970                 struct spoolss_Notify *notifies;
971                 uint32_t count = 0;
972                 uint32_t id;
973                 int     i;
974
975                 /* Is there notification on this handle? */
976
977                 if ( !p->notify.client_connected )
978                         continue;
979
980                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
981
982                 /* For this printer?  Print servers always receive
983                    notifications. */
984
985                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
986                     ( !strequal(msg_group->printername, p->sharename) ) )
987                         continue;
988
989                 DEBUG(10,("Our printer\n"));
990
991                 /* allocate the max entries possible */
992
993                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
994                 if (!notifies) {
995                         return;
996                 }
997
998                 /* build the array of change notifications */
999
1000                 sending_msg_count = 0;
1001
1002                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1003                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1004
1005                         /* Are we monitoring this event? */
1006
1007                         if (!is_monitoring_event(p, msg->type, msg->field))
1008                                 continue;
1009
1010                         sending_msg_count++;
1011
1012
1013                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1014                                 msg->type, msg->field, p->sharename));
1015
1016                         /*
1017                          * if the is a printer notification handle and not a job notification
1018                          * type, then set the id to 0.  Other wise just use what was specified
1019                          * in the message.
1020                          *
1021                          * When registering change notification on a print server handle
1022                          * we always need to send back the id (snum) matching the printer
1023                          * for which the change took place.  For change notify registered
1024                          * on a printer handle, this does not matter and the id should be 0.
1025                          *
1026                          * --jerry
1027                          */
1028
1029                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1030                                 id = 0;
1031                         else
1032                                 id = msg->id;
1033
1034
1035                         /* Convert unix jobid to smb jobid */
1036
1037                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1038                                 id = sysjob_to_jobid(msg->id);
1039
1040                                 if (id == -1) {
1041                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1042                                         goto done;
1043                                 }
1044                         }
1045
1046                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1047
1048                         switch(msg->type) {
1049                         case PRINTER_NOTIFY_TYPE:
1050                                 if ( printer_notify_table[msg->field].fn )
1051                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1052                                 break;
1053
1054                         case JOB_NOTIFY_TYPE:
1055                                 if ( job_notify_table[msg->field].fn )
1056                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1057                                 break;
1058
1059                         default:
1060                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1061                                 goto done;
1062                         }
1063
1064                         count++;
1065                 }
1066
1067                 if ( sending_msg_count ) {
1068                         NTSTATUS status;
1069                         WERROR werr;
1070                         union spoolss_ReplyPrinterInfo info;
1071                         struct spoolss_NotifyInfo info0;
1072                         uint32_t reply_result;
1073
1074                         info0.version   = 0x2;
1075                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1076                         info0.count     = count;
1077                         info0.notifies  = notifies;
1078
1079                         info.info0 = &info0;
1080
1081                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1082                                                                      &p->notify.client_hnd,
1083                                                                      p->notify.change, /* color */
1084                                                                      p->notify.flags,
1085                                                                      &reply_result,
1086                                                                      0, /* reply_type, must be 0 */
1087                                                                      info,
1088                                                                      &werr);
1089                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1090                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1091                                         notify_cli_pipe->srv_name_slash,
1092                                         win_errstr(werr)));
1093                         }
1094                         switch (reply_result) {
1095                                 case 0:
1096                                         break;
1097                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1098                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1099                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1100                                         break;
1101                                 default:
1102                                         break;
1103                         }
1104                 }
1105         }
1106
1107 done:
1108         DEBUG(8,("send_notify2_changes: Exit...\n"));
1109         return;
1110 }
1111
1112 /***********************************************************************
1113  **********************************************************************/
1114
1115 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1116 {
1117
1118         uint32_t tv_sec, tv_usec;
1119         size_t offset = 0;
1120
1121         /* Unpack message */
1122
1123         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1124                              msg->printer);
1125
1126         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1127                                 &tv_sec, &tv_usec,
1128                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1129
1130         if (msg->len == 0)
1131                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1132                            &msg->notify.value[0], &msg->notify.value[1]);
1133         else
1134                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1135                            &msg->len, &msg->notify.data);
1136
1137         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1138                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1139
1140         tv->tv_sec = tv_sec;
1141         tv->tv_usec = tv_usec;
1142
1143         if (msg->len == 0)
1144                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1145                           msg->notify.value[1]));
1146         else
1147                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1148
1149         return true;
1150 }
1151
1152 /********************************************************************
1153  Receive a notify2 message list
1154  ********************************************************************/
1155
1156 static void receive_notify2_message_list(struct messaging_context *msg,
1157                                          void *private_data,
1158                                          uint32_t msg_type,
1159                                          struct server_id server_id,
1160                                          DATA_BLOB *data)
1161 {
1162         size_t                  msg_count, i;
1163         char                    *buf = (char *)data->data;
1164         char                    *msg_ptr;
1165         size_t                  msg_len;
1166         SPOOLSS_NOTIFY_MSG      notify;
1167         SPOOLSS_NOTIFY_MSG_CTR  messages;
1168         int                     num_groups;
1169
1170         if (data->length < 4) {
1171                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1172                 return;
1173         }
1174
1175         msg_count = IVAL(buf, 0);
1176         msg_ptr = buf + 4;
1177
1178         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1179
1180         if (msg_count == 0) {
1181                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1182                 return;
1183         }
1184
1185         /* initialize the container */
1186
1187         ZERO_STRUCT( messages );
1188         notify_msg_ctr_init( &messages );
1189
1190         /*
1191          * build message groups for each printer identified
1192          * in a change_notify msg.  Remember that a PCN message
1193          * includes the handle returned for the srv_spoolss_replyopenprinter()
1194          * call.  Therefore messages are grouped according to printer handle.
1195          */
1196
1197         for ( i=0; i<msg_count; i++ ) {
1198                 struct timeval msg_tv;
1199
1200                 if (msg_ptr + 4 - buf > data->length) {
1201                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1202                         return;
1203                 }
1204
1205                 msg_len = IVAL(msg_ptr,0);
1206                 msg_ptr += 4;
1207
1208                 if (msg_ptr + msg_len - buf > data->length) {
1209                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1210                         return;
1211                 }
1212
1213                 /* unpack messages */
1214
1215                 ZERO_STRUCT( notify );
1216                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1217                 msg_ptr += msg_len;
1218
1219                 /* add to correct list in container */
1220
1221                 notify_msg_ctr_addmsg( &messages, &notify );
1222
1223                 /* free memory that might have been allocated by notify2_unpack_msg() */
1224
1225                 if ( notify.len != 0 )
1226                         SAFE_FREE( notify.notify.data );
1227         }
1228
1229         /* process each group of messages */
1230
1231         num_groups = notify_msg_ctr_numgroups( &messages );
1232         for ( i=0; i<num_groups; i++ )
1233                 send_notify2_changes( &messages, i );
1234
1235
1236         /* cleanup */
1237
1238         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1239                 (uint32_t)msg_count ));
1240
1241         notify_msg_ctr_destroy( &messages );
1242
1243         return;
1244 }
1245
1246 /********************************************************************
1247  Send a message to ourself about new driver being installed
1248  so we can upgrade the information for each printer bound to this
1249  driver
1250  ********************************************************************/
1251
1252 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1253 {
1254         int len = strlen(drivername);
1255
1256         if (!len)
1257                 return false;
1258
1259         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1260                 drivername));
1261
1262         messaging_send_buf(smbd_messaging_context(), procid_self(),
1263                            MSG_PRINTER_DRVUPGRADE,
1264                            (uint8_t *)drivername, len+1);
1265
1266         return true;
1267 }
1268
1269 /**********************************************************************
1270  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1271  over all printers, upgrading ones as necessary
1272  **********************************************************************/
1273
1274 void do_drv_upgrade_printer(struct messaging_context *msg,
1275                             void *private_data,
1276                             uint32_t msg_type,
1277                             struct server_id server_id,
1278                             DATA_BLOB *data)
1279 {
1280         fstring drivername;
1281         int snum;
1282         int n_services = lp_numservices();
1283         size_t len;
1284
1285         len = MIN(data->length,sizeof(drivername)-1);
1286         strncpy(drivername, (const char *)data->data, len);
1287
1288         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1289
1290         /* Iterate the printer list */
1291
1292         for (snum=0; snum<n_services; snum++)
1293         {
1294                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1295                 {
1296                         WERROR result;
1297                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1298
1299                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1300                         if (!W_ERROR_IS_OK(result))
1301                                 continue;
1302
1303                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1304                         {
1305                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1306
1307                                 /* all we care about currently is the change_id */
1308
1309                                 result = mod_a_printer(printer, 2);
1310                                 if (!W_ERROR_IS_OK(result)) {
1311                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1312                                                 win_errstr(result)));
1313                                 }
1314                         }
1315
1316                         free_a_printer(&printer, 2);
1317                 }
1318         }
1319
1320         /* all done */
1321 }
1322
1323 /********************************************************************
1324  Update the cache for all printq's with a registered client
1325  connection
1326  ********************************************************************/
1327
1328 void update_monitored_printq_cache( void )
1329 {
1330         Printer_entry *printer = printers_list;
1331         int snum;
1332
1333         /* loop through all printers and update the cache where
1334            client_connected == true */
1335         while ( printer )
1336         {
1337                 if ( (printer->printer_type == SPLHND_PRINTER)
1338                         && printer->notify.client_connected )
1339                 {
1340                         snum = print_queue_snum(printer->sharename);
1341                         print_queue_status( snum, NULL, NULL );
1342                 }
1343
1344                 printer = printer->next;
1345         }
1346
1347         return;
1348 }
1349 /********************************************************************
1350  Send a message to ourself about new driver being installed
1351  so we can upgrade the information for each printer bound to this
1352  driver
1353  ********************************************************************/
1354
1355 static bool srv_spoolss_reset_printerdata(char* drivername)
1356 {
1357         int len = strlen(drivername);
1358
1359         if (!len)
1360                 return false;
1361
1362         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1363                 drivername));
1364
1365         messaging_send_buf(smbd_messaging_context(), procid_self(),
1366                            MSG_PRINTERDATA_INIT_RESET,
1367                            (uint8_t *)drivername, len+1);
1368
1369         return true;
1370 }
1371
1372 /**********************************************************************
1373  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1374  over all printers, resetting printer data as neessary
1375  **********************************************************************/
1376
1377 void reset_all_printerdata(struct messaging_context *msg,
1378                            void *private_data,
1379                            uint32_t msg_type,
1380                            struct server_id server_id,
1381                            DATA_BLOB *data)
1382 {
1383         fstring drivername;
1384         int snum;
1385         int n_services = lp_numservices();
1386         size_t len;
1387
1388         len = MIN( data->length, sizeof(drivername)-1 );
1389         strncpy( drivername, (const char *)data->data, len );
1390
1391         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1392
1393         /* Iterate the printer list */
1394
1395         for ( snum=0; snum<n_services; snum++ )
1396         {
1397                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1398                 {
1399                         WERROR result;
1400                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1401
1402                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1403                         if ( !W_ERROR_IS_OK(result) )
1404                                 continue;
1405
1406                         /*
1407                          * if the printer is bound to the driver,
1408                          * then reset to the new driver initdata
1409                          */
1410
1411                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1412                         {
1413                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1414
1415                                 if ( !set_driver_init(printer, 2) ) {
1416                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1417                                                 printer->info_2->printername, printer->info_2->drivername));
1418                                 }
1419
1420                                 result = mod_a_printer( printer, 2 );
1421                                 if ( !W_ERROR_IS_OK(result) ) {
1422                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1423                                                 get_dos_error_msg(result)));
1424                                 }
1425                         }
1426
1427                         free_a_printer( &printer, 2 );
1428                 }
1429         }
1430
1431         /* all done */
1432
1433         return;
1434 }
1435
1436 /****************************************************************
1437  _spoolss_OpenPrinter
1438 ****************************************************************/
1439
1440 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1441                             struct spoolss_OpenPrinter *r)
1442 {
1443         struct spoolss_OpenPrinterEx e;
1444         WERROR werr;
1445
1446         ZERO_STRUCT(e.in.userlevel);
1447
1448         e.in.printername        = r->in.printername;
1449         e.in.datatype           = r->in.datatype;
1450         e.in.devmode_ctr        = r->in.devmode_ctr;
1451         e.in.access_mask        = r->in.access_mask;
1452         e.in.level              = 0;
1453
1454         e.out.handle            = r->out.handle;
1455
1456         werr = _spoolss_OpenPrinterEx(p, &e);
1457
1458         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1459                 /* OpenPrinterEx returns this for a bad
1460                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1461                  * instead.
1462                  */
1463                 werr = WERR_INVALID_PRINTER_NAME;
1464         }
1465
1466         return werr;
1467 }
1468
1469 /********************************************************************
1470  ********************************************************************/
1471
1472 bool convert_devicemode(const char *printername,
1473                         const struct spoolss_DeviceMode *devmode,
1474                         NT_DEVICEMODE **pp_nt_devmode)
1475 {
1476         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1477
1478         /*
1479          * Ensure nt_devmode is a valid pointer
1480          * as we will be overwriting it.
1481          */
1482
1483         if (nt_devmode == NULL) {
1484                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1485                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1486                         return false;
1487         }
1488
1489         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1490         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1491
1492         nt_devmode->specversion         = devmode->specversion;
1493         nt_devmode->driverversion       = devmode->driverversion;
1494         nt_devmode->size                = devmode->size;
1495         nt_devmode->fields              = devmode->fields;
1496         nt_devmode->orientation         = devmode->orientation;
1497         nt_devmode->papersize           = devmode->papersize;
1498         nt_devmode->paperlength         = devmode->paperlength;
1499         nt_devmode->paperwidth          = devmode->paperwidth;
1500         nt_devmode->scale               = devmode->scale;
1501         nt_devmode->copies              = devmode->copies;
1502         nt_devmode->defaultsource       = devmode->defaultsource;
1503         nt_devmode->printquality        = devmode->printquality;
1504         nt_devmode->color               = devmode->color;
1505         nt_devmode->duplex              = devmode->duplex;
1506         nt_devmode->yresolution         = devmode->yresolution;
1507         nt_devmode->ttoption            = devmode->ttoption;
1508         nt_devmode->collate             = devmode->collate;
1509
1510         nt_devmode->logpixels           = devmode->logpixels;
1511         nt_devmode->bitsperpel          = devmode->bitsperpel;
1512         nt_devmode->pelswidth           = devmode->pelswidth;
1513         nt_devmode->pelsheight          = devmode->pelsheight;
1514         nt_devmode->displayflags        = devmode->displayflags;
1515         nt_devmode->displayfrequency    = devmode->displayfrequency;
1516         nt_devmode->icmmethod           = devmode->icmmethod;
1517         nt_devmode->icmintent           = devmode->icmintent;
1518         nt_devmode->mediatype           = devmode->mediatype;
1519         nt_devmode->dithertype          = devmode->dithertype;
1520         nt_devmode->reserved1           = devmode->reserved1;
1521         nt_devmode->reserved2           = devmode->reserved2;
1522         nt_devmode->panningwidth        = devmode->panningwidth;
1523         nt_devmode->panningheight       = devmode->panningheight;
1524
1525         /*
1526          * Only change private and driverextra if the incoming devmode
1527          * has a new one. JRA.
1528          */
1529
1530         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1531                 SAFE_FREE(nt_devmode->nt_dev_private);
1532                 nt_devmode->driverextra = devmode->__driverextra_length;
1533                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1534                         return false;
1535                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1536         }
1537
1538         *pp_nt_devmode = nt_devmode;
1539
1540         return true;
1541 }
1542
1543 /****************************************************************
1544  _spoolss_OpenPrinterEx
1545 ****************************************************************/
1546
1547 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1548                               struct spoolss_OpenPrinterEx *r)
1549 {
1550         int snum;
1551         Printer_entry *Printer=NULL;
1552
1553         if (!r->in.printername) {
1554                 return WERR_INVALID_PARAM;
1555         }
1556
1557         /* some sanity check because you can open a printer or a print server */
1558         /* aka: \\server\printer or \\server */
1559
1560         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1561
1562         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1563                 ZERO_STRUCTP(r->out.handle);
1564                 return WERR_INVALID_PARAM;
1565         }
1566
1567         Printer = find_printer_index_by_hnd(p, r->out.handle);
1568         if ( !Printer ) {
1569                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1570                         "handle we created for printer %s\n", r->in.printername));
1571                 close_printer_handle(p, r->out.handle);
1572                 ZERO_STRUCTP(r->out.handle);
1573                 return WERR_INVALID_PARAM;
1574         }
1575
1576         /*
1577          * First case: the user is opening the print server:
1578          *
1579          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1580          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1581          *
1582          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1583          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1584          * or if the user is listed in the smb.conf printer admin parameter.
1585          *
1586          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1587          * client view printer folder, but does not show the MSAPW.
1588          *
1589          * Note: this test needs code to check access rights here too. Jeremy
1590          * could you look at this?
1591          *
1592          * Second case: the user is opening a printer:
1593          * NT doesn't let us connect to a printer if the connecting user
1594          * doesn't have print permission.
1595          *
1596          * Third case: user is opening a Port Monitor
1597          * access checks same as opening a handle to the print server.
1598          */
1599
1600         switch (Printer->printer_type )
1601         {
1602         case SPLHND_SERVER:
1603         case SPLHND_PORTMON_TCP:
1604         case SPLHND_PORTMON_LOCAL:
1605                 /* Printserver handles use global struct... */
1606
1607                 snum = -1;
1608
1609                 /* Map standard access rights to object specific access rights */
1610
1611                 se_map_standard(&r->in.access_mask,
1612                                 &printserver_std_mapping);
1613
1614                 /* Deny any object specific bits that don't apply to print
1615                    servers (i.e printer and job specific bits) */
1616
1617                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1618
1619                 if (r->in.access_mask &
1620                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1621                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1622                         close_printer_handle(p, r->out.handle);
1623                         ZERO_STRUCTP(r->out.handle);
1624                         return WERR_ACCESS_DENIED;
1625                 }
1626
1627                 /* Allow admin access */
1628
1629                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1630                 {
1631                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1632
1633                         if (!lp_ms_add_printer_wizard()) {
1634                                 close_printer_handle(p, r->out.handle);
1635                                 ZERO_STRUCTP(r->out.handle);
1636                                 return WERR_ACCESS_DENIED;
1637                         }
1638
1639                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1640                            and not a printer admin, then fail */
1641
1642                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1643                             !user_has_privileges(p->server_info->ptok,
1644                                                  &se_printop ) &&
1645                             !token_contains_name_in_list(
1646                                     uidtoname(p->server_info->utok.uid),
1647                                     NULL, NULL,
1648                                     p->server_info->ptok,
1649                                     lp_printer_admin(snum))) {
1650                                 close_printer_handle(p, r->out.handle);
1651                                 ZERO_STRUCTP(r->out.handle);
1652                                 return WERR_ACCESS_DENIED;
1653                         }
1654
1655                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1656                 }
1657                 else
1658                 {
1659                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1660                 }
1661
1662                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1663                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1664
1665                 /* We fall through to return WERR_OK */
1666                 break;
1667
1668         case SPLHND_PRINTER:
1669                 /* NT doesn't let us connect to a printer if the connecting user
1670                    doesn't have print permission.  */
1671
1672                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1673                         close_printer_handle(p, r->out.handle);
1674                         ZERO_STRUCTP(r->out.handle);
1675                         return WERR_BADFID;
1676                 }
1677
1678                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1679
1680                 /* map an empty access mask to the minimum access mask */
1681                 if (r->in.access_mask == 0x0)
1682                         r->in.access_mask = PRINTER_ACCESS_USE;
1683
1684                 /*
1685                  * If we are not serving the printer driver for this printer,
1686                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1687                  * will keep NT clients happy  --jerry
1688                  */
1689
1690                 if (lp_use_client_driver(snum)
1691                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1692                 {
1693                         r->in.access_mask = PRINTER_ACCESS_USE;
1694                 }
1695
1696                 /* check smb.conf parameters and the the sec_desc */
1697
1698                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1699                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1700                         ZERO_STRUCTP(r->out.handle);
1701                         return WERR_ACCESS_DENIED;
1702                 }
1703
1704                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1705                                    p->server_info->ptok, snum) ||
1706                     !print_access_check(p->server_info, snum,
1707                                         r->in.access_mask)) {
1708                         DEBUG(3, ("access DENIED for printer open\n"));
1709                         close_printer_handle(p, r->out.handle);
1710                         ZERO_STRUCTP(r->out.handle);
1711                         return WERR_ACCESS_DENIED;
1712                 }
1713
1714                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1715                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1716                         close_printer_handle(p, r->out.handle);
1717                         ZERO_STRUCTP(r->out.handle);
1718                         return WERR_ACCESS_DENIED;
1719                 }
1720
1721                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1722                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1723                 else
1724                         r->in.access_mask = PRINTER_ACCESS_USE;
1725
1726                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1727                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1728
1729                 break;
1730
1731         default:
1732                 /* sanity check to prevent programmer error */
1733                 ZERO_STRUCTP(r->out.handle);
1734                 return WERR_BADFID;
1735         }
1736
1737         Printer->access_granted = r->in.access_mask;
1738
1739         /*
1740          * If the client sent a devmode in the OpenPrinter() call, then
1741          * save it here in case we get a job submission on this handle
1742          */
1743
1744          if ((Printer->printer_type != SPLHND_SERVER) &&
1745              r->in.devmode_ctr.devmode) {
1746                 convert_devicemode(Printer->sharename,
1747                                    r->in.devmode_ctr.devmode,
1748                                    &Printer->nt_devmode);
1749          }
1750
1751 #if 0   /* JERRY -- I'm doubtful this is really effective */
1752         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1753            optimization in Windows 2000 clients  --jerry */
1754
1755         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1756                 && (RA_WIN2K == get_remote_arch()) )
1757         {
1758                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1759                 sys_usleep( 500000 );
1760         }
1761 #endif
1762
1763         return WERR_OK;
1764 }
1765
1766 /****************************************************************************
1767 ****************************************************************************/
1768
1769 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1770                                               NT_PRINTER_INFO_LEVEL_2 *d)
1771 {
1772         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1773
1774         if (!r || !d) {
1775                 return false;
1776         }
1777
1778         d->attributes           = r->attributes;
1779         d->priority             = r->priority;
1780         d->default_priority     = r->defaultpriority;
1781         d->starttime            = r->starttime;
1782         d->untiltime            = r->untiltime;
1783         d->status               = r->status;
1784         d->cjobs                = r->cjobs;
1785
1786         fstrcpy(d->servername,  r->servername);
1787         fstrcpy(d->printername, r->printername);
1788         fstrcpy(d->sharename,   r->sharename);
1789         fstrcpy(d->portname,    r->portname);
1790         fstrcpy(d->drivername,  r->drivername);
1791         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1792         fstrcpy(d->location,    r->location);
1793         fstrcpy(d->sepfile,     r->sepfile);
1794         fstrcpy(d->printprocessor, r->printprocessor);
1795         fstrcpy(d->datatype,    r->datatype);
1796         fstrcpy(d->parameters,  r->parameters);
1797
1798         return true;
1799 }
1800
1801 /****************************************************************************
1802 ****************************************************************************/
1803
1804 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1805                                  NT_PRINTER_INFO_LEVEL *printer)
1806 {
1807         bool ret;
1808
1809         switch (info_ctr->level) {
1810         case 2:
1811                 /* allocate memory if needed.  Messy because
1812                    convert_printer_info is used to update an existing
1813                    printer or build a new one */
1814
1815                 if (!printer->info_2) {
1816                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1817                         if (!printer->info_2) {
1818                                 DEBUG(0,("convert_printer_info: "
1819                                         "talloc() failed!\n"));
1820                                 return false;
1821                         }
1822                 }
1823
1824                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1825                                                         printer->info_2);
1826                 printer->info_2->setuptime = time(NULL);
1827                 return ret;
1828         }
1829
1830         return false;
1831 }
1832
1833 /*******************************************************************
1834 ********************************************************************/
1835
1836 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1837 {
1838         int i;
1839
1840         if (!sarray) {
1841                 *farray = NULL;
1842                 return true;
1843         }
1844
1845         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1846         if (!*farray) {
1847                 return false;
1848         }
1849
1850         for (i=0; sarray[i] != NULL; i++) {
1851                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1852                 if (!*farray) {
1853                         return false;
1854                 }
1855                 fstrcpy((*farray)[i], sarray[i]);
1856         }
1857
1858         fstrcpy((*farray)[i], "");
1859
1860         return true;
1861 }
1862
1863 /*******************************************************************
1864 ********************************************************************/
1865
1866 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1867                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1868 {
1869         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1870
1871         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1872
1873         if (*p == NULL) {
1874                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1875                 if (*p == NULL) {
1876                         return false;
1877                 }
1878                 ZERO_STRUCTP(*p);
1879         }
1880
1881         d = *p;
1882
1883         d->cversion =                   r->version;
1884
1885         fstrcpy(d->name,                r->driver_name);
1886         fstrcpy(d->environment,         r->architecture);
1887         fstrcpy(d->driverpath,          r->driver_path);
1888         fstrcpy(d->datafile,            r->data_file);
1889         fstrcpy(d->configfile,          r->config_file);
1890         fstrcpy(d->helpfile,            r->help_file);
1891         fstrcpy(d->monitorname,         r->monitor_name);
1892         fstrcpy(d->defaultdatatype,     r->default_datatype);
1893
1894         DEBUGADD(8,( "version:         %d\n", d->cversion));
1895         DEBUGADD(8,( "name:            %s\n", d->name));
1896         DEBUGADD(8,( "environment:     %s\n", d->environment));
1897         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1898         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1899         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1900         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1901         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1902         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1903
1904         if (r->dependent_files) {
1905                 if (!string_array_to_fstring_array(r->dependent_files->string,
1906                                                    &d->dependentfiles)) {
1907                         SAFE_FREE(*p);
1908                         return false;
1909                 }
1910         }
1911
1912         return true;
1913 }
1914
1915 /*******************************************************************
1916 ********************************************************************/
1917
1918 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1919                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1920 {
1921         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1922
1923         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1924
1925         if (*p == NULL) {
1926                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1927                 if (*p == NULL) {
1928                         return false;
1929                 }
1930                 ZERO_STRUCTP(*p);
1931         }
1932
1933         d = *p;
1934
1935         d->version =                    r->version;
1936
1937         fstrcpy(d->name,                r->driver_name);
1938         fstrcpy(d->environment,         r->architecture);
1939         fstrcpy(d->driverpath,          r->driver_path);
1940         fstrcpy(d->datafile,            r->data_file);
1941         fstrcpy(d->configfile,          r->config_file);
1942         fstrcpy(d->helpfile,            r->help_file);
1943         fstrcpy(d->monitorname,         r->monitor_name);
1944         fstrcpy(d->defaultdatatype,     r->default_datatype);
1945
1946         DEBUGADD(8,( "version:         %d\n", d->version));
1947         DEBUGADD(8,( "name:            %s\n", d->name));
1948         DEBUGADD(8,( "environment:     %s\n", d->environment));
1949         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1950         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1951         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1952         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1953         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1954         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1955
1956         if (r->dependent_files) {
1957                 if (!string_array_to_fstring_array(r->dependent_files->string,
1958                                                    &d->dependentfiles)) {
1959                         goto error;
1960                 }
1961         }
1962
1963         if (r->previous_names) {
1964                 if (!string_array_to_fstring_array(r->previous_names->string,
1965                                                    &d->previousnames)) {
1966                         goto error;
1967                 }
1968         }
1969
1970         return true;
1971
1972  error:
1973         SAFE_FREE(*p);
1974         return false;
1975 }
1976
1977 /********************************************************************
1978  ********************************************************************/
1979
1980 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1981                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1982                                         uint32_t level)
1983 {
1984         switch (level) {
1985         case 3:
1986                 printer->info_3 = NULL;
1987                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1988                         return false;
1989                 }
1990                 break;
1991         case 6:
1992                 printer->info_6 = NULL;
1993                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1994                         return false;
1995                 }
1996                 break;
1997         default:
1998                 return false;
1999         }
2000
2001         return true;
2002 }
2003
2004 /********************************************************************
2005  * _spoolss_enddocprinter_internal.
2006  ********************************************************************/
2007
2008 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p,
2009                                               struct policy_handle *handle)
2010 {
2011         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2012         int snum;
2013
2014         if (!Printer) {
2015                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2016                 return WERR_BADFID;
2017         }
2018
2019         if (!get_printer_snum(p, handle, &snum, NULL))
2020                 return WERR_BADFID;
2021
2022         Printer->document_started = false;
2023         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2024         /* error codes unhandled so far ... */
2025
2026         return WERR_OK;
2027 }
2028
2029 /****************************************************************
2030  _spoolss_ClosePrinter
2031 ****************************************************************/
2032
2033 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2034                              struct spoolss_ClosePrinter *r)
2035 {
2036         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2037
2038         if (Printer && Printer->document_started)
2039                 _spoolss_enddocprinter_internal(p, r->in.handle);          /* print job was not closed */
2040
2041         if (!close_printer_handle(p, r->in.handle))
2042                 return WERR_BADFID;
2043
2044         /* clear the returned printer handle.  Observed behavior
2045            from Win2k server.  Don't think this really matters.
2046            Previous code just copied the value of the closed
2047            handle.    --jerry */
2048
2049         ZERO_STRUCTP(r->out.handle);
2050
2051         return WERR_OK;
2052 }
2053
2054 /****************************************************************
2055  _spoolss_DeletePrinter
2056 ****************************************************************/
2057
2058 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2059                               struct spoolss_DeletePrinter *r)
2060 {
2061         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2062         WERROR result;
2063
2064         if (Printer && Printer->document_started)
2065                 _spoolss_enddocprinter_internal(p, r->in.handle);  /* print job was not closed */
2066
2067         result = delete_printer_handle(p, r->in.handle);
2068
2069         update_c_setprinter(false);
2070
2071         return result;
2072 }
2073
2074 /*******************************************************************
2075  * static function to lookup the version id corresponding to an
2076  * long architecture string
2077  ******************************************************************/
2078
2079 static int get_version_id(const char *arch)
2080 {
2081         int i;
2082         struct table_node archi_table[]= {
2083
2084                 {"Windows 4.0",          "WIN40",       0 },
2085                 {"Windows NT x86",       "W32X86",      2 },
2086                 {"Windows NT R4000",     "W32MIPS",     2 },
2087                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2088                 {"Windows NT PowerPC",   "W32PPC",      2 },
2089                 {"Windows IA64",         "IA64",        3 },
2090                 {"Windows x64",          "x64",         3 },
2091                 {NULL,                   "",            -1 }
2092         };
2093
2094         for (i=0; archi_table[i].long_archi != NULL; i++)
2095         {
2096                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2097                         return (archi_table[i].version);
2098         }
2099
2100         return -1;
2101 }
2102
2103 /****************************************************************
2104  _spoolss_DeletePrinterDriver
2105 ****************************************************************/
2106
2107 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2108                                     struct spoolss_DeletePrinterDriver *r)
2109 {
2110         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2111         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2112         int                             version;
2113         WERROR                          status;
2114         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2115         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2116
2117         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2118            and not a printer admin, then fail */
2119
2120         if ( (p->server_info->utok.uid != sec_initial_uid())
2121                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2122                 && !token_contains_name_in_list(
2123                         uidtoname(p->server_info->utok.uid), NULL,
2124                         NULL, p->server_info->ptok,
2125                         lp_printer_admin(-1)) )
2126         {
2127                 return WERR_ACCESS_DENIED;
2128         }
2129
2130         /* check that we have a valid driver name first */
2131
2132         if ((version = get_version_id(r->in.architecture)) == -1)
2133                 return WERR_INVALID_ENVIRONMENT;
2134
2135         ZERO_STRUCT(info);
2136         ZERO_STRUCT(info_win2k);
2137
2138         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2139                                                 r->in.architecture,
2140                                                 version)))
2141         {
2142                 /* try for Win2k driver if "Windows NT x86" */
2143
2144                 if ( version == 2 ) {
2145                         version = 3;
2146                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2147                                                                 r->in.driver,
2148                                                                 r->in.architecture,
2149                                                                 version))) {
2150                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2151                                 goto done;
2152                         }
2153                 }
2154                 /* otherwise it was a failure */
2155                 else {
2156                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2157                         goto done;
2158                 }
2159
2160         }
2161
2162         if (printer_driver_in_use(info.info_3)) {
2163                 status = WERR_PRINTER_DRIVER_IN_USE;
2164                 goto done;
2165         }
2166
2167         if ( version == 2 )
2168         {
2169                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2170                                                        r->in.driver,
2171                                                        r->in.architecture, 3)))
2172                 {
2173                         /* if we get to here, we now have 2 driver info structures to remove */
2174                         /* remove the Win2k driver first*/
2175
2176                         status_win2k = delete_printer_driver(
2177                                 p, info_win2k.info_3, 3, false);
2178                         free_a_printer_driver( info_win2k, 3 );
2179
2180                         /* this should not have failed---if it did, report to client */
2181                         if ( !W_ERROR_IS_OK(status_win2k) )
2182                         {
2183                                 status = status_win2k;
2184                                 goto done;
2185                         }
2186                 }
2187         }
2188
2189         status = delete_printer_driver(p, info.info_3, version, false);
2190
2191         /* if at least one of the deletes succeeded return OK */
2192
2193         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2194                 status = WERR_OK;
2195
2196 done:
2197         free_a_printer_driver( info, 3 );
2198
2199         return status;
2200 }
2201
2202 /****************************************************************
2203  _spoolss_DeletePrinterDriverEx
2204 ****************************************************************/
2205
2206 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2207                                       struct spoolss_DeletePrinterDriverEx *r)
2208 {
2209         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2210         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2211         int                             version;
2212         bool                            delete_files;
2213         WERROR                          status;
2214         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2215         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2216
2217         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2218            and not a printer admin, then fail */
2219
2220         if ( (p->server_info->utok.uid != sec_initial_uid())
2221                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2222                 && !token_contains_name_in_list(
2223                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2224                         p->server_info->ptok, lp_printer_admin(-1)) )
2225         {
2226                 return WERR_ACCESS_DENIED;
2227         }
2228
2229         /* check that we have a valid driver name first */
2230         if ((version = get_version_id(r->in.architecture)) == -1) {
2231                 /* this is what NT returns */
2232                 return WERR_INVALID_ENVIRONMENT;
2233         }
2234
2235         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2236                 version = r->in.version;
2237
2238         ZERO_STRUCT(info);
2239         ZERO_STRUCT(info_win2k);
2240
2241         status = get_a_printer_driver(&info, 3, r->in.driver,
2242                                       r->in.architecture, version);
2243
2244         if ( !W_ERROR_IS_OK(status) )
2245         {
2246                 /*
2247                  * if the client asked for a specific version,
2248                  * or this is something other than Windows NT x86,
2249                  * then we've failed
2250                  */
2251
2252                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2253                         goto done;
2254
2255                 /* try for Win2k driver if "Windows NT x86" */
2256
2257                 version = 3;
2258                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2259                                                         r->in.architecture,
2260                                                         version))) {
2261                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2262                         goto done;
2263                 }
2264         }
2265
2266         if ( printer_driver_in_use(info.info_3) ) {
2267                 status = WERR_PRINTER_DRIVER_IN_USE;
2268                 goto done;
2269         }
2270
2271         /*
2272          * we have a couple of cases to consider.
2273          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2274          *     then the delete should fail if **any** files overlap with
2275          *     other drivers
2276          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2277          *     non-overlapping files
2278          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2279          *     is set, the do not delete any files
2280          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2281          */
2282
2283         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2284
2285         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2286
2287         if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2288                 /* no idea of the correct error here */
2289                 status = WERR_ACCESS_DENIED;
2290                 goto done;
2291         }
2292
2293
2294         /* also check for W32X86/3 if necessary; maybe we already have? */
2295
2296         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2297                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2298                                                        r->in.driver,
2299                                                        r->in.architecture, 3)))
2300                 {
2301
2302                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2303                                 /* no idea of the correct error here */
2304                                 free_a_printer_driver( info_win2k, 3 );
2305                                 status = WERR_ACCESS_DENIED;
2306                                 goto done;
2307                         }
2308
2309                         /* if we get to here, we now have 2 driver info structures to remove */
2310                         /* remove the Win2k driver first*/
2311
2312                         status_win2k = delete_printer_driver(
2313                                 p, info_win2k.info_3, 3, delete_files);
2314                         free_a_printer_driver( info_win2k, 3 );
2315
2316                         /* this should not have failed---if it did, report to client */
2317
2318                         if ( !W_ERROR_IS_OK(status_win2k) )
2319                                 goto done;
2320                 }
2321         }
2322
2323         status = delete_printer_driver(p, info.info_3, version, delete_files);
2324
2325         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2326                 status = WERR_OK;
2327 done:
2328         free_a_printer_driver( info, 3 );
2329
2330         return status;
2331 }
2332
2333
2334 /****************************************************************************
2335  Internal routine for removing printerdata
2336  ***************************************************************************/
2337
2338 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2339 {
2340         return delete_printer_data( printer->info_2, key, value );
2341 }
2342
2343 /****************************************************************************
2344  Internal routine for storing printerdata
2345  ***************************************************************************/
2346
2347 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2348                           const char *key, const char *value,
2349                           uint32_t type, uint8_t *data, int real_len)
2350 {
2351         /* the registry objects enforce uniqueness based on value name */
2352
2353         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2354 }
2355
2356 /********************************************************************
2357  GetPrinterData on a printer server Handle.
2358 ********************************************************************/
2359
2360 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2361                                             const char *value,
2362                                             enum winreg_Type *type,
2363                                             union spoolss_PrinterData *data)
2364 {
2365         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2366
2367         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2368                 *type = REG_DWORD;
2369                 data->value = 0x00;
2370                 return WERR_OK;
2371         }
2372
2373         if (!StrCaseCmp(value, "BeepEnabled")) {
2374                 *type = REG_DWORD;
2375                 data->value = 0x00;
2376                 return WERR_OK;
2377         }
2378
2379         if (!StrCaseCmp(value, "EventLog")) {
2380                 *type = REG_DWORD;
2381                 /* formally was 0x1b */
2382                 data->value = 0x00;
2383                 return WERR_OK;
2384         }
2385
2386         if (!StrCaseCmp(value, "NetPopup")) {
2387                 *type = REG_DWORD;
2388                 data->value = 0x00;
2389                 return WERR_OK;
2390         }
2391
2392         if (!StrCaseCmp(value, "MajorVersion")) {
2393                 *type = REG_DWORD;
2394
2395                 /* Windows NT 4.0 seems to not allow uploading of drivers
2396                    to a server that reports 0x3 as the MajorVersion.
2397                    need to investigate more how Win2k gets around this .
2398                    -- jerry */
2399
2400                 if (RA_WINNT == get_remote_arch()) {
2401                         data->value = 0x02;
2402                 } else {
2403                         data->value = 0x03;
2404                 }
2405
2406                 return WERR_OK;
2407         }
2408
2409         if (!StrCaseCmp(value, "MinorVersion")) {
2410                 *type = REG_DWORD;
2411                 data->value = 0x00;
2412                 return WERR_OK;
2413         }
2414
2415         /* REG_BINARY
2416          *  uint32_t size        = 0x114
2417          *  uint32_t major       = 5
2418          *  uint32_t minor       = [0|1]
2419          *  uint32_t build       = [2195|2600]
2420          *  extra unicode string = e.g. "Service Pack 3"
2421          */
2422         if (!StrCaseCmp(value, "OSVersion")) {
2423                 DATA_BLOB blob;
2424                 enum ndr_err_code ndr_err;
2425                 struct spoolss_OSVersion os;
2426
2427                 os.major                = 5;    /* Windows 2000 == 5.0 */
2428                 os.minor                = 0;
2429                 os.build                = 2195; /* build */
2430                 os.extra_string         = "";   /* leave extra string empty */
2431
2432                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2433                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2434                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2435                         return WERR_GENERAL_FAILURE;
2436                 }
2437
2438                 *type = REG_BINARY;
2439                 data->binary = blob;
2440
2441                 return WERR_OK;
2442         }
2443
2444
2445         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2446                 *type = REG_SZ;
2447
2448                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2449                 W_ERROR_HAVE_NO_MEMORY(data->string);
2450
2451                 return WERR_OK;
2452         }
2453
2454         if (!StrCaseCmp(value, "Architecture")) {
2455                 *type = REG_SZ;
2456
2457                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2458                 W_ERROR_HAVE_NO_MEMORY(data->string);
2459
2460                 return WERR_OK;
2461         }
2462
2463         if (!StrCaseCmp(value, "DsPresent")) {
2464                 *type = REG_DWORD;
2465
2466                 /* only show the publish check box if we are a
2467                    member of a AD domain */
2468
2469                 if (lp_security() == SEC_ADS) {
2470                         data->value = 0x01;
2471                 } else {
2472                         data->value = 0x00;
2473                 }
2474                 return WERR_OK;
2475         }
2476
2477         if (!StrCaseCmp(value, "DNSMachineName")) {
2478                 const char *hostname = get_mydnsfullname();
2479
2480                 if (!hostname) {
2481                         return WERR_BADFILE;
2482                 }
2483
2484                 *type = REG_SZ;
2485                 data->string = talloc_strdup(mem_ctx, hostname);
2486                 W_ERROR_HAVE_NO_MEMORY(data->string);
2487
2488                 return WERR_OK;
2489         }
2490
2491         return WERR_INVALID_PARAM;
2492 }
2493
2494 /****************************************************************
2495  _spoolss_GetPrinterData
2496 ****************************************************************/
2497
2498 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2499                                struct spoolss_GetPrinterData *r)
2500 {
2501         WERROR result;
2502         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2503         NT_PRINTER_INFO_LEVEL *printer = NULL;
2504         int snum = 0;
2505
2506         /*
2507          * Reminder: when it's a string, the length is in BYTES
2508          * even if UNICODE is negociated.
2509          *
2510          * JFM, 4/19/1999
2511          */
2512
2513         /* in case of problem, return some default values */
2514
2515         *r->out.needed  = 0;
2516         *r->out.type    = 0;
2517
2518         DEBUG(4,("_spoolss_GetPrinterData\n"));
2519
2520         if (!Printer) {
2521                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2522                         OUR_HANDLE(r->in.handle)));
2523                 result = WERR_BADFID;
2524                 goto done;
2525         }
2526
2527         if (Printer->printer_type == SPLHND_SERVER) {
2528                 result = getprinterdata_printer_server(p->mem_ctx,
2529                                                        r->in.value_name,
2530                                                        r->out.type,
2531                                                        r->out.data);
2532         } else {
2533                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2534                         result = WERR_BADFID;
2535                         goto done;
2536                 }
2537
2538                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2539                 if (!W_ERROR_IS_OK(result)) {
2540                         goto done;
2541                 }
2542
2543                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2544
2545                 if (strequal(r->in.value_name, "ChangeId")) {
2546                         *r->out.type = REG_DWORD;
2547                         r->out.data->value = printer->info_2->changeid;
2548                         result = WERR_OK;
2549                 } else {
2550                         struct regval_blob *v;
2551                         DATA_BLOB blob;
2552
2553                         v = get_printer_data(printer->info_2,
2554                                              SPOOL_PRINTERDATA_KEY,
2555                                              r->in.value_name);
2556                         if (!v) {
2557                                 result = WERR_BADFILE;
2558                                 goto done;
2559                         }
2560
2561                         *r->out.type = v->type;
2562
2563                         blob = data_blob_const(v->data_p, v->size);
2564
2565                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2566                                                           r->out.data,
2567                                                           *r->out.type);
2568                 }
2569         }
2570
2571  done:
2572         /* cleanup & exit */
2573
2574         if (printer) {
2575                 free_a_printer(&printer, 2);
2576         }
2577
2578         if (!W_ERROR_IS_OK(result)) {
2579                 return result;
2580         }
2581
2582         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2583         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2584         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2585
2586         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2587 }
2588
2589 /*********************************************************
2590  Connect to the client machine.
2591 **********************************************************/
2592
2593 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2594                         struct sockaddr_storage *client_ss, const char *remote_machine)
2595 {
2596         NTSTATUS ret;
2597         struct cli_state *the_cli;
2598         struct sockaddr_storage rm_addr;
2599
2600         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2601                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2602                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2603                         return false;
2604                 }
2605
2606                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2607                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2608                         return false;
2609                 }
2610         } else {
2611                 char addr[INET6_ADDRSTRLEN];
2612                 rm_addr = *client_ss;
2613                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2614                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2615                         addr));
2616         }
2617
2618         /* setup the connection */
2619
2620         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2621                 &rm_addr, 0, "IPC$", "IPC",
2622                 "", /* username */
2623                 "", /* domain */
2624                 "", /* password */
2625                 0, lp_client_signing(), NULL );
2626
2627         if ( !NT_STATUS_IS_OK( ret ) ) {
2628                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2629                         remote_machine ));
2630                 return false;
2631         }
2632
2633         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2634                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2635                 cli_shutdown(the_cli);
2636                 return false;
2637         }
2638
2639         /*
2640          * Ok - we have an anonymous connection to the IPC$ share.
2641          * Now start the NT Domain stuff :-).
2642          */
2643
2644         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2645         if (!NT_STATUS_IS_OK(ret)) {
2646                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2647                         remote_machine, nt_errstr(ret)));
2648                 cli_shutdown(the_cli);
2649                 return false;
2650         }
2651
2652         return true;
2653 }
2654
2655 /***************************************************************************
2656  Connect to the client.
2657 ****************************************************************************/
2658
2659 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2660                                         uint32_t localprinter, uint32_t type,
2661                                         struct policy_handle *handle,
2662                                         struct sockaddr_storage *client_ss)
2663 {
2664         WERROR result;
2665         NTSTATUS status;
2666
2667         /*
2668          * If it's the first connection, contact the client
2669          * and connect to the IPC$ share anonymously
2670          */
2671         if (smb_connections==0) {
2672                 fstring unix_printer;
2673
2674                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2675
2676                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2677                         return false;
2678
2679                 messaging_register(smbd_messaging_context(), NULL,
2680                                    MSG_PRINTER_NOTIFY2,
2681                                    receive_notify2_message_list);
2682                 /* Tell the connections db we're now interested in printer
2683                  * notify messages. */
2684                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2685         }
2686
2687         /*
2688          * Tell the specific printing tdb we want messages for this printer
2689          * by registering our PID.
2690          */
2691
2692         if (!print_notify_register_pid(snum))
2693                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2694
2695         smb_connections++;
2696
2697         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2698                                                  printer,
2699                                                  localprinter,
2700                                                  type,
2701                                                  0,
2702                                                  NULL,
2703                                                  handle,
2704                                                  &result);
2705         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2706                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2707                         win_errstr(result)));
2708
2709         return (W_ERROR_IS_OK(result));
2710 }
2711
2712 /****************************************************************
2713  ****************************************************************/
2714
2715 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2716                                                              const struct spoolss_NotifyOption *r)
2717 {
2718         struct spoolss_NotifyOption *option;
2719         uint32_t i,k;
2720
2721         if (!r) {
2722                 return NULL;
2723         }
2724
2725         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2726         if (!option) {
2727                 return NULL;
2728         }
2729
2730         *option = *r;
2731
2732         if (!option->count) {
2733                 return option;
2734         }
2735
2736         option->types = talloc_zero_array(option,
2737                 struct spoolss_NotifyOptionType, option->count);
2738         if (!option->types) {
2739                 talloc_free(option);
2740                 return NULL;
2741         }
2742
2743         for (i=0; i < option->count; i++) {
2744                 option->types[i] = r->types[i];
2745
2746                 if (option->types[i].count) {
2747                         option->types[i].fields = talloc_zero_array(option,
2748                                 union spoolss_Field, option->types[i].count);
2749                         if (!option->types[i].fields) {
2750                                 talloc_free(option);
2751                                 return NULL;
2752                         }
2753                         for (k=0; k<option->types[i].count; k++) {
2754                                 option->types[i].fields[k] =
2755                                         r->types[i].fields[k];
2756                         }
2757                 }
2758         }
2759
2760         return option;
2761 }
2762
2763 /****************************************************************
2764  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2765  *
2766  * before replying OK: status=0 a rpc call is made to the workstation
2767  * asking ReplyOpenPrinter
2768  *
2769  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2770  * called from api_spoolss_rffpcnex
2771 ****************************************************************/
2772
2773 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2774                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2775 {
2776         int snum = -1;
2777         struct spoolss_NotifyOption *option = r->in.notify_options;
2778         struct sockaddr_storage client_ss;
2779
2780         /* store the notify value in the printer struct */
2781
2782         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2783
2784         if (!Printer) {
2785                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2786                         "Invalid handle (%s:%u:%u).\n",
2787                         OUR_HANDLE(r->in.handle)));
2788                 return WERR_BADFID;
2789         }
2790
2791         Printer->notify.flags           = r->in.flags;
2792         Printer->notify.options         = r->in.options;
2793         Printer->notify.printerlocal    = r->in.printer_local;
2794
2795         TALLOC_FREE(Printer->notify.option);
2796         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2797
2798         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2799
2800         /* Connect to the client machine and send a ReplyOpenPrinter */
2801
2802         if ( Printer->printer_type == SPLHND_SERVER)
2803                 snum = -1;
2804         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2805                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2806                 return WERR_BADFID;
2807
2808         if (!interpret_string_addr(&client_ss, p->client_address,
2809                                    AI_NUMERICHOST)) {
2810                 return WERR_SERVER_UNAVAILABLE;
2811         }
2812
2813         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2814                                         Printer->notify.printerlocal, 1,
2815                                         &Printer->notify.client_hnd, &client_ss))
2816                 return WERR_SERVER_UNAVAILABLE;
2817
2818         Printer->notify.client_connected = true;
2819
2820         return WERR_OK;
2821 }
2822
2823 /*******************************************************************
2824  * fill a notify_info_data with the servername
2825  ********************************************************************/
2826
2827 void spoolss_notify_server_name(int snum,
2828                                        struct spoolss_Notify *data,
2829                                        print_queue_struct *queue,
2830                                        NT_PRINTER_INFO_LEVEL *printer,
2831                                        TALLOC_CTX *mem_ctx)
2832 {
2833         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2834 }
2835
2836 /*******************************************************************
2837  * fill a notify_info_data with the printername (not including the servername).
2838  ********************************************************************/
2839
2840 void spoolss_notify_printer_name(int snum,
2841                                         struct spoolss_Notify *data,
2842                                         print_queue_struct *queue,
2843                                         NT_PRINTER_INFO_LEVEL *printer,
2844                                         TALLOC_CTX *mem_ctx)
2845 {
2846         /* the notify name should not contain the \\server\ part */
2847         char *p = strrchr(printer->info_2->printername, '\\');
2848
2849         if (!p) {
2850                 p = printer->info_2->printername;
2851         } else {
2852                 p++;
2853         }
2854
2855         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2856 }
2857
2858 /*******************************************************************
2859  * fill a notify_info_data with the servicename
2860  ********************************************************************/
2861
2862 void spoolss_notify_share_name(int snum,
2863                                       struct spoolss_Notify *data,
2864                                       print_queue_struct *queue,
2865                                       NT_PRINTER_INFO_LEVEL *printer,
2866                                       TALLOC_CTX *mem_ctx)
2867 {
2868         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2869 }
2870
2871 /*******************************************************************
2872  * fill a notify_info_data with the port name
2873  ********************************************************************/
2874
2875 void spoolss_notify_port_name(int snum,
2876                                      struct spoolss_Notify *data,
2877                                      print_queue_struct *queue,
2878                                      NT_PRINTER_INFO_LEVEL *printer,
2879                                      TALLOC_CTX *mem_ctx)
2880 {
2881         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2882 }
2883
2884 /*******************************************************************
2885  * fill a notify_info_data with the printername
2886  * but it doesn't exist, have to see what to do
2887  ********************************************************************/
2888
2889 void spoolss_notify_driver_name(int snum,
2890                                        struct spoolss_Notify *data,
2891                                        print_queue_struct *queue,
2892                                        NT_PRINTER_INFO_LEVEL *printer,
2893                                        TALLOC_CTX *mem_ctx)
2894 {
2895         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2896 }
2897
2898 /*******************************************************************
2899  * fill a notify_info_data with the comment
2900  ********************************************************************/
2901
2902 void spoolss_notify_comment(int snum,
2903                                    struct spoolss_Notify *data,
2904                                    print_queue_struct *queue,
2905                                    NT_PRINTER_INFO_LEVEL *printer,
2906                                    TALLOC_CTX *mem_ctx)
2907 {
2908         char *p;
2909
2910         if (*printer->info_2->comment == '\0') {
2911                 p = lp_comment(snum);
2912         } else {
2913                 p = printer->info_2->comment;
2914         }
2915
2916         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2917 }
2918
2919 /*******************************************************************
2920  * fill a notify_info_data with the comment
2921  * location = "Room 1, floor 2, building 3"
2922  ********************************************************************/
2923
2924 void spoolss_notify_location(int snum,
2925                                     struct spoolss_Notify *data,
2926                                     print_queue_struct *queue,
2927                                     NT_PRINTER_INFO_LEVEL *printer,
2928                                     TALLOC_CTX *mem_ctx)
2929 {
2930         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2931 }
2932
2933 /*******************************************************************
2934  * fill a notify_info_data with the device mode
2935  * jfm:xxxx don't to it for know but that's a real problem !!!
2936  ********************************************************************/
2937
2938 static void spoolss_notify_devmode(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         /* for a dummy implementation we have to zero the fields */
2945         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the separator file name
2950  ********************************************************************/
2951
2952 void spoolss_notify_sepfile(int snum,
2953                                    struct spoolss_Notify *data,
2954                                    print_queue_struct *queue,
2955                                    NT_PRINTER_INFO_LEVEL *printer,
2956                                    TALLOC_CTX *mem_ctx)
2957 {
2958         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2959 }
2960
2961 /*******************************************************************
2962  * fill a notify_info_data with the print processor
2963  * jfm:xxxx return always winprint to indicate we don't do anything to it
2964  ********************************************************************/
2965
2966 void spoolss_notify_print_processor(int snum,
2967                                            struct spoolss_Notify *data,
2968                                            print_queue_struct *queue,
2969                                            NT_PRINTER_INFO_LEVEL *printer,
2970                                            TALLOC_CTX *mem_ctx)
2971 {
2972         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2973 }
2974
2975 /*******************************************************************
2976  * fill a notify_info_data with the print processor options
2977  * jfm:xxxx send an empty string
2978  ********************************************************************/
2979
2980 void spoolss_notify_parameters(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_STRING(data, printer->info_2->parameters);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the data type
2991  * jfm:xxxx always send RAW as data type
2992  ********************************************************************/
2993
2994 void spoolss_notify_datatype(int snum,
2995                                     struct spoolss_Notify *data,
2996                                     print_queue_struct *queue,
2997                                     NT_PRINTER_INFO_LEVEL *printer,
2998                                     TALLOC_CTX *mem_ctx)
2999 {
3000         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3001 }
3002
3003 /*******************************************************************
3004  * fill a notify_info_data with the security descriptor
3005  * jfm:xxxx send an null pointer to say no security desc
3006  * have to implement security before !
3007  ********************************************************************/
3008
3009 static void spoolss_notify_security_desc(int snum,
3010                                          struct spoolss_Notify *data,
3011                                          print_queue_struct *queue,
3012                                          NT_PRINTER_INFO_LEVEL *printer,
3013                                          TALLOC_CTX *mem_ctx)
3014 {
3015         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3016                                           printer->info_2->secdesc_buf->sd_size,
3017                                           printer->info_2->secdesc_buf->sd);
3018 }
3019
3020 /*******************************************************************
3021  * fill a notify_info_data with the attributes
3022  * jfm:xxxx a samba printer is always shared
3023  ********************************************************************/
3024
3025 void spoolss_notify_attributes(int snum,
3026                                       struct spoolss_Notify *data,
3027                                       print_queue_struct *queue,
3028                                       NT_PRINTER_INFO_LEVEL *printer,
3029                                       TALLOC_CTX *mem_ctx)
3030 {
3031         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3032 }
3033
3034 /*******************************************************************
3035  * fill a notify_info_data with the priority
3036  ********************************************************************/
3037
3038 static void spoolss_notify_priority(int snum,
3039                                     struct spoolss_Notify *data,
3040                                     print_queue_struct *queue,
3041                                     NT_PRINTER_INFO_LEVEL *printer,
3042                                     TALLOC_CTX *mem_ctx)
3043 {
3044         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3045 }
3046
3047 /*******************************************************************
3048  * fill a notify_info_data with the default priority
3049  ********************************************************************/
3050
3051 static void spoolss_notify_default_priority(int snum,
3052                                             struct spoolss_Notify *data,
3053                                             print_queue_struct *queue,
3054                                             NT_PRINTER_INFO_LEVEL *printer,
3055                                             TALLOC_CTX *mem_ctx)
3056 {
3057         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3058 }
3059
3060 /*******************************************************************
3061  * fill a notify_info_data with the start time
3062  ********************************************************************/
3063
3064 static void spoolss_notify_start_time(int snum,
3065                                       struct spoolss_Notify *data,
3066                                       print_queue_struct *queue,
3067                                       NT_PRINTER_INFO_LEVEL *printer,
3068                                       TALLOC_CTX *mem_ctx)
3069 {
3070         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3071 }
3072
3073 /*******************************************************************
3074  * fill a notify_info_data with the until time
3075  ********************************************************************/
3076
3077 static void spoolss_notify_until_time(int snum,
3078                                       struct spoolss_Notify *data,
3079                                       print_queue_struct *queue,
3080                                       NT_PRINTER_INFO_LEVEL *printer,
3081                                       TALLOC_CTX *mem_ctx)
3082 {
3083         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3084 }
3085
3086 /*******************************************************************
3087  * fill a notify_info_data with the status
3088  ********************************************************************/
3089
3090 static void spoolss_notify_status(int snum,
3091                                   struct spoolss_Notify *data,
3092                                   print_queue_struct *queue,
3093                                   NT_PRINTER_INFO_LEVEL *printer,
3094                                   TALLOC_CTX *mem_ctx)
3095 {
3096         print_status_struct status;
3097
3098         print_queue_length(snum, &status);
3099         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3100 }
3101
3102 /*******************************************************************
3103  * fill a notify_info_data with the number of jobs queued
3104  ********************************************************************/
3105
3106 void spoolss_notify_cjobs(int snum,
3107                                  struct spoolss_Notify *data,
3108                                  print_queue_struct *queue,
3109                                  NT_PRINTER_INFO_LEVEL *printer,
3110                                  TALLOC_CTX *mem_ctx)
3111 {
3112         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3113 }
3114
3115 /*******************************************************************
3116  * fill a notify_info_data with the average ppm
3117  ********************************************************************/
3118
3119 static void spoolss_notify_average_ppm(int snum,
3120                                        struct spoolss_Notify *data,
3121                                        print_queue_struct *queue,
3122                                        NT_PRINTER_INFO_LEVEL *printer,
3123                                        TALLOC_CTX *mem_ctx)
3124 {
3125         /* always respond 8 pages per minutes */
3126         /* a little hard ! */
3127         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3128 }
3129
3130 /*******************************************************************
3131  * fill a notify_info_data with username
3132  ********************************************************************/
3133
3134 static void spoolss_notify_username(int snum,
3135                                     struct spoolss_Notify *data,
3136                                     print_queue_struct *queue,
3137                                     NT_PRINTER_INFO_LEVEL *printer,
3138                                     TALLOC_CTX *mem_ctx)
3139 {
3140         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3141 }
3142
3143 /*******************************************************************
3144  * fill a notify_info_data with job status
3145  ********************************************************************/
3146
3147 static void spoolss_notify_job_status(int snum,
3148                                       struct spoolss_Notify *data,
3149                                       print_queue_struct *queue,
3150                                       NT_PRINTER_INFO_LEVEL *printer,
3151                                       TALLOC_CTX *mem_ctx)
3152 {
3153         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3154 }
3155
3156 /*******************************************************************
3157  * fill a notify_info_data with job name
3158  ********************************************************************/
3159
3160 static void spoolss_notify_job_name(int snum,
3161                                     struct spoolss_Notify *data,
3162                                     print_queue_struct *queue,
3163                                     NT_PRINTER_INFO_LEVEL *printer,
3164                                     TALLOC_CTX *mem_ctx)
3165 {
3166         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3167 }
3168
3169 /*******************************************************************
3170  * fill a notify_info_data with job status
3171  ********************************************************************/
3172
3173 static void spoolss_notify_job_status_string(int snum,
3174                                              struct spoolss_Notify *data,
3175                                              print_queue_struct *queue,
3176                                              NT_PRINTER_INFO_LEVEL *printer,
3177                                              TALLOC_CTX *mem_ctx)
3178 {
3179         /*
3180          * Now we're returning job status codes we just return a "" here. JRA.
3181          */
3182
3183         const char *p = "";
3184
3185 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3186         p = "unknown";
3187
3188         switch (queue->status) {
3189         case LPQ_QUEUED:
3190                 p = "Queued";
3191                 break;
3192         case LPQ_PAUSED:
3193                 p = "";    /* NT provides the paused string */
3194                 break;
3195         case LPQ_SPOOLING:
3196                 p = "Spooling";
3197                 break;
3198         case LPQ_PRINTING:
3199                 p = "Printing";
3200                 break;
3201         }
3202 #endif /* NO LONGER NEEDED. */
3203
3204         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3205 }
3206
3207 /*******************************************************************
3208  * fill a notify_info_data with job time
3209  ********************************************************************/
3210
3211 static void spoolss_notify_job_time(int snum,
3212                                     struct spoolss_Notify *data,
3213                                     print_queue_struct *queue,
3214                                     NT_PRINTER_INFO_LEVEL *printer,
3215                                     TALLOC_CTX *mem_ctx)
3216 {
3217         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3218 }
3219
3220 /*******************************************************************
3221  * fill a notify_info_data with job size
3222  ********************************************************************/
3223
3224 static void spoolss_notify_job_size(int snum,
3225                                     struct spoolss_Notify *data,
3226                                     print_queue_struct *queue,
3227                                     NT_PRINTER_INFO_LEVEL *printer,
3228                                     TALLOC_CTX *mem_ctx)
3229 {
3230         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3231 }
3232
3233 /*******************************************************************
3234  * fill a notify_info_data with page info
3235  ********************************************************************/
3236 static void spoolss_notify_total_pages(int snum,
3237                                 struct spoolss_Notify *data,
3238                                 print_queue_struct *queue,
3239                                 NT_PRINTER_INFO_LEVEL *printer,
3240                                 TALLOC_CTX *mem_ctx)
3241 {
3242         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3243 }
3244
3245 /*******************************************************************
3246  * fill a notify_info_data with pages printed info.
3247  ********************************************************************/
3248 static void spoolss_notify_pages_printed(int snum,
3249                                 struct spoolss_Notify *data,
3250                                 print_queue_struct *queue,
3251                                 NT_PRINTER_INFO_LEVEL *printer,
3252                                 TALLOC_CTX *mem_ctx)
3253 {
3254         /* Add code when back-end tracks this */
3255         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3256 }
3257
3258 /*******************************************************************
3259  Fill a notify_info_data with job position.
3260  ********************************************************************/
3261
3262 static void spoolss_notify_job_position(int snum,
3263                                         struct spoolss_Notify *data,
3264                                         print_queue_struct *queue,
3265                                         NT_PRINTER_INFO_LEVEL *printer,
3266                                         TALLOC_CTX *mem_ctx)
3267 {
3268         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3269 }
3270
3271 /*******************************************************************
3272  Fill a notify_info_data with submitted time.
3273  ********************************************************************/
3274
3275 static void spoolss_notify_submitted_time(int snum,
3276                                           struct spoolss_Notify *data,
3277                                           print_queue_struct *queue,
3278                                           NT_PRINTER_INFO_LEVEL *printer,
3279                                           TALLOC_CTX *mem_ctx)
3280 {
3281         data->data.string.string = NULL;
3282         data->data.string.size = 0;
3283
3284         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3285                                &data->data.string.string,
3286                                &data->data.string.size);
3287
3288 }
3289
3290 struct s_notify_info_data_table
3291 {
3292         enum spoolss_NotifyType type;
3293         uint16_t field;
3294         const char *name;
3295         enum spoolss_NotifyTable variable_type;
3296         void (*fn) (int snum, struct spoolss_Notify *data,
3297                     print_queue_struct *queue,
3298                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3299 };
3300
3301 /* A table describing the various print notification constants and
3302    whether the notification data is a pointer to a variable sized
3303    buffer, a one value uint32_t or a two value uint32_t. */
3304
3305 static const struct s_notify_info_data_table notify_info_data_table[] =
3306 {
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3329 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3330 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3333 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3334 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3335 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3336 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3337 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3338 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3339 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3340 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3341 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3342 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3343 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3344 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3345 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3346 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3347 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3348 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3349 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3350 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3351 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3352 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3353 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3354 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3355 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3356 };
3357
3358 /*******************************************************************
3359  Return the variable_type of info_data structure.
3360 ********************************************************************/
3361
3362 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3363                                                   uint16_t field)
3364 {
3365         int i=0;
3366
3367         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3368                 if ( (notify_info_data_table[i].type == type) &&
3369                      (notify_info_data_table[i].field == field) ) {
3370                         return notify_info_data_table[i].variable_type;
3371                 }
3372         }
3373
3374         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3375
3376         return 0;
3377 }
3378
3379 /****************************************************************************
3380 ****************************************************************************/
3381
3382 static bool search_notify(enum spoolss_NotifyType type,
3383                           uint16_t field,
3384                           int *value)
3385 {
3386         int i;
3387
3388         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3389                 if (notify_info_data_table[i].type == type &&
3390                     notify_info_data_table[i].field == field &&
3391                     notify_info_data_table[i].fn != NULL) {
3392                         *value = i;
3393                         return true;
3394                 }
3395         }
3396
3397         return false;
3398 }
3399
3400 /****************************************************************************
3401 ****************************************************************************/
3402
3403 void construct_info_data(struct spoolss_Notify *info_data,
3404                          enum spoolss_NotifyType type,
3405                          uint16_t field,
3406                          int id)
3407 {
3408         info_data->type                 = type;
3409         info_data->field.field          = field;
3410         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3411         info_data->job_id               = id;
3412 }
3413
3414 /*******************************************************************
3415  *
3416  * fill a notify_info struct with info asked
3417  *
3418  ********************************************************************/
3419
3420 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3421                                           struct spoolss_NotifyInfo *info,
3422                                           int snum,
3423                                           const struct spoolss_NotifyOptionType *option_type,
3424                                           uint32_t id,
3425                                           TALLOC_CTX *mem_ctx)
3426 {
3427         int field_num,j;
3428         enum spoolss_NotifyType type;
3429         uint16_t field;
3430
3431         struct spoolss_Notify *current_data;
3432         NT_PRINTER_INFO_LEVEL *printer = NULL;
3433         print_queue_struct *queue=NULL;
3434
3435         type = option_type->type;
3436
3437         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3438                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3439                 option_type->count, lp_servicename(snum)));
3440
3441         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3442                 return false;
3443
3444         for(field_num=0; field_num < option_type->count; field_num++) {
3445                 field = option_type->fields[field_num].field;
3446
3447                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3448
3449                 if (!search_notify(type, field, &j) )
3450                         continue;
3451
3452                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3453                                                       struct spoolss_Notify,
3454                                                       info->count + 1);
3455                 if (info->notifies == NULL) {
3456                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3457                         free_a_printer(&printer, 2);
3458                         return false;
3459                 }
3460
3461                 current_data = &info->notifies[info->count];
3462
3463                 construct_info_data(current_data, type, field, id);
3464
3465                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3466                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3467
3468                 notify_info_data_table[j].fn(snum, current_data, queue,
3469                                              printer, mem_ctx);
3470
3471                 info->count++;
3472         }
3473
3474         free_a_printer(&printer, 2);
3475         return true;
3476 }
3477
3478 /*******************************************************************
3479  *
3480  * fill a notify_info struct with info asked
3481  *
3482  ********************************************************************/
3483
3484 static bool construct_notify_jobs_info(print_queue_struct *queue,
3485                                        struct spoolss_NotifyInfo *info,
3486                                        NT_PRINTER_INFO_LEVEL *printer,
3487                                        int snum,
3488                                        const struct spoolss_NotifyOptionType *option_type,
3489                                        uint32_t id,
3490                                        TALLOC_CTX *mem_ctx)
3491 {
3492         int field_num,j;
3493         enum spoolss_NotifyType type;
3494         uint16_t field;
3495         struct spoolss_Notify *current_data;
3496
3497         DEBUG(4,("construct_notify_jobs_info\n"));
3498
3499         type = option_type->type;
3500
3501         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3502                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3503                 option_type->count));
3504
3505         for(field_num=0; field_num<option_type->count; field_num++) {
3506                 field = option_type->fields[field_num].field;
3507
3508                 if (!search_notify(type, field, &j) )
3509                         continue;
3510
3511                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3512                                                       struct spoolss_Notify,
3513                                                       info->count + 1);
3514                 if (info->notifies == NULL) {
3515                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3516                         return false;
3517                 }
3518
3519                 current_data=&(info->notifies[info->count]);
3520
3521                 construct_info_data(current_data, type, field, id);
3522                 notify_info_data_table[j].fn(snum, current_data, queue,
3523                                              printer, mem_ctx);
3524                 info->count++;
3525         }
3526
3527         return true;
3528 }
3529
3530 /*
3531  * JFM: The enumeration is not that simple, it's even non obvious.
3532  *
3533  * let's take an example: I want to monitor the PRINTER SERVER for
3534  * the printer's name and the number of jobs currently queued.
3535  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3536  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3537  *
3538  * I have 3 printers on the back of my server.
3539  *
3540  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3541  * structures.
3542  *   Number     Data                    Id
3543  *      1       printer 1 name          1
3544  *      2       printer 1 cjob          1
3545  *      3       printer 2 name          2
3546  *      4       printer 2 cjob          2
3547  *      5       printer 3 name          3
3548  *      6       printer 3 name          3
3549  *
3550  * that's the print server case, the printer case is even worse.
3551  */
3552
3553 /*******************************************************************
3554  *
3555  * enumerate all printers on the printserver
3556  * fill a notify_info struct with info asked
3557  *
3558  ********************************************************************/
3559
3560 static WERROR printserver_notify_info(pipes_struct *p,
3561                                       struct policy_handle *hnd,
3562                                       struct spoolss_NotifyInfo *info,
3563                                       TALLOC_CTX *mem_ctx)
3564 {
3565         int snum;
3566         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3567         int n_services=lp_numservices();
3568         int i;
3569         struct spoolss_NotifyOption *option;
3570         struct spoolss_NotifyOptionType option_type;
3571
3572         DEBUG(4,("printserver_notify_info\n"));
3573
3574         if (!Printer)
3575                 return WERR_BADFID;
3576
3577         option = Printer->notify.option;
3578
3579         info->version   = 2;
3580         info->notifies  = NULL;
3581         info->count     = 0;
3582
3583         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3584            sending a ffpcn() request first */
3585
3586         if ( !option )
3587                 return WERR_BADFID;
3588
3589         for (i=0; i<option->count; i++) {
3590                 option_type = option->types[i];
3591
3592                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3593                         continue;
3594
3595                 for (snum=0; snum<n_services; snum++)
3596                 {
3597                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3598                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3599                 }
3600         }
3601
3602 #if 0
3603         /*
3604          * Debugging information, don't delete.
3605          */
3606
3607         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3608         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3609         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3610
3611         for (i=0; i<info->count; i++) {
3612                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3613                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3614                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3615         }
3616 #endif
3617
3618         return WERR_OK;
3619 }
3620
3621 /*******************************************************************
3622  *
3623  * fill a notify_info struct with info asked
3624  *
3625  ********************************************************************/
3626
3627 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3628                                   struct spoolss_NotifyInfo *info,
3629                                   TALLOC_CTX *mem_ctx)
3630 {
3631         int snum;
3632         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3633         int i;
3634         uint32_t id;
3635         struct spoolss_NotifyOption *option;
3636         struct spoolss_NotifyOptionType option_type;
3637         int count,j;
3638         print_queue_struct *queue=NULL;
3639         print_status_struct status;
3640
3641         DEBUG(4,("printer_notify_info\n"));
3642
3643         if (!Printer)
3644                 return WERR_BADFID;
3645
3646         option = Printer->notify.option;
3647         id = 0x0;
3648
3649         info->version   = 2;
3650         info->notifies  = NULL;
3651         info->count     = 0;
3652
3653         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3654            sending a ffpcn() request first */
3655
3656         if ( !option )
3657                 return WERR_BADFID;
3658
3659         get_printer_snum(p, hnd, &snum, NULL);
3660
3661         for (i=0; i<option->count; i++) {
3662                 option_type = option->types[i];
3663
3664                 switch (option_type.type) {
3665                 case PRINTER_NOTIFY_TYPE:
3666                         if(construct_notify_printer_info(Printer, info, snum,
3667                                                          &option_type, id,
3668                                                          mem_ctx))
3669                                 id--;
3670                         break;
3671
3672                 case JOB_NOTIFY_TYPE: {
3673                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3674
3675                         count = print_queue_status(snum, &queue, &status);
3676
3677                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3678                                 goto done;
3679
3680                         for (j=0; j<count; j++) {
3681                                 construct_notify_jobs_info(&queue[j], info,
3682                                                            printer, snum,
3683                                                            &option_type,
3684                                                            queue[j].job,
3685                                                            mem_ctx);
3686                         }
3687
3688                         free_a_printer(&printer, 2);
3689
3690                 done:
3691                         SAFE_FREE(queue);
3692                         break;
3693                 }
3694                 }
3695         }
3696
3697         /*
3698          * Debugging information, don't delete.
3699          */
3700         /*
3701         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3703         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3704
3705         for (i=0; i<info->count; i++) {
3706                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3708                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3709         }
3710         */
3711         return WERR_OK;
3712 }
3713
3714 /****************************************************************
3715  _spoolss_RouterRefreshPrinterChangeNotify
3716 ****************************************************************/
3717
3718 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3719                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3720 {
3721         struct spoolss_NotifyInfo *info;
3722
3723         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3724         WERROR result = WERR_BADFID;
3725
3726         /* we always have a spoolss_NotifyInfo struct */
3727         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3728         if (!info) {
3729                 result = WERR_NOMEM;
3730                 goto done;
3731         }
3732
3733         *r->out.info = info;
3734
3735         if (!Printer) {
3736                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3737                         "Invalid handle (%s:%u:%u).\n",
3738                         OUR_HANDLE(r->in.handle)));
3739                 goto done;
3740         }
3741
3742         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3743
3744         /*
3745          *      We are now using the change value, and
3746          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3747          *      I don't have a global notification system, I'm sending back all the
3748          *      informations even when _NOTHING_ has changed.
3749          */
3750
3751         /* We need to keep track of the change value to send back in
3752            RRPCN replies otherwise our updates are ignored. */
3753
3754         Printer->notify.fnpcn = true;
3755
3756         if (Printer->notify.client_connected) {
3757                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3758                         "Saving change value in request [%x]\n",
3759                         r->in.change_low));
3760                 Printer->notify.change = r->in.change_low;
3761         }
3762
3763         /* just ignore the spoolss_NotifyOption */
3764
3765         switch (Printer->printer_type) {
3766                 case SPLHND_SERVER:
3767                         result = printserver_notify_info(p, r->in.handle,
3768                                                          info, p->mem_ctx);
3769                         break;
3770
3771                 case SPLHND_PRINTER:
3772                         result = printer_notify_info(p, r->in.handle,
3773                                                      info, p->mem_ctx);
3774                         break;
3775         }
3776
3777         Printer->notify.fnpcn = false;
3778
3779 done:
3780         return result;
3781 }
3782
3783 /********************************************************************
3784  * construct_printer_info_0
3785  * fill a printer_info_0 struct
3786  ********************************************************************/
3787
3788 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3789                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3790                                       struct spoolss_PrinterInfo0 *r,
3791                                       int snum)
3792 {
3793         int count;
3794         counter_printer_0 *session_counter;
3795         time_t setuptime;
3796         print_status_struct status;
3797
3798         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3799         W_ERROR_HAVE_NO_MEMORY(r->printername);
3800
3801         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3802         W_ERROR_HAVE_NO_MEMORY(r->servername);
3803
3804         count = print_queue_length(snum, &status);
3805
3806         /* check if we already have a counter for this printer */
3807         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3808                 if (session_counter->snum == snum)
3809                         break;
3810         }
3811
3812         /* it's the first time, add it to the list */
3813         if (session_counter == NULL) {
3814                 session_counter = SMB_MALLOC_P(counter_printer_0);
3815                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3816                 ZERO_STRUCTP(session_counter);
3817                 session_counter->snum           = snum;
3818                 session_counter->counter        = 0;
3819                 DLIST_ADD(counter_list, session_counter);
3820         }
3821
3822         /* increment it */
3823         session_counter->counter++;
3824
3825         r->cjobs                        = count;
3826         r->total_jobs                   = 0;
3827         r->total_bytes                  = 0;
3828
3829         setuptime = (time_t)ntprinter->info_2->setuptime;
3830
3831         init_systemtime(&r->time, gmtime(&setuptime));
3832
3833         /* JFM:
3834          * the global_counter should be stored in a TDB as it's common to all the clients
3835          * and should be zeroed on samba startup
3836          */
3837         r->global_counter               = session_counter->counter;
3838         r->total_pages                  = 0;
3839         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3840         r->version                      = 0x0005;       /* NT 5 */
3841         r->free_build                   = 0x0893;       /* build 2195 */
3842         r->spooling                     = 0;
3843         r->max_spooling                 = 0;
3844         r->session_counter              = session_counter->counter;
3845         r->num_error_out_of_paper       = 0x0;
3846         r->num_error_not_ready          = 0x0;          /* number of print failure */
3847         r->job_error                    = 0x0;
3848         r->number_of_processors         = 0x1;
3849         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3850         r->high_part_total_bytes        = 0x0;
3851         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3852         r->last_error                   = WERR_OK;
3853         r->status                       = nt_printq_status(status.status);
3854         r->enumerate_network_printers   = 0x0;
3855         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3856         r->processor_architecture       = 0x0;
3857         r->processor_level              = 0x6;          /* 6  ???*/
3858         r->ref_ic                       = 0;
3859         r->reserved2                    = 0;
3860         r->reserved3                    = 0;
3861
3862         return WERR_OK;
3863 }
3864
3865 /****************************************************************************
3866  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3867  should be valid upon entry
3868 ****************************************************************************/
3869
3870 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3871                                     struct spoolss_DeviceMode *r,
3872                                     const NT_DEVICEMODE *ntdevmode)
3873 {
3874         if (!r || !ntdevmode) {
3875                 return WERR_INVALID_PARAM;
3876         }
3877
3878         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3879         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3880
3881         r->specversion          = ntdevmode->specversion;
3882         r->driverversion        = ntdevmode->driverversion;
3883         r->size                 = ntdevmode->size;
3884         r->__driverextra_length = ntdevmode->driverextra;
3885         r->fields               = ntdevmode->fields;
3886
3887         r->orientation          = ntdevmode->orientation;
3888         r->papersize            = ntdevmode->papersize;
3889         r->paperlength          = ntdevmode->paperlength;
3890         r->paperwidth           = ntdevmode->paperwidth;
3891         r->scale                = ntdevmode->scale;
3892         r->copies               = ntdevmode->copies;
3893         r->defaultsource        = ntdevmode->defaultsource;
3894         r->printquality         = ntdevmode->printquality;
3895         r->color                = ntdevmode->color;
3896         r->duplex               = ntdevmode->duplex;
3897         r->yresolution          = ntdevmode->yresolution;
3898         r->ttoption             = ntdevmode->ttoption;
3899         r->collate              = ntdevmode->collate;
3900
3901         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3902         W_ERROR_HAVE_NO_MEMORY(r->formname);
3903
3904         /* all 0 below are values that have not been set in the old parsing/copy
3905          * function, maybe they should... - gd */
3906
3907         r->logpixels            = 0;
3908         r->bitsperpel           = 0;
3909         r->pelswidth            = 0;
3910         r->pelsheight           = 0;
3911         r->displayflags         = 0;
3912         r->displayfrequency     = 0;
3913         r->icmmethod            = ntdevmode->icmmethod;
3914         r->icmintent            = ntdevmode->icmintent;
3915         r->mediatype            = ntdevmode->mediatype;
3916         r->dithertype           = ntdevmode->dithertype;
3917         r->reserved1            = 0;
3918         r->reserved2            = 0;
3919         r->panningwidth         = 0;
3920         r->panningheight        = 0;
3921
3922         if (ntdevmode->nt_dev_private != NULL) {
3923                 r->driverextra_data = data_blob_talloc(mem_ctx,
3924                         ntdevmode->nt_dev_private,
3925                         ntdevmode->driverextra);
3926                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3927         }
3928
3929         return WERR_OK;
3930 }
3931
3932
3933 /****************************************************************************
3934  Create a spoolss_DeviceMode struct. Returns talloced memory.
3935 ****************************************************************************/
3936
3937 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3938                                               const char *servicename)
3939 {
3940         WERROR result;
3941         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3942         struct spoolss_DeviceMode *devmode = NULL;
3943
3944         DEBUG(7,("construct_dev_mode\n"));
3945
3946         DEBUGADD(8,("getting printer characteristics\n"));
3947
3948         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3949                 return NULL;
3950
3951         if (!printer->info_2->devmode) {
3952                 DEBUG(5, ("BONG! There was no device mode!\n"));
3953                 goto done;
3954         }
3955
3956         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3957         if (!devmode) {
3958                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3959                 goto done;
3960         }
3961
3962         DEBUGADD(8,("loading DEVICEMODE\n"));
3963
3964         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3965         if (!W_ERROR_IS_OK(result)) {
3966                 TALLOC_FREE(devmode);
3967         }
3968
3969 done:
3970         free_a_printer(&printer,2);
3971
3972         return devmode;
3973 }
3974
3975 /********************************************************************
3976  * construct_printer_info3
3977  * fill a spoolss_PrinterInfo3 struct
3978  ********************************************************************/
3979
3980 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3981                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3982                                       struct spoolss_PrinterInfo3 *r,
3983                                       int snum)
3984 {
3985         /* These are the components of the SD we are returning. */
3986
3987         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3988                 /* don't use talloc_steal() here unless you do a deep steal of all
3989                    the SEC_DESC members */
3990
3991                 r->secdesc = dup_sec_desc(mem_ctx,
3992                                           ntprinter->info_2->secdesc_buf->sd);
3993                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3994         }
3995
3996         return WERR_OK;
3997 }
3998
3999 /********************************************************************
4000  * construct_printer_info4
4001  * fill a spoolss_PrinterInfo4 struct
4002  ********************************************************************/
4003
4004 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4005                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4006                                       struct spoolss_PrinterInfo4 *r,
4007                                       int snum)
4008 {
4009         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4010         W_ERROR_HAVE_NO_MEMORY(r->printername);
4011         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4012         W_ERROR_HAVE_NO_MEMORY(r->servername);
4013
4014         r->attributes   = ntprinter->info_2->attributes;
4015
4016         return WERR_OK;
4017 }
4018
4019 /********************************************************************
4020  * construct_printer_info5
4021  * fill a spoolss_PrinterInfo5 struct
4022  ********************************************************************/
4023
4024 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4025                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4026                                       struct spoolss_PrinterInfo5 *r,
4027                                       int snum)
4028 {
4029         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4030         W_ERROR_HAVE_NO_MEMORY(r->printername);
4031         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4032         W_ERROR_HAVE_NO_MEMORY(r->portname);
4033
4034         r->attributes   = ntprinter->info_2->attributes;
4035
4036         /* these two are not used by NT+ according to MSDN */
4037
4038         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4039         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4040
4041         return WERR_OK;
4042 }
4043
4044 /********************************************************************
4045  * construct_printer_info_6
4046  * fill a spoolss_PrinterInfo6 struct
4047  ********************************************************************/
4048
4049 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4050                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4051                                       struct spoolss_PrinterInfo6 *r,
4052                                       int snum)
4053 {
4054         int count;
4055         print_status_struct status;
4056
4057         count = print_queue_length(snum, &status);
4058
4059         r->status = nt_printq_status(status.status);
4060
4061         return WERR_OK;
4062 }
4063
4064 /********************************************************************
4065  * construct_printer_info7
4066  * fill a spoolss_PrinterInfo7 struct
4067  ********************************************************************/
4068
4069 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4070                                       Printer_entry *print_hnd,
4071                                       struct spoolss_PrinterInfo7 *r,
4072                                       int snum)
4073 {
4074         struct GUID guid;
4075
4076         if (is_printer_published(print_hnd, snum, &guid)) {
4077                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4078                 r->action = DSPRINT_PUBLISH;
4079         } else {
4080                 r->guid = talloc_strdup(mem_ctx, "");
4081                 r->action = DSPRINT_UNPUBLISH;
4082         }
4083         W_ERROR_HAVE_NO_MEMORY(r->guid);
4084
4085         return WERR_OK;
4086 }
4087
4088 /********************************************************************
4089  * construct_printer_info8
4090  * fill a spoolss_PrinterInfo8 struct
4091  ********************************************************************/
4092
4093 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4094                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4095                                       struct spoolss_DeviceModeInfo *r,
4096                                       int snum)
4097 {
4098         struct spoolss_DeviceMode *devmode;
4099         WERROR result;
4100
4101         if (!ntprinter->info_2->devmode) {
4102                 r->devmode = NULL;
4103                 return WERR_OK;
4104         }
4105
4106         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4107         W_ERROR_HAVE_NO_MEMORY(devmode);
4108
4109         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4110         if (!W_ERROR_IS_OK(result)) {
4111                 TALLOC_FREE(devmode);
4112                 return result;
4113         }
4114
4115         r->devmode      = devmode;
4116
4117         return WERR_OK;
4118 }
4119
4120
4121 /********************************************************************
4122  * construct_printer_info1
4123  * fill a spoolss_PrinterInfo1 struct
4124 ********************************************************************/
4125
4126 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4127                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4128                                       uint32_t flags,
4129                                       struct spoolss_PrinterInfo1 *r,
4130                                       int snum)
4131 {
4132         r->flags                = flags;
4133
4134         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4135                                                   ntprinter->info_2->printername,
4136                                                   ntprinter->info_2->drivername,
4137                                                   ntprinter->info_2->location);
4138         W_ERROR_HAVE_NO_MEMORY(r->description);
4139
4140         if (*ntprinter->info_2->comment == '\0') {
4141                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4142         } else {
4143                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4144         }
4145         W_ERROR_HAVE_NO_MEMORY(r->comment);
4146
4147         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4148         W_ERROR_HAVE_NO_MEMORY(r->name);
4149
4150         return WERR_OK;
4151 }
4152
4153 /********************************************************************
4154  * construct_printer_info2
4155  * fill a spoolss_PrinterInfo2 struct
4156 ********************************************************************/
4157
4158 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4159                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4160                                       struct spoolss_PrinterInfo2 *r,
4161                                       int snum)
4162 {
4163         int count;
4164
4165         print_status_struct status;
4166
4167         count = print_queue_length(snum, &status);
4168
4169         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4170         W_ERROR_HAVE_NO_MEMORY(r->servername);
4171         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4172         W_ERROR_HAVE_NO_MEMORY(r->printername);
4173         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4174         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4175         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4176         W_ERROR_HAVE_NO_MEMORY(r->portname);
4177         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4178         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4179
4180         if (*ntprinter->info_2->comment == '\0') {
4181                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4182         } else {
4183                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4184         }
4185         W_ERROR_HAVE_NO_MEMORY(r->comment);
4186
4187         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4188         W_ERROR_HAVE_NO_MEMORY(r->location);
4189         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4190         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4191         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4192         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4193         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4194         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4195         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4196         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4197
4198         r->attributes           = ntprinter->info_2->attributes;
4199
4200         r->priority             = ntprinter->info_2->priority;
4201         r->defaultpriority      = ntprinter->info_2->default_priority;
4202         r->starttime            = ntprinter->info_2->starttime;
4203         r->untiltime            = ntprinter->info_2->untiltime;
4204         r->status               = nt_printq_status(status.status);
4205         r->cjobs                = count;
4206         r->averageppm           = ntprinter->info_2->averageppm;
4207
4208         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4209         if (!r->devmode) {
4210                 DEBUG(8,("Returning NULL Devicemode!\n"));
4211         }
4212
4213         r->secdesc              = NULL;
4214
4215         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4216                 /* don't use talloc_steal() here unless you do a deep steal of all
4217                    the SEC_DESC members */
4218
4219                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4220         }
4221
4222         return WERR_OK;
4223 }
4224
4225 /********************************************************************
4226 ********************************************************************/
4227
4228 static bool snum_is_shared_printer(int snum)
4229 {
4230         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4231 }
4232
4233 /********************************************************************
4234  Spoolss_enumprinters.
4235 ********************************************************************/
4236
4237 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4238                                            uint32_t level,
4239                                            uint32_t flags,
4240                                            union spoolss_PrinterInfo **info_p,
4241                                            uint32_t *count_p)
4242 {
4243         int snum;
4244         int n_services = lp_numservices();
4245         union spoolss_PrinterInfo *info = NULL;
4246         uint32_t count = 0;
4247         WERROR result = WERR_OK;
4248
4249         *count_p = 0;
4250         *info_p = NULL;
4251
4252         for (snum = 0; snum < n_services; snum++) {
4253
4254                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4255
4256                 if (!snum_is_shared_printer(snum)) {
4257                         continue;
4258                 }
4259
4260                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4261                         lp_servicename(snum), snum));
4262
4263                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4264                                             union spoolss_PrinterInfo,
4265                                             count + 1);
4266                 if (!info) {
4267                         result = WERR_NOMEM;
4268                         goto out;
4269                 }
4270
4271                 result = get_a_printer(NULL, &ntprinter, 2,
4272                                        lp_const_servicename(snum));
4273                 if (!W_ERROR_IS_OK(result)) {
4274                         goto out;
4275                 }
4276
4277                 switch (level) {
4278                 case 0:
4279                         result = construct_printer_info0(info, ntprinter,
4280                                                          &info[count].info0, snum);
4281                         break;
4282                 case 1:
4283                         result = construct_printer_info1(info, ntprinter, flags,
4284                                                          &info[count].info1, snum);
4285                         break;
4286                 case 2:
4287                         result = construct_printer_info2(info, ntprinter,
4288                                                          &info[count].info2, snum);
4289                         break;
4290                 case 4:
4291                         result = construct_printer_info4(info, ntprinter,
4292                                                          &info[count].info4, snum);
4293                         break;
4294                 case 5:
4295                         result = construct_printer_info5(info, ntprinter,
4296                                                          &info[count].info5, snum);
4297                         break;
4298
4299                 default:
4300                         result = WERR_UNKNOWN_LEVEL;
4301                         free_a_printer(&ntprinter, 2);
4302                         goto out;
4303                 }
4304
4305                 free_a_printer(&ntprinter, 2);
4306                 if (!W_ERROR_IS_OK(result)) {
4307                         goto out;
4308                 }
4309
4310                 count++;
4311         }
4312
4313         *count_p = count;
4314         *info_p = info;
4315
4316  out:
4317         if (!W_ERROR_IS_OK(result)) {
4318                 TALLOC_FREE(info);
4319                 return result;
4320         }
4321
4322         *info_p = info;
4323
4324         return WERR_OK;
4325 }
4326
4327 /********************************************************************
4328  * handle enumeration of printers at level 0
4329  ********************************************************************/
4330
4331 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4332                                   uint32_t flags,
4333                                   const char *servername,
4334                                   union spoolss_PrinterInfo **info,
4335                                   uint32_t *count)
4336 {
4337         DEBUG(4,("enum_all_printers_info_0\n"));
4338
4339         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4340 }
4341
4342
4343 /********************************************************************
4344 ********************************************************************/
4345
4346 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4347                                        uint32_t flags,
4348                                        union spoolss_PrinterInfo **info,
4349                                        uint32_t *count)
4350 {
4351         DEBUG(4,("enum_all_printers_info_1\n"));
4352
4353         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4354 }
4355
4356 /********************************************************************
4357  enum_all_printers_info_1_local.
4358 *********************************************************************/
4359
4360 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4361                                              union spoolss_PrinterInfo **info,
4362                                              uint32_t *count)
4363 {
4364         DEBUG(4,("enum_all_printers_info_1_local\n"));
4365
4366         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4367 }
4368
4369 /********************************************************************
4370  enum_all_printers_info_1_name.
4371 *********************************************************************/
4372
4373 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4374                                             const char *name,
4375                                             union spoolss_PrinterInfo **info,
4376                                             uint32_t *count)
4377 {
4378         const char *s = name;
4379
4380         DEBUG(4,("enum_all_printers_info_1_name\n"));
4381
4382         if ((name[0] == '\\') && (name[1] == '\\')) {
4383                 s = name + 2;
4384         }
4385
4386         if (!is_myname_or_ipaddr(s)) {
4387                 return WERR_INVALID_NAME;
4388         }
4389
4390         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4391 }
4392
4393 /********************************************************************
4394  enum_all_printers_info_1_network.
4395 *********************************************************************/
4396
4397 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4398                                                const char *name,
4399                                                union spoolss_PrinterInfo **info,
4400                                                uint32_t *count)
4401 {
4402         const char *s = name;
4403
4404         DEBUG(4,("enum_all_printers_info_1_network\n"));
4405
4406         /* If we respond to a enum_printers level 1 on our name with flags
4407            set to PRINTER_ENUM_REMOTE with a list of printers then these
4408            printers incorrectly appear in the APW browse list.
4409            Specifically the printers for the server appear at the workgroup
4410            level where all the other servers in the domain are
4411            listed. Windows responds to this call with a
4412            WERR_CAN_NOT_COMPLETE so we should do the same. */
4413
4414         if (name[0] == '\\' && name[1] == '\\') {
4415                  s = name + 2;
4416         }
4417
4418         if (is_myname_or_ipaddr(s)) {
4419                  return WERR_CAN_NOT_COMPLETE;
4420         }
4421
4422         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4423 }
4424
4425 /********************************************************************
4426  * api_spoolss_enumprinters
4427  *
4428  * called from api_spoolss_enumprinters (see this to understand)
4429  ********************************************************************/
4430
4431 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4432                                        union spoolss_PrinterInfo **info,
4433                                        uint32_t *count)
4434 {
4435         DEBUG(4,("enum_all_printers_info_2\n"));
4436
4437         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4438 }
4439
4440 /********************************************************************
4441  * handle enumeration of printers at level 1
4442  ********************************************************************/
4443
4444 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4445                                   uint32_t flags,
4446                                   const char *name,
4447                                   union spoolss_PrinterInfo **info,
4448                                   uint32_t *count)
4449 {
4450         /* Not all the flags are equals */
4451
4452         if (flags & PRINTER_ENUM_LOCAL) {
4453                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4454         }
4455
4456         if (flags & PRINTER_ENUM_NAME) {
4457                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4458         }
4459
4460         if (flags & PRINTER_ENUM_NETWORK) {
4461                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4462         }
4463
4464         return WERR_OK; /* NT4sp5 does that */
4465 }
4466
4467 /********************************************************************
4468  * handle enumeration of printers at level 2
4469  ********************************************************************/
4470
4471 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4472                                   uint32_t flags,
4473                                   const char *servername,
4474                                   union spoolss_PrinterInfo **info,
4475                                   uint32_t *count)
4476 {
4477         if (flags & PRINTER_ENUM_LOCAL) {
4478                 return enum_all_printers_info_2(mem_ctx, info, count);
4479         }
4480
4481         if (flags & PRINTER_ENUM_NAME) {
4482                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4483                         return WERR_INVALID_NAME;
4484                 }
4485
4486                 return enum_all_printers_info_2(mem_ctx, info, count);
4487         }
4488
4489         if (flags & PRINTER_ENUM_REMOTE) {
4490                 return WERR_UNKNOWN_LEVEL;
4491         }
4492
4493         return WERR_OK;
4494 }
4495
4496 /********************************************************************
4497  * handle enumeration of printers at level 4
4498  ********************************************************************/
4499
4500 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4501                                   uint32_t flags,
4502                                   const char *servername,
4503                                   union spoolss_PrinterInfo **info,
4504                                   uint32_t *count)
4505 {
4506         DEBUG(4,("enum_all_printers_info_4\n"));
4507
4508         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4509 }
4510
4511
4512 /********************************************************************
4513  * handle enumeration of printers at level 5
4514  ********************************************************************/
4515
4516 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4517                                   uint32_t flags,
4518                                   const char *servername,
4519                                   union spoolss_PrinterInfo **info,
4520                                   uint32_t *count)
4521 {
4522         DEBUG(4,("enum_all_printers_info_5\n"));
4523
4524         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4525 }
4526
4527 /****************************************************************
4528  _spoolss_EnumPrinters
4529 ****************************************************************/
4530
4531 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4532                              struct spoolss_EnumPrinters *r)
4533 {
4534         const char *name;
4535         WERROR result;
4536
4537         /* that's an [in out] buffer */
4538
4539         if (!r->in.buffer && (r->in.offered != 0)) {
4540                 return WERR_INVALID_PARAM;
4541         }
4542
4543         DEBUG(4,("_spoolss_EnumPrinters\n"));
4544
4545         *r->out.needed = 0;
4546         *r->out.count = 0;
4547         *r->out.info = NULL;
4548
4549         /*
4550          * Level 1:
4551          *          flags==PRINTER_ENUM_NAME
4552          *           if name=="" then enumerates all printers
4553          *           if name!="" then enumerate the printer
4554          *          flags==PRINTER_ENUM_REMOTE
4555          *          name is NULL, enumerate printers
4556          * Level 2: name!="" enumerates printers, name can't be NULL
4557          * Level 3: doesn't exist
4558          * Level 4: does a local registry lookup
4559          * Level 5: same as Level 2
4560          */
4561
4562         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4563         W_ERROR_HAVE_NO_MEMORY(name);
4564
4565         switch (r->in.level) {
4566         case 0:
4567                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4568                                              r->out.info, r->out.count);
4569                 break;
4570         case 1:
4571                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4572                                              r->out.info, r->out.count);
4573                 break;
4574         case 2:
4575                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4576                                              r->out.info, r->out.count);
4577                 break;
4578         case 4:
4579                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4580                                              r->out.info, r->out.count);
4581                 break;
4582         case 5:
4583                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4584                                              r->out.info, r->out.count);
4585                 break;
4586         default:
4587                 return WERR_UNKNOWN_LEVEL;
4588         }
4589
4590         if (!W_ERROR_IS_OK(result)) {
4591                 return result;
4592         }
4593
4594         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4595                                                      spoolss_EnumPrinters, NULL,
4596                                                      *r->out.info, r->in.level,
4597                                                      *r->out.count);
4598         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4599         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4600
4601         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4602 }
4603
4604 /****************************************************************
4605  _spoolss_GetPrinter
4606 ****************************************************************/
4607
4608 WERROR _spoolss_GetPrinter(pipes_struct *p,
4609                            struct spoolss_GetPrinter *r)
4610 {
4611         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4612         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4613         WERROR result = WERR_OK;
4614
4615         int snum;
4616
4617         /* that's an [in out] buffer */
4618
4619         if (!r->in.buffer && (r->in.offered != 0)) {
4620                 return WERR_INVALID_PARAM;
4621         }
4622
4623         *r->out.needed = 0;
4624
4625         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4626                 return WERR_BADFID;
4627         }
4628
4629         result = get_a_printer(Printer, &ntprinter, 2,
4630                                lp_const_servicename(snum));
4631         if (!W_ERROR_IS_OK(result)) {
4632                 return result;
4633         }
4634
4635         switch (r->in.level) {
4636         case 0:
4637                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4638                                                  &r->out.info->info0, snum);
4639                 break;
4640         case 1:
4641                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4642                                                  PRINTER_ENUM_ICON8,
4643                                                  &r->out.info->info1, snum);
4644                 break;
4645         case 2:
4646                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4647                                                  &r->out.info->info2, snum);
4648                 break;
4649         case 3:
4650                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4651                                                  &r->out.info->info3, snum);
4652                 break;
4653         case 4:
4654                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4655                                                  &r->out.info->info4, snum);
4656                 break;
4657         case 5:
4658                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4659                                                  &r->out.info->info5, snum);
4660                 break;
4661         case 6:
4662                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4663                                                  &r->out.info->info6, snum);
4664                 break;
4665         case 7:
4666                 result = construct_printer_info7(p->mem_ctx, Printer,
4667                                                  &r->out.info->info7, snum);
4668                 break;
4669         case 8:
4670                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4671                                                  &r->out.info->info8, snum);
4672                 break;
4673         default:
4674                 result = WERR_UNKNOWN_LEVEL;
4675                 break;
4676         }
4677
4678         free_a_printer(&ntprinter, 2);
4679
4680         if (!W_ERROR_IS_OK(result)) {
4681                 TALLOC_FREE(r->out.info);
4682                 return result;
4683         }
4684
4685         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4686                                                r->out.info, r->in.level);
4687         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4688
4689         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4690 }
4691
4692 /********************************************************************
4693  ********************************************************************/
4694
4695 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4696                                                   fstring *fstring_array,
4697                                                   const char *cservername)
4698 {
4699         int i, num_strings = 0;
4700         const char **array = NULL;
4701
4702         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4703
4704                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4705                                                   cservername, fstring_array[i]);
4706                 if (!str) {
4707                         TALLOC_FREE(array);
4708                         return NULL;
4709                 }
4710
4711
4712                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4713                         TALLOC_FREE(array);
4714                         return NULL;
4715                 }
4716         }
4717
4718         if (i > 0) {
4719                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4720                              &array, &num_strings);
4721         }
4722
4723         return array;
4724 }
4725
4726 /********************************************************************
4727  * fill a spoolss_DriverInfo1 struct
4728  ********************************************************************/
4729
4730 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4731                                         struct spoolss_DriverInfo1 *r,
4732                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4733                                         const char *servername,
4734                                         const char *architecture)
4735 {
4736         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4737         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4738
4739         return WERR_OK;
4740 }
4741
4742 /********************************************************************
4743  * fill a spoolss_DriverInfo2 struct
4744  ********************************************************************/
4745
4746 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4747                                         struct spoolss_DriverInfo2 *r,
4748                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4749                                         const char *servername)
4750
4751 {
4752         const char *cservername = canon_servername(servername);
4753
4754         r->version              = driver->info_3->cversion;
4755
4756         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4757         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4758         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4759         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4760
4761         if (strlen(driver->info_3->driverpath)) {
4762                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4763                                 cservername, driver->info_3->driverpath);
4764         } else {
4765                 r->driver_path  = talloc_strdup(mem_ctx, "");
4766         }
4767         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4768
4769         if (strlen(driver->info_3->datafile)) {
4770                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4771                                 cservername, driver->info_3->datafile);
4772         } else {
4773                 r->data_file    = talloc_strdup(mem_ctx, "");
4774         }
4775         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4776
4777         if (strlen(driver->info_3->configfile)) {
4778                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4779                                 cservername, driver->info_3->configfile);
4780         } else {
4781                 r->config_file  = talloc_strdup(mem_ctx, "");
4782         }
4783         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4784
4785         return WERR_OK;
4786 }
4787
4788 /********************************************************************
4789  * fill a spoolss_DriverInfo3 struct
4790  ********************************************************************/
4791
4792 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4793                                         struct spoolss_DriverInfo3 *r,
4794                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4795                                         const char *servername)
4796 {
4797         const char *cservername = canon_servername(servername);
4798
4799         r->version              = driver->info_3->cversion;
4800
4801         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4802         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4803         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4804         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4805
4806         if (strlen(driver->info_3->driverpath)) {
4807                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4808                                 cservername, driver->info_3->driverpath);
4809         } else {
4810                 r->driver_path  = talloc_strdup(mem_ctx, "");
4811         }
4812         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4813
4814         if (strlen(driver->info_3->datafile)) {
4815                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4816                                 cservername, driver->info_3->datafile);
4817         } else {
4818                 r->data_file    = talloc_strdup(mem_ctx, "");
4819         }
4820         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4821
4822         if (strlen(driver->info_3->configfile)) {
4823                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4824                                 cservername, driver->info_3->configfile);
4825         } else {
4826                 r->config_file  = talloc_strdup(mem_ctx, "");
4827         }
4828         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4829
4830         if (strlen(driver->info_3->helpfile)) {
4831                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4832                                 cservername, driver->info_3->helpfile);
4833         } else {
4834                 r->help_file    = talloc_strdup(mem_ctx, "");
4835         }
4836         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4837
4838         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4839         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4840         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4841         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4842
4843         r->dependent_files = string_array_from_driver_info(mem_ctx,
4844                                                            driver->info_3->dependentfiles,
4845                                                            cservername);
4846         return WERR_OK;
4847 }
4848
4849 /********************************************************************
4850  * fill a spoolss_DriverInfo4 struct
4851  ********************************************************************/
4852
4853 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4854                                         struct spoolss_DriverInfo4 *r,
4855                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4856                                         const char *servername)
4857 {
4858         const char *cservername = canon_servername(servername);
4859
4860         r->version              = driver->info_3->cversion;
4861
4862         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4863         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4864         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4865         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4866
4867         if (strlen(driver->info_3->driverpath)) {
4868                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4869                                 cservername, driver->info_3->driverpath);
4870         } else {
4871                 r->driver_path  = talloc_strdup(mem_ctx, "");
4872         }
4873         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4874
4875         if (strlen(driver->info_3->datafile)) {
4876                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4877                                 cservername, driver->info_3->datafile);
4878         } else {
4879                 r->data_file    = talloc_strdup(mem_ctx, "");
4880         }
4881         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4882
4883         if (strlen(driver->info_3->configfile)) {
4884                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4885                                 cservername, driver->info_3->configfile);
4886         } else {
4887                 r->config_file  = talloc_strdup(mem_ctx, "");
4888         }
4889         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4890
4891         if (strlen(driver->info_3->helpfile)) {
4892                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4893                                 cservername, driver->info_3->helpfile);
4894         } else {
4895                 r->help_file    = talloc_strdup(mem_ctx, "");
4896         }
4897         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4898
4899         r->dependent_files = string_array_from_driver_info(mem_ctx,
4900                                                            driver->info_3->dependentfiles,
4901                                                            cservername);
4902
4903
4904         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4905         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4906         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4907         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4908
4909         r->previous_names = string_array_from_driver_info(mem_ctx,
4910                                                           NULL,
4911                                                           cservername);
4912
4913         return WERR_OK;
4914 }
4915
4916 /********************************************************************
4917  * fill a spoolss_DriverInfo5 struct
4918  ********************************************************************/
4919
4920 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4921                                         struct spoolss_DriverInfo5 *r,
4922                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4923                                         const char *servername)
4924 {
4925         const char *cservername = canon_servername(servername);
4926
4927         r->version              = driver->info_3->cversion;
4928
4929         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4930         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4931         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4932         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4933
4934         if (strlen(driver->info_3->driverpath)) {
4935                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4936                                 cservername, driver->info_3->driverpath);
4937         } else {
4938                 r->driver_path  = talloc_strdup(mem_ctx, "");
4939         }
4940         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4941
4942         if (strlen(driver->info_3->datafile)) {
4943                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4944                                 cservername, driver->info_3->datafile);
4945         } else {
4946                 r->data_file    = talloc_strdup(mem_ctx, "");
4947         }
4948         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4949
4950         if (strlen(driver->info_3->configfile)) {
4951                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4952                                 cservername, driver->info_3->configfile);
4953         } else {
4954                 r->config_file  = talloc_strdup(mem_ctx, "");
4955         }
4956         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4957
4958         r->driver_attributes    = 0;
4959         r->config_version       = 0;
4960         r->driver_version       = 0;
4961
4962         return WERR_OK;
4963 }
4964 /********************************************************************
4965  * fill a spoolss_DriverInfo6 struct
4966  ********************************************************************/
4967
4968 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4969                                         struct spoolss_DriverInfo6 *r,
4970                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4971                                         const char *servername)
4972 {
4973         const char *cservername = canon_servername(servername);
4974
4975         r->version              = driver->info_3->cversion;
4976
4977         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4978         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4979         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4980         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4981
4982         if (strlen(driver->info_3->driverpath)) {
4983                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4984                                 cservername, driver->info_3->driverpath);
4985         } else {
4986                 r->driver_path  = talloc_strdup(mem_ctx, "");
4987         }
4988         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4989
4990         if (strlen(driver->info_3->datafile)) {
4991                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4992                                 cservername, driver->info_3->datafile);
4993         } else {
4994                 r->data_file    = talloc_strdup(mem_ctx, "");
4995         }
4996         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4997
4998         if (strlen(driver->info_3->configfile)) {
4999                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5000                                 cservername, driver->info_3->configfile);
5001         } else {
5002                 r->config_file  = talloc_strdup(mem_ctx, "");
5003         }
5004         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5005
5006         if (strlen(driver->info_3->helpfile)) {
5007                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5008                                 cservername, driver->info_3->helpfile);
5009         } else {
5010                 r->help_file    = talloc_strdup(mem_ctx, "");
5011         }
5012         W_ERROR_HAVE_NO_MEMORY(r->help_file);
5013
5014         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5015         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5016         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5017         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5018
5019         r->dependent_files = string_array_from_driver_info(mem_ctx,
5020                                                            driver->info_3->dependentfiles,
5021                                                            cservername);
5022         r->previous_names = string_array_from_driver_info(mem_ctx,
5023                                                           NULL,
5024                                                           cservername);
5025
5026         r->driver_date          = 0;
5027         r->driver_version       = 0;
5028
5029         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5030         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5031         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5032         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5033         r->hardware_id          = talloc_strdup(mem_ctx, "");
5034         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5035         r->provider             = talloc_strdup(mem_ctx, "");
5036         W_ERROR_HAVE_NO_MEMORY(r->provider);
5037
5038         return WERR_OK;
5039 }
5040
5041 /********************************************************************
5042  ********************************************************************/
5043
5044 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5045                                           struct spoolss_DriverFileInfo *r,
5046                                           const char *cservername,
5047                                           const char *file_name,
5048                                           enum spoolss_DriverFileType file_type,
5049                                           uint32_t file_version)
5050 {
5051         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5052                                           cservername, file_name);
5053         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5054         r->file_type    = file_type;
5055         r->file_version = file_version;
5056
5057         return WERR_OK;
5058 }
5059
5060 /********************************************************************
5061  ********************************************************************/
5062
5063 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5064                                                  const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5065                                                  const char *cservername,
5066                                                  struct spoolss_DriverFileInfo **info_p,
5067                                                  uint32_t *count_p)
5068 {
5069         struct spoolss_DriverFileInfo *info = NULL;
5070         uint32_t count = 0;
5071         WERROR result;
5072         uint32_t i;
5073
5074         *info_p = NULL;
5075         *count_p = 0;
5076
5077         if (strlen(driver->info_3->driverpath)) {
5078                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5079                                             struct spoolss_DriverFileInfo,
5080                                             count + 1);
5081                 W_ERROR_HAVE_NO_MEMORY(info);
5082                 result = fill_spoolss_DriverFileInfo(info,
5083                                                      &info[count],
5084                                                      cservername,
5085                                                      driver->info_3->driverpath,
5086                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5087                                                      0);
5088                 W_ERROR_NOT_OK_RETURN(result);
5089                 count++;
5090         }
5091
5092         if (strlen(driver->info_3->configfile)) {
5093                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5094                                             struct spoolss_DriverFileInfo,
5095                                             count + 1);
5096                 W_ERROR_HAVE_NO_MEMORY(info);
5097                 result = fill_spoolss_DriverFileInfo(info,
5098                                                      &info[count],
5099                                                      cservername,
5100                                                      driver->info_3->configfile,
5101                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5102                                                      0);
5103                 W_ERROR_NOT_OK_RETURN(result);
5104                 count++;
5105         }
5106
5107         if (strlen(driver->info_3->datafile)) {
5108                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5109                                             struct spoolss_DriverFileInfo,
5110                                             count + 1);
5111                 W_ERROR_HAVE_NO_MEMORY(info);
5112                 result = fill_spoolss_DriverFileInfo(info,
5113                                                      &info[count],
5114                                                      cservername,
5115                                                      driver->info_3->datafile,
5116                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5117                                                      0);
5118                 W_ERROR_NOT_OK_RETURN(result);
5119                 count++;
5120         }
5121
5122         if (strlen(driver->info_3->helpfile)) {
5123                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5124                                             struct spoolss_DriverFileInfo,
5125                                             count + 1);
5126                 W_ERROR_HAVE_NO_MEMORY(info);
5127                 result = fill_spoolss_DriverFileInfo(info,
5128                                                      &info[count],
5129                                                      cservername,
5130                                                      driver->info_3->helpfile,
5131                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5132                                                      0);
5133                 W_ERROR_NOT_OK_RETURN(result);
5134                 count++;
5135         }
5136
5137         for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5138                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5139                                             struct spoolss_DriverFileInfo,
5140                                             count + 1);
5141                 W_ERROR_HAVE_NO_MEMORY(info);
5142                 result = fill_spoolss_DriverFileInfo(info,
5143                                                      &info[count],
5144                                                      cservername,
5145                                                      driver->info_3->dependentfiles[i],
5146                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5147                                                      0);
5148                 W_ERROR_NOT_OK_RETURN(result);
5149                 count++;
5150         }
5151
5152         *info_p = info;
5153         *count_p = count;
5154
5155         return WERR_OK;
5156 }
5157
5158 /********************************************************************
5159  * fill a spoolss_DriverInfo101 sttruct
5160  ********************************************************************/
5161
5162 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5163                                           struct spoolss_DriverInfo101 *r,
5164                                           const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5165                                           const char *servername)
5166 {
5167         const char *cservername = canon_servername(servername);
5168         WERROR result;
5169
5170         r->version              = driver->info_3->cversion;
5171
5172         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5173         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5174         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5175         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5176
5177         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5178                                                     cservername,
5179                                                     &r->file_info,
5180                                                     &r->file_count);
5181         if (!W_ERROR_IS_OK(result)) {
5182                 return result;
5183         }
5184
5185         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5186         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5187
5188         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5189         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5190
5191         r->previous_names = string_array_from_driver_info(mem_ctx,
5192                                                           NULL,
5193                                                           cservername);
5194         r->driver_date          = 0;
5195         r->driver_version       = 0;
5196
5197         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5198         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5199         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5200         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5201         r->hardware_id          = talloc_strdup(mem_ctx, "");
5202         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5203         r->provider             = talloc_strdup(mem_ctx, "");
5204         W_ERROR_HAVE_NO_MEMORY(r->provider);
5205
5206         return WERR_OK;
5207 }
5208
5209 /********************************************************************
5210  * construct_printer_driver_info_1
5211  ********************************************************************/
5212
5213 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5214                                               struct spoolss_DriverInfo1 *r,
5215                                               int snum,
5216                                               const char *servername,
5217                                               const char *architecture,
5218                                               uint32_t version)
5219 {
5220         NT_PRINTER_INFO_LEVEL *printer = NULL;
5221         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5222         WERROR result;
5223
5224         ZERO_STRUCT(driver);
5225
5226         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5227                 return WERR_INVALID_PRINTER_NAME;
5228
5229         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5230                 free_a_printer(&printer, 2);
5231                 return WERR_UNKNOWN_PRINTER_DRIVER;
5232         }
5233
5234         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5235
5236         free_a_printer(&printer,2);
5237
5238         return result;
5239 }
5240
5241 /********************************************************************
5242  * construct_printer_driver_info_2
5243  * fill a printer_info_2 struct
5244  ********************************************************************/
5245
5246 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5247                                               struct spoolss_DriverInfo2 *r,
5248                                               int snum,
5249                                               const char *servername,
5250                                               const char *architecture,
5251                                               uint32_t version)
5252 {
5253         NT_PRINTER_INFO_LEVEL *printer = NULL;
5254         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5255         WERROR result;
5256
5257         ZERO_STRUCT(printer);
5258         ZERO_STRUCT(driver);
5259
5260         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5261                 return WERR_INVALID_PRINTER_NAME;
5262
5263         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5264                 free_a_printer(&printer, 2);
5265                 return WERR_UNKNOWN_PRINTER_DRIVER;
5266         }
5267
5268         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5269
5270         free_a_printer(&printer,2);
5271
5272         return result;
5273 }
5274
5275 /********************************************************************
5276  * construct_printer_info_3
5277  * fill a printer_info_3 struct
5278  ********************************************************************/
5279
5280 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5281                                               struct spoolss_DriverInfo3 *r,
5282                                               int snum,
5283                                               const char *servername,
5284                                               const char *architecture,
5285                                               uint32_t version)
5286 {
5287         NT_PRINTER_INFO_LEVEL *printer = NULL;
5288         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5289         WERROR status;
5290         ZERO_STRUCT(driver);
5291
5292         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5293         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5294         if (!W_ERROR_IS_OK(status))
5295                 return WERR_INVALID_PRINTER_NAME;
5296
5297         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5298         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5299
5300 #if 0   /* JERRY */
5301
5302         /*
5303          * I put this code in during testing.  Helpful when commenting out the
5304          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5305          * as win2k always queries the driver using an infor level of 6.
5306          * I've left it in (but ifdef'd out) because I'll probably
5307          * use it in experimentation again in the future.   --jerry 22/01/2002
5308          */
5309
5310         if (!W_ERROR_IS_OK(status)) {
5311                 /*
5312                  * Is this a W2k client ?
5313                  */
5314                 if (version == 3) {
5315                         /* Yes - try again with a WinNT driver. */
5316                         version = 2;
5317                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5318                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5319                 }
5320 #endif
5321
5322                 if (!W_ERROR_IS_OK(status)) {
5323                         free_a_printer(&printer,2);
5324                         return WERR_UNKNOWN_PRINTER_DRIVER;
5325                 }
5326
5327 #if 0   /* JERRY */
5328         }
5329 #endif
5330
5331
5332         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5333
5334         free_a_printer(&printer,2);
5335
5336         return status;
5337 }
5338
5339 /********************************************************************
5340  * construct_printer_info_6
5341  * fill a printer_info_6 struct
5342  ********************************************************************/
5343
5344 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5345                                               struct spoolss_DriverInfo6 *r,
5346                                               int snum,
5347                                               const char *servername,
5348                                               const char *architecture,
5349                                               uint32_t version)
5350 {
5351         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5352         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5353         WERROR                          status;
5354
5355         ZERO_STRUCT(driver);
5356
5357         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5358
5359         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5360
5361         if (!W_ERROR_IS_OK(status))
5362                 return WERR_INVALID_PRINTER_NAME;
5363
5364         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5365
5366         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5367
5368         if (!W_ERROR_IS_OK(status))
5369         {
5370                 /*
5371                  * Is this a W2k client ?
5372                  */
5373
5374                 if (version < 3) {
5375                         free_a_printer(&printer,2);
5376                         return WERR_UNKNOWN_PRINTER_DRIVER;
5377                 }
5378
5379                 /* Yes - try again with a WinNT driver. */
5380                 version = 2;
5381                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5382                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5383                 if (!W_ERROR_IS_OK(status)) {
5384                         free_a_printer(&printer,2);
5385                         return WERR_UNKNOWN_PRINTER_DRIVER;
5386                 }
5387         }
5388
5389         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5390
5391         free_a_printer(&printer,2);
5392         free_a_printer_driver(driver, 3);
5393
5394         return status;
5395 }
5396
5397 /********************************************************************
5398  * construct_printer_info_101
5399  * fill a printer_info_101 struct
5400  ********************************************************************/
5401
5402 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5403                                                 struct spoolss_DriverInfo101 *r,
5404                                                 int snum,
5405                                                 const char *servername,
5406                                                 const char *architecture,
5407                                                 uint32_t version)
5408 {
5409         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5410         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5411         WERROR                          result;
5412
5413         ZERO_STRUCT(driver);
5414
5415         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5416
5417         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5418                 win_errstr(result)));
5419
5420         if (!W_ERROR_IS_OK(result)) {
5421                 return WERR_INVALID_PRINTER_NAME;
5422         }
5423
5424         result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5425                                       architecture, version);
5426
5427         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5428                 win_errstr(result)));
5429
5430         if (!W_ERROR_IS_OK(result)) {
5431                 /*
5432                  * Is this a W2k client ?
5433                  */
5434
5435                 if (version < 3) {
5436                         free_a_printer(&printer, 2);
5437                         return WERR_UNKNOWN_PRINTER_DRIVER;
5438                 }
5439
5440                 /* Yes - try again with a WinNT driver. */
5441                 version = 2;
5442                 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5443                                               architecture, version);
5444                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5445                         win_errstr(result)));
5446                 if (!W_ERROR_IS_OK(result)) {
5447                         free_a_printer(&printer, 2);
5448                         return WERR_UNKNOWN_PRINTER_DRIVER;
5449                 }
5450         }
5451
5452         result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5453
5454         free_a_printer(&printer, 2);
5455         free_a_printer_driver(driver, 3);
5456
5457         return result;
5458 }
5459
5460 /****************************************************************
5461  _spoolss_GetPrinterDriver2
5462 ****************************************************************/
5463
5464 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5465                                   struct spoolss_GetPrinterDriver2 *r)
5466 {
5467         Printer_entry *printer;
5468         WERROR result;
5469
5470         const char *servername;
5471         int snum;
5472
5473         /* that's an [in out] buffer */
5474
5475         if (!r->in.buffer && (r->in.offered != 0)) {
5476                 return WERR_INVALID_PARAM;
5477         }
5478
5479         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5480
5481         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5482                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5483                 return WERR_INVALID_PRINTER_NAME;
5484         }
5485
5486         *r->out.needed = 0;
5487         *r->out.server_major_version = 0;
5488         *r->out.server_minor_version = 0;
5489
5490         servername = get_server_name(printer);
5491
5492         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5493                 return WERR_BADFID;
5494         }
5495
5496         switch (r->in.level) {
5497         case 1:
5498                 result = construct_printer_driver_info_1(p->mem_ctx,
5499                                                          &r->out.info->info1,
5500                                                          snum,
5501                                                          servername,
5502                                                          r->in.architecture,
5503                                                          r->in.client_major_version);
5504                 break;
5505         case 2:
5506                 result = construct_printer_driver_info_2(p->mem_ctx,
5507                                                          &r->out.info->info2,
5508                                                          snum,
5509                                                          servername,
5510                                                          r->in.architecture,
5511                                                          r->in.client_major_version);
5512                 break;
5513         case 3:
5514                 result = construct_printer_driver_info_3(p->mem_ctx,
5515                                                          &r->out.info->info3,
5516                                                          snum,
5517                                                          servername,
5518                                                          r->in.architecture,
5519                                                          r->in.client_major_version);
5520                 break;
5521         case 6:
5522                 result = construct_printer_driver_info_6(p->mem_ctx,
5523                                                          &r->out.info->info6,
5524                                                          snum,
5525                                                          servername,
5526                                                          r->in.architecture,
5527                                                          r->in.client_major_version);
5528                 break;
5529         case 101:
5530                 result = construct_printer_driver_info_101(p->mem_ctx,
5531                                                            &r->out.info->info101,
5532                                                            snum,
5533                                                            servername,
5534                                                            r->in.architecture,
5535                                                            r->in.client_major_version);
5536                 break;
5537         default:
5538                 result = WERR_UNKNOWN_LEVEL;
5539                 break;
5540         }
5541
5542         if (!W_ERROR_IS_OK(result)) {
5543                 TALLOC_FREE(r->out.info);
5544                 return result;
5545         }
5546
5547         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5548                                                r->out.info, r->in.level);
5549         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5550
5551         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5552 }
5553
5554
5555 /****************************************************************
5556  _spoolss_StartPagePrinter
5557 ****************************************************************/
5558
5559 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5560                                  struct spoolss_StartPagePrinter *r)
5561 {
5562         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5563
5564         if (!Printer) {
5565                 DEBUG(3,("_spoolss_StartPagePrinter: "
5566                         "Error in startpageprinter printer handle\n"));
5567                 return WERR_BADFID;
5568         }
5569
5570         Printer->page_started = true;
5571         return WERR_OK;
5572 }
5573
5574 /****************************************************************
5575  _spoolss_EndPagePrinter
5576 ****************************************************************/
5577
5578 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5579                                struct spoolss_EndPagePrinter *r)
5580 {
5581         int snum;
5582
5583         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5584
5585         if (!Printer) {
5586                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5587                         OUR_HANDLE(r->in.handle)));
5588                 return WERR_BADFID;
5589         }
5590
5591         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5592                 return WERR_BADFID;
5593
5594         Printer->page_started = false;
5595         print_job_endpage(snum, Printer->jobid);
5596
5597         return WERR_OK;
5598 }
5599
5600 /****************************************************************
5601  _spoolss_StartDocPrinter
5602 ****************************************************************/
5603
5604 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5605                                 struct spoolss_StartDocPrinter *r)
5606 {
5607         struct spoolss_DocumentInfo1 *info_1;
5608         int snum;
5609         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5610
5611         if (!Printer) {
5612                 DEBUG(2,("_spoolss_StartDocPrinter: "
5613                         "Invalid handle (%s:%u:%u)\n",
5614                         OUR_HANDLE(r->in.handle)));
5615                 return WERR_BADFID;
5616         }
5617
5618         if (r->in.level != 1) {
5619                 return WERR_UNKNOWN_LEVEL;
5620         }
5621
5622         info_1 = r->in.info.info1;
5623
5624         /*
5625          * a nice thing with NT is it doesn't listen to what you tell it.
5626          * when asked to send _only_ RAW datas, it tries to send datas
5627          * in EMF format.
5628          *
5629          * So I add checks like in NT Server ...
5630          */
5631
5632         if (info_1->datatype) {
5633                 if (strcmp(info_1->datatype, "RAW") != 0) {
5634                         *r->out.job_id = 0;
5635                         return WERR_INVALID_DATATYPE;
5636                 }
5637         }
5638
5639         /* get the share number of the printer */
5640         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5641                 return WERR_BADFID;
5642         }
5643
5644         Printer->jobid = print_job_start(p->server_info, snum,
5645                                          info_1->document_name,
5646                                          Printer->nt_devmode);
5647
5648         /* An error occured in print_job_start() so return an appropriate
5649            NT error code. */
5650
5651         if (Printer->jobid == -1) {
5652                 return map_werror_from_unix(errno);
5653         }
5654
5655         Printer->document_started = true;
5656         *r->out.job_id = Printer->jobid;
5657
5658         return WERR_OK;
5659 }
5660
5661 /****************************************************************
5662  _spoolss_EndDocPrinter
5663 ****************************************************************/
5664
5665 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5666                               struct spoolss_EndDocPrinter *r)
5667 {
5668         return _spoolss_enddocprinter_internal(p, r->in.handle);
5669 }
5670
5671 /****************************************************************
5672  _spoolss_WritePrinter
5673 ****************************************************************/
5674
5675 WERROR _spoolss_WritePrinter(pipes_struct *p,
5676                              struct spoolss_WritePrinter *r)
5677 {
5678         uint32_t buffer_written;
5679         int snum;
5680         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5681
5682         if (!Printer) {
5683                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5684                         OUR_HANDLE(r->in.handle)));
5685                 *r->out.num_written = r->in._data_size;
5686                 return WERR_BADFID;
5687         }
5688
5689         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5690                 return WERR_BADFID;
5691
5692         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5693                                                    (const char *)r->in.data.data,
5694                                                    (SMB_OFF_T)-1,
5695                                                    (size_t)r->in._data_size);
5696         if (buffer_written == (uint32_t)-1) {
5697                 *r->out.num_written = 0;
5698                 if (errno == ENOSPC)
5699                         return WERR_NO_SPOOL_SPACE;
5700                 else
5701                         return WERR_ACCESS_DENIED;
5702         }
5703
5704         *r->out.num_written = r->in._data_size;
5705
5706         return WERR_OK;
5707 }
5708
5709 /********************************************************************
5710  * api_spoolss_getprinter
5711  * called from the spoolss dispatcher
5712  *
5713  ********************************************************************/
5714
5715 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5716                               pipes_struct *p)
5717 {
5718         int snum;
5719         WERROR errcode = WERR_BADFUNC;
5720         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5721
5722         if (!Printer) {
5723                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5724                         OUR_HANDLE(handle)));
5725                 return WERR_BADFID;
5726         }
5727
5728         if (!get_printer_snum(p, handle, &snum, NULL))
5729                 return WERR_BADFID;
5730
5731         switch (command) {
5732         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5733                 errcode = print_queue_pause(p->server_info, snum);
5734                 break;
5735         case SPOOLSS_PRINTER_CONTROL_RESUME:
5736         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5737                 errcode = print_queue_resume(p->server_info, snum);
5738                 break;
5739         case SPOOLSS_PRINTER_CONTROL_PURGE:
5740                 errcode = print_queue_purge(p->server_info, snum);
5741                 break;
5742         default:
5743                 return WERR_UNKNOWN_LEVEL;
5744         }
5745
5746         return errcode;
5747 }
5748
5749
5750 /****************************************************************
5751  _spoolss_AbortPrinter
5752  * From MSDN: "Deletes printer's spool file if printer is configured
5753  * for spooling"
5754 ****************************************************************/
5755
5756 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5757                              struct spoolss_AbortPrinter *r)
5758 {
5759         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5760         int             snum;
5761         WERROR          errcode = WERR_OK;
5762
5763         if (!Printer) {
5764                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5765                         OUR_HANDLE(r->in.handle)));
5766                 return WERR_BADFID;
5767         }
5768
5769         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5770                 return WERR_BADFID;
5771
5772         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5773
5774         return errcode;
5775 }
5776
5777 /********************************************************************
5778  * called by spoolss_api_setprinter
5779  * when updating a printer description
5780  ********************************************************************/
5781
5782 static WERROR update_printer_sec(struct policy_handle *handle,
5783                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5784 {
5785         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5786         WERROR result;
5787         int snum;
5788
5789         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5790
5791         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5792                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5793                          OUR_HANDLE(handle)));
5794
5795                 result = WERR_BADFID;
5796                 goto done;
5797         }
5798
5799         if (!secdesc_ctr) {
5800                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5801                 result = WERR_INVALID_PARAM;
5802                 goto done;
5803         }
5804
5805         /* Check the user has permissions to change the security
5806            descriptor.  By experimentation with two NT machines, the user
5807            requires Full Access to the printer to change security
5808            information. */
5809
5810         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5811                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5812                 result = WERR_ACCESS_DENIED;
5813                 goto done;
5814         }
5815
5816         /* NT seems to like setting the security descriptor even though
5817            nothing may have actually changed. */
5818
5819         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5820                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5821                 result = WERR_BADFID;
5822                 goto done;
5823         }
5824
5825         if (DEBUGLEVEL >= 10) {
5826                 SEC_ACL *the_acl;
5827                 int i;
5828
5829                 the_acl = old_secdesc_ctr->sd->dacl;
5830                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5831                            PRINTERNAME(snum), the_acl->num_aces));
5832
5833                 for (i = 0; i < the_acl->num_aces; i++) {
5834                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5835                                            &the_acl->aces[i].trustee),
5836                                   the_acl->aces[i].access_mask));
5837                 }
5838
5839                 the_acl = secdesc_ctr->sd->dacl;
5840
5841                 if (the_acl) {
5842                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5843                                    PRINTERNAME(snum), the_acl->num_aces));
5844
5845                         for (i = 0; i < the_acl->num_aces; i++) {
5846                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5847                                                    &the_acl->aces[i].trustee),
5848                                            the_acl->aces[i].access_mask));
5849                         }
5850                 } else {
5851                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5852                 }
5853         }
5854
5855         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5856         if (!new_secdesc_ctr) {
5857                 result = WERR_NOMEM;
5858                 goto done;
5859         }
5860
5861         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5862                 result = WERR_OK;
5863                 goto done;
5864         }
5865
5866         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5867
5868  done:
5869
5870         return result;
5871 }
5872
5873 /********************************************************************
5874  Canonicalize printer info from a client
5875
5876  ATTN: It does not matter what we set the servername to hear
5877  since we do the necessary work in get_a_printer() to set it to
5878  the correct value based on what the client sent in the
5879  _spoolss_open_printer_ex().
5880  ********************************************************************/
5881
5882 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5883 {
5884         fstring printername;
5885         const char *p;
5886
5887         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5888                 "portname=%s drivername=%s comment=%s location=%s\n",
5889                 info->servername, info->printername, info->sharename,
5890                 info->portname, info->drivername, info->comment, info->location));
5891
5892         /* we force some elements to "correct" values */
5893         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5894         fstrcpy(info->sharename, lp_servicename(snum));
5895
5896         /* check to see if we allow printername != sharename */
5897
5898         if ( lp_force_printername(snum) ) {
5899                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5900                         global_myname(), info->sharename );
5901         } else {
5902
5903                 /* make sure printername is in \\server\printername format */
5904
5905                 fstrcpy( printername, info->printername );
5906                 p = printername;
5907                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5908                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5909                                 p++;
5910                 }
5911
5912                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5913                          global_myname(), p );
5914         }
5915
5916         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5917         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5918
5919
5920
5921         return true;
5922 }
5923
5924 /****************************************************************************
5925 ****************************************************************************/
5926
5927 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5928 {
5929         char *cmd = lp_addport_cmd();
5930         char *command = NULL;
5931         int ret;
5932         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5933         bool is_print_op = false;
5934
5935         if ( !*cmd ) {
5936                 return WERR_ACCESS_DENIED;
5937         }
5938
5939         command = talloc_asprintf(ctx,
5940                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5941         if (!command) {
5942                 return WERR_NOMEM;
5943         }
5944
5945         if ( token )
5946                 is_print_op = user_has_privileges( token, &se_printop );
5947
5948         DEBUG(10,("Running [%s]\n", command));
5949
5950         /********* BEGIN SePrintOperatorPrivilege **********/
5951
5952         if ( is_print_op )
5953                 become_root();
5954
5955         ret = smbrun(command, NULL);
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
5966         if ( ret != 0 ) {
5967                 return WERR_ACCESS_DENIED;
5968         }
5969
5970         return WERR_OK;
5971 }
5972
5973 /****************************************************************************
5974 ****************************************************************************/
5975
5976 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5977 {
5978         char *cmd = lp_addprinter_cmd();
5979         char **qlines;
5980         char *command = NULL;
5981         int numlines;
5982         int ret;
5983         int fd;
5984         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5985         bool is_print_op = false;
5986         char *remote_machine = talloc_strdup(ctx, "%m");
5987
5988         if (!remote_machine) {
5989                 return false;
5990         }
5991         remote_machine = talloc_sub_basic(ctx,
5992                                 current_user_info.smb_name,
5993                                 current_user_info.domain,
5994                                 remote_machine);
5995         if (!remote_machine) {
5996                 return false;
5997         }
5998
5999         command = talloc_asprintf(ctx,
6000                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6001                         cmd, printer->info_2->printername, printer->info_2->sharename,
6002                         printer->info_2->portname, printer->info_2->drivername,
6003                         printer->info_2->location, printer->info_2->comment, remote_machine);
6004         if (!command) {
6005                 return false;
6006         }
6007
6008         if ( token )
6009                 is_print_op = user_has_privileges( token, &se_printop );
6010
6011         DEBUG(10,("Running [%s]\n", command));
6012
6013         /********* BEGIN SePrintOperatorPrivilege **********/
6014
6015         if ( is_print_op )
6016                 become_root();
6017
6018         if ( (ret = smbrun(command, &fd)) == 0 ) {
6019                 /* Tell everyone we updated smb.conf. */
6020                 message_send_all(smbd_messaging_context(),
6021                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6022         }
6023
6024         if ( is_print_op )
6025                 unbecome_root();
6026
6027         /********* END SePrintOperatorPrivilege **********/
6028
6029         DEBUGADD(10,("returned [%d]\n", ret));
6030
6031         TALLOC_FREE(command);
6032         TALLOC_FREE(remote_machine);
6033
6034         if ( ret != 0 ) {
6035                 if (fd != -1)
6036                         close(fd);
6037                 return false;
6038         }
6039
6040         /* reload our services immediately */
6041         reload_services(false);
6042
6043         numlines = 0;
6044         /* Get lines and convert them back to dos-codepage */
6045         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6046         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6047         close(fd);
6048
6049         /* Set the portname to what the script says the portname should be. */
6050         /* but don't require anything to be return from the script exit a good error code */
6051
6052         if (numlines) {
6053                 /* Set the portname to what the script says the portname should be. */
6054                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6055                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6056         }
6057
6058         TALLOC_FREE(qlines);
6059         return true;
6060 }
6061
6062
6063 /********************************************************************
6064  * Called by spoolss_api_setprinter
6065  * when updating a printer description.
6066  ********************************************************************/
6067
6068 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6069                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6070                              struct spoolss_DeviceMode *devmode)
6071 {
6072         int snum;
6073         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6074         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6075         WERROR result;
6076         UNISTR2 buffer;
6077         fstring asc_buffer;
6078
6079         DEBUG(8,("update_printer\n"));
6080
6081         result = WERR_OK;
6082
6083         if (!Printer) {
6084                 result = WERR_BADFID;
6085                 goto done;
6086         }
6087
6088         if (!get_printer_snum(p, handle, &snum, NULL)) {
6089                 result = WERR_BADFID;
6090                 goto done;
6091         }
6092
6093         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6094             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6095                 result = WERR_BADFID;
6096                 goto done;
6097         }
6098
6099         DEBUGADD(8,("Converting info_2 struct\n"));
6100
6101         /*
6102          * convert_printer_info converts the incoming
6103          * info from the client and overwrites the info
6104          * just read from the tdb in the pointer 'printer'.
6105          */
6106
6107         if (!convert_printer_info(info_ctr, printer)) {
6108                 result =  WERR_NOMEM;
6109                 goto done;
6110         }
6111
6112         if (devmode) {
6113                 /* we have a valid devmode
6114                    convert it and link it*/
6115
6116                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6117                 if (!convert_devicemode(printer->info_2->printername, devmode,
6118                                         &printer->info_2->devmode)) {
6119                         result =  WERR_NOMEM;
6120                         goto done;
6121                 }
6122         }
6123
6124         /* Do sanity check on the requested changes for Samba */
6125
6126         if (!check_printer_ok(printer->info_2, snum)) {
6127                 result = WERR_INVALID_PARAM;
6128                 goto done;
6129         }
6130
6131         /* FIXME!!! If the driver has changed we really should verify that
6132            it is installed before doing much else   --jerry */
6133
6134         /* Check calling user has permission to update printer description */
6135
6136         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6137                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6138                 result = WERR_ACCESS_DENIED;
6139                 goto done;
6140         }
6141
6142         /* Call addprinter hook */
6143         /* Check changes to see if this is really needed */
6144
6145         if ( *lp_addprinter_cmd()
6146                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6147                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6148                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6149                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6150         {
6151                 /* add_printer_hook() will call reload_services() */
6152
6153                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6154                                        printer) ) {
6155                         result = WERR_ACCESS_DENIED;
6156                         goto done;
6157                 }
6158         }
6159
6160         /*
6161          * When a *new* driver is bound to a printer, the drivername is used to
6162          * lookup previously saved driver initialization info, which is then
6163          * bound to the printer, simulating what happens in the Windows arch.
6164          */
6165         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6166         {
6167                 if (!set_driver_init(printer, 2))
6168                 {
6169                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6170                                 printer->info_2->drivername));
6171                 }
6172
6173                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6174                         printer->info_2->drivername));
6175
6176                 notify_printer_driver(snum, printer->info_2->drivername);
6177         }
6178
6179         /*
6180          * flag which changes actually occured.  This is a small subset of
6181          * all the possible changes.  We also have to update things in the
6182          * DsSpooler key.
6183          */
6184
6185         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6186                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6187                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6188                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6189
6190                 notify_printer_comment(snum, printer->info_2->comment);
6191         }
6192
6193         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6194                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6195                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6196                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6197
6198                 notify_printer_sharename(snum, printer->info_2->sharename);
6199         }
6200
6201         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6202                 char *pname;
6203
6204                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6205                         pname++;
6206                 else
6207                         pname = printer->info_2->printername;
6208
6209
6210                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6211                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6212                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6213
6214                 notify_printer_printername( snum, pname );
6215         }
6216
6217         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6218                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6219                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6220                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6221
6222                 notify_printer_port(snum, printer->info_2->portname);
6223         }
6224
6225         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6226                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6227                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6228                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6229
6230                 notify_printer_location(snum, printer->info_2->location);
6231         }
6232
6233         /* here we need to update some more DsSpooler keys */
6234         /* uNCName, serverName, shortServerName */
6235
6236         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6237         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6238                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6239         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6240                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6241
6242         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6243                  global_myname(), printer->info_2->sharename );
6244         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6245         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6246                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6247
6248         /* Update printer info */
6249         result = mod_a_printer(printer, 2);
6250
6251 done:
6252         free_a_printer(&printer, 2);
6253         free_a_printer(&old_printer, 2);
6254
6255
6256         return result;
6257 }
6258
6259 /****************************************************************************
6260 ****************************************************************************/
6261 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6262                                            struct policy_handle *handle,
6263                                            struct spoolss_SetPrinterInfo7 *info7)
6264 {
6265 #ifdef HAVE_ADS
6266         int snum;
6267         Printer_entry *Printer;
6268
6269         if ( lp_security() != SEC_ADS ) {
6270                 return WERR_UNKNOWN_LEVEL;
6271         }
6272
6273         Printer = find_printer_index_by_hnd(p, handle);
6274
6275         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6276
6277         if (!Printer)
6278                 return WERR_BADFID;
6279
6280         if (!get_printer_snum(p, handle, &snum, NULL))
6281                 return WERR_BADFID;
6282
6283         nt_printer_publish(Printer, snum, info7->action);
6284
6285         return WERR_OK;
6286 #else
6287         return WERR_UNKNOWN_LEVEL;
6288 #endif
6289 }
6290
6291 /****************************************************************
6292  _spoolss_SetPrinter
6293 ****************************************************************/
6294
6295 WERROR _spoolss_SetPrinter(pipes_struct *p,
6296                            struct spoolss_SetPrinter *r)
6297 {
6298         WERROR result;
6299
6300         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6301
6302         if (!Printer) {
6303                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6304                         OUR_HANDLE(r->in.handle)));
6305                 return WERR_BADFID;
6306         }
6307
6308         /* check the level */
6309         switch (r->in.info_ctr->level) {
6310                 case 0:
6311                         return control_printer(r->in.handle, r->in.command, p);
6312                 case 2:
6313                         result = update_printer(p, r->in.handle,
6314                                                 r->in.info_ctr,
6315                                                 r->in.devmode_ctr->devmode);
6316                         if (!W_ERROR_IS_OK(result))
6317                                 return result;
6318                         if (r->in.secdesc_ctr->sd)
6319                                 result = update_printer_sec(r->in.handle, p,
6320                                                             r->in.secdesc_ctr);
6321                         return result;
6322                 case 3:
6323                         return update_printer_sec(r->in.handle, p,
6324                                                   r->in.secdesc_ctr);
6325                 case 7:
6326                         return publish_or_unpublish_printer(p, r->in.handle,
6327                                                             r->in.info_ctr->info.info7);
6328                 default:
6329                         return WERR_UNKNOWN_LEVEL;
6330         }
6331 }
6332
6333 /****************************************************************
6334  _spoolss_FindClosePrinterNotify
6335 ****************************************************************/
6336
6337 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6338                                        struct spoolss_FindClosePrinterNotify *r)
6339 {
6340         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6341
6342         if (!Printer) {
6343                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6344                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6345                 return WERR_BADFID;
6346         }
6347
6348         if (Printer->notify.client_connected == true) {
6349                 int snum = -1;
6350
6351                 if ( Printer->printer_type == SPLHND_SERVER)
6352                         snum = -1;
6353                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6354                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6355                         return WERR_BADFID;
6356
6357                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6358         }
6359
6360         Printer->notify.flags=0;
6361         Printer->notify.options=0;
6362         Printer->notify.localmachine[0]='\0';
6363         Printer->notify.printerlocal=0;
6364         TALLOC_FREE(Printer->notify.option);
6365         Printer->notify.client_connected = false;
6366
6367         return WERR_OK;
6368 }
6369
6370 /****************************************************************
6371  _spoolss_AddJob
6372 ****************************************************************/
6373
6374 WERROR _spoolss_AddJob(pipes_struct *p,
6375                        struct spoolss_AddJob *r)
6376 {
6377         if (!r->in.buffer && (r->in.offered != 0)) {
6378                 return WERR_INVALID_PARAM;
6379         }
6380
6381         /* this is what a NT server returns for AddJob. AddJob must fail on
6382          * non-local printers */
6383
6384         if (r->in.level != 1) {
6385                 return WERR_UNKNOWN_LEVEL;
6386         }
6387
6388         return WERR_INVALID_PARAM;
6389 }
6390
6391 /****************************************************************************
6392 fill_job_info1
6393 ****************************************************************************/
6394
6395 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6396                              struct spoolss_JobInfo1 *r,
6397                              const print_queue_struct *queue,
6398                              int position, int snum,
6399                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6400 {
6401         struct tm *t;
6402
6403         t = gmtime(&queue->time);
6404
6405         r->job_id               = queue->job;
6406
6407         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6408         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6409         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6410         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6411         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6412         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6413         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6414         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6415         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6416         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6417         r->text_status          = talloc_strdup(mem_ctx, "");
6418         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6419
6420         r->status               = nt_printj_status(queue->status);
6421         r->priority             = queue->priority;
6422         r->position             = position;
6423         r->total_pages          = queue->page_count;
6424         r->pages_printed        = 0; /* ??? */
6425
6426         init_systemtime(&r->submitted, t);
6427
6428         return WERR_OK;
6429 }
6430
6431 /****************************************************************************
6432 fill_job_info2
6433 ****************************************************************************/
6434
6435 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6436                              struct spoolss_JobInfo2 *r,
6437                              const print_queue_struct *queue,
6438                              int position, int snum,
6439                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6440                              struct spoolss_DeviceMode *devmode)
6441 {
6442         struct tm *t;
6443
6444         t = gmtime(&queue->time);
6445
6446         r->job_id               = queue->job;
6447
6448         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6449         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6450         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6451         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6452         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6453         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6454         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6455         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6456         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6457         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6458         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6459         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6460         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6461         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6462         r->parameters           = talloc_strdup(mem_ctx, "");
6463         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6464         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6465         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6466
6467         r->devmode              = devmode;
6468
6469         r->text_status          = talloc_strdup(mem_ctx, "");
6470         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6471
6472         r->secdesc              = NULL;
6473
6474         r->status               = nt_printj_status(queue->status);
6475         r->priority             = queue->priority;
6476         r->position             = position;
6477         r->start_time           = 0;
6478         r->until_time           = 0;
6479         r->total_pages          = queue->page_count;
6480         r->size                 = queue->size;
6481         init_systemtime(&r->submitted, t);
6482         r->time                 = 0;
6483         r->pages_printed        = 0; /* ??? */
6484
6485         return WERR_OK;
6486 }
6487
6488 /****************************************************************************
6489  Enumjobs at level 1.
6490 ****************************************************************************/
6491
6492 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6493                               const print_queue_struct *queue,
6494                               uint32_t num_queues, int snum,
6495                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6496                               union spoolss_JobInfo **info_p,
6497                               uint32_t *count)
6498 {
6499         union spoolss_JobInfo *info;
6500         int i;
6501         WERROR result = WERR_OK;
6502
6503         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6504         W_ERROR_HAVE_NO_MEMORY(info);
6505
6506         *count = num_queues;
6507
6508         for (i=0; i<*count; i++) {
6509                 result = fill_job_info1(info,
6510                                         &info[i].info1,
6511                                         &queue[i],
6512                                         i,
6513                                         snum,
6514                                         ntprinter);
6515                 if (!W_ERROR_IS_OK(result)) {
6516                         goto out;
6517                 }
6518         }
6519
6520  out:
6521         if (!W_ERROR_IS_OK(result)) {
6522                 TALLOC_FREE(info);
6523                 *count = 0;
6524                 return result;
6525         }
6526
6527         *info_p = info;
6528
6529         return WERR_OK;
6530 }
6531
6532 /****************************************************************************
6533  Enumjobs at level 2.
6534 ****************************************************************************/
6535
6536 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6537                               const print_queue_struct *queue,
6538                               uint32_t num_queues, int snum,
6539                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6540                               union spoolss_JobInfo **info_p,
6541                               uint32_t *count)
6542 {
6543         union spoolss_JobInfo *info;
6544         int i;
6545         WERROR result = WERR_OK;
6546
6547         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6548         W_ERROR_HAVE_NO_MEMORY(info);
6549
6550         *count = num_queues;
6551
6552         for (i=0; i<*count; i++) {
6553
6554                 struct spoolss_DeviceMode *devmode;
6555
6556                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6557                 if (!devmode) {
6558                         result = WERR_NOMEM;
6559                         goto out;
6560                 }
6561
6562                 result = fill_job_info2(info,
6563                                         &info[i].info2,
6564                                         &queue[i],
6565                                         i,
6566                                         snum,
6567                                         ntprinter,
6568                                         devmode);
6569                 if (!W_ERROR_IS_OK(result)) {
6570                         goto out;
6571                 }
6572         }
6573
6574  out:
6575         if (!W_ERROR_IS_OK(result)) {
6576                 TALLOC_FREE(info);
6577                 *count = 0;
6578                 return result;
6579         }
6580
6581         *info_p = info;
6582
6583         return WERR_OK;
6584 }
6585
6586 /****************************************************************
6587  _spoolss_EnumJobs
6588 ****************************************************************/
6589
6590 WERROR _spoolss_EnumJobs(pipes_struct *p,
6591                          struct spoolss_EnumJobs *r)
6592 {
6593         WERROR result;
6594         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6595         int snum;
6596         print_status_struct prt_status;
6597         print_queue_struct *queue = NULL;
6598         uint32_t count;
6599
6600         /* that's an [in out] buffer */
6601
6602         if (!r->in.buffer && (r->in.offered != 0)) {
6603                 return WERR_INVALID_PARAM;
6604         }
6605
6606         DEBUG(4,("_spoolss_EnumJobs\n"));
6607
6608         *r->out.needed = 0;
6609         *r->out.count = 0;
6610         *r->out.info = NULL;
6611
6612         /* lookup the printer snum and tdb entry */
6613
6614         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6615                 return WERR_BADFID;
6616         }
6617
6618         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6619         if (!W_ERROR_IS_OK(result)) {
6620                 return result;
6621         }
6622
6623         count = print_queue_status(snum, &queue, &prt_status);
6624         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6625                 count, prt_status.status, prt_status.message));
6626
6627         if (count == 0) {
6628                 SAFE_FREE(queue);
6629                 free_a_printer(&ntprinter, 2);
6630                 return WERR_OK;
6631         }
6632
6633         switch (r->in.level) {
6634         case 1:
6635                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6636                                          ntprinter, r->out.info, r->out.count);
6637                 break;
6638         case 2:
6639                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6640                                          ntprinter, r->out.info, r->out.count);
6641                 break;
6642         default:
6643                 result = WERR_UNKNOWN_LEVEL;
6644                 break;
6645         }
6646
6647         SAFE_FREE(queue);
6648         free_a_printer(&ntprinter, 2);
6649
6650         if (!W_ERROR_IS_OK(result)) {
6651                 return result;
6652         }
6653
6654         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6655                                                      spoolss_EnumJobs, NULL,
6656                                                      *r->out.info, r->in.level,
6657                                                      *r->out.count);
6658         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6659         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6660
6661         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6662 }
6663
6664 /****************************************************************
6665  _spoolss_ScheduleJob
6666 ****************************************************************/
6667
6668 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6669                             struct spoolss_ScheduleJob *r)
6670 {
6671         return WERR_OK;
6672 }
6673
6674 /****************************************************************
6675  _spoolss_SetJob
6676 ****************************************************************/
6677
6678 WERROR _spoolss_SetJob(pipes_struct *p,
6679                        struct spoolss_SetJob *r)
6680 {
6681         int snum;
6682         WERROR errcode = WERR_BADFUNC;
6683
6684         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6685                 return WERR_BADFID;
6686         }
6687
6688         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6689                 return WERR_INVALID_PRINTER_NAME;
6690         }
6691
6692         switch (r->in.command) {
6693         case SPOOLSS_JOB_CONTROL_CANCEL:
6694         case SPOOLSS_JOB_CONTROL_DELETE:
6695                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6696                         errcode = WERR_OK;
6697                 }
6698                 break;
6699         case SPOOLSS_JOB_CONTROL_PAUSE:
6700                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6701                         errcode = WERR_OK;
6702                 }
6703                 break;
6704         case SPOOLSS_JOB_CONTROL_RESTART:
6705         case SPOOLSS_JOB_CONTROL_RESUME:
6706                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6707                         errcode = WERR_OK;
6708                 }
6709                 break;
6710         default:
6711                 return WERR_UNKNOWN_LEVEL;
6712         }
6713
6714         return errcode;
6715 }
6716
6717 /****************************************************************************
6718  Enumerates all printer drivers by level.
6719 ****************************************************************************/
6720
6721 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6722                                        const char *servername,
6723                                        const char *architecture,
6724                                        uint32_t level,
6725                                        union spoolss_DriverInfo **info_p,
6726                                        uint32_t *count_p)
6727 {
6728         int i;
6729         int ndrivers;
6730         uint32_t version;
6731         fstring *list = NULL;
6732         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6733         union spoolss_DriverInfo *info = NULL;
6734         uint32_t count = 0;
6735         WERROR result = WERR_OK;
6736
6737         *count_p = 0;
6738         *info_p = NULL;
6739
6740         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6741                 list = NULL;
6742                 ndrivers = get_ntdrivers(&list, architecture, version);
6743                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6744                         ndrivers, architecture, version));
6745
6746                 if (ndrivers == -1) {
6747                         result = WERR_NOMEM;
6748                         goto out;
6749                 }
6750
6751                 if (ndrivers != 0) {
6752                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6753                                                     union spoolss_DriverInfo,
6754                                                     count + ndrivers);
6755                         if (!info) {
6756                                 DEBUG(0,("enumprinterdrivers_level1: "
6757                                         "failed to enlarge driver info buffer!\n"));
6758                                 result = WERR_NOMEM;
6759                                 goto out;
6760                         }
6761                 }
6762
6763                 for (i=0; i<ndrivers; i++) {
6764                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6765                         ZERO_STRUCT(driver);
6766                         result = get_a_printer_driver(&driver, 3, list[i],
6767                                                       architecture, version);
6768                         if (!W_ERROR_IS_OK(result)) {
6769                                 goto out;
6770                         }
6771
6772                         switch (level) {
6773                         case 1:
6774                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6775                                                                    &driver, servername,
6776                                                                    architecture);
6777                                 break;
6778                         case 2:
6779                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6780                                                                    &driver, servername);
6781                                 break;
6782                         case 3:
6783                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6784                                                                    &driver, servername);
6785                                 break;
6786                         case 4:
6787                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6788                                                                    &driver, servername);
6789                                 break;
6790                         case 5:
6791                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6792                                                                    &driver, servername);
6793                                 break;
6794                         case 6:
6795                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6796                                                                    &driver, servername);
6797                                 break;
6798                         default:
6799                                 result = WERR_UNKNOWN_LEVEL;
6800                                 break;
6801                         }
6802
6803                         if (!W_ERROR_IS_OK(result)) {
6804                                 free_a_printer_driver(driver, 3);
6805                                 goto out;
6806                         }
6807                         free_a_printer_driver(driver, 3);
6808                 }
6809
6810                 count += ndrivers;
6811                 SAFE_FREE(list);
6812         }
6813
6814  out:
6815         SAFE_FREE(list);
6816
6817         if (!W_ERROR_IS_OK(result)) {
6818                 TALLOC_FREE(info);
6819                 return result;
6820         }
6821
6822         *info_p = info;
6823         *count_p = count;
6824
6825         return WERR_OK;
6826 }
6827
6828 /****************************************************************************
6829  Enumerates all printer drivers at level 1.
6830 ****************************************************************************/
6831
6832 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6833                                         const char *servername,
6834                                         const char *architecture,
6835                                         union spoolss_DriverInfo **info_p,
6836                                         uint32_t *count)
6837 {
6838         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6839                                         info_p, count);
6840 }
6841
6842 /****************************************************************************
6843  Enumerates all printer drivers at level 2.
6844 ****************************************************************************/
6845
6846 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6847                                         const char *servername,
6848                                         const char *architecture,
6849                                         union spoolss_DriverInfo **info_p,
6850                                         uint32_t *count)
6851 {
6852         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6853                                         info_p, count);
6854 }
6855
6856 /****************************************************************************
6857  Enumerates all printer drivers at level 3.
6858 ****************************************************************************/
6859
6860 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6861                                         const char *servername,
6862                                         const char *architecture,
6863                                         union spoolss_DriverInfo **info_p,
6864                                         uint32_t *count)
6865 {
6866         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6867                                         info_p, count);
6868 }
6869
6870 /****************************************************************************
6871  Enumerates all printer drivers at level 4.
6872 ****************************************************************************/
6873
6874 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6875                                         const char *servername,
6876                                         const char *architecture,
6877                                         union spoolss_DriverInfo **info_p,
6878                                         uint32_t *count)
6879 {
6880         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6881                                         info_p, count);
6882 }
6883
6884 /****************************************************************************
6885  Enumerates all printer drivers at level 5.
6886 ****************************************************************************/
6887
6888 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6889                                         const char *servername,
6890                                         const char *architecture,
6891                                         union spoolss_DriverInfo **info_p,
6892                                         uint32_t *count)
6893 {
6894         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6895                                         info_p, count);
6896 }
6897
6898 /****************************************************************************
6899  Enumerates all printer drivers at level 6.
6900 ****************************************************************************/
6901
6902 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6903                                         const char *servername,
6904                                         const char *architecture,
6905                                         union spoolss_DriverInfo **info_p,
6906                                         uint32_t *count)
6907 {
6908         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6909                                         info_p, count);
6910 }
6911
6912
6913 /****************************************************************
6914  _spoolss_EnumPrinterDrivers
6915 ****************************************************************/
6916
6917 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6918                                    struct spoolss_EnumPrinterDrivers *r)
6919 {
6920         const char *cservername;
6921         WERROR result;
6922
6923         /* that's an [in out] buffer */
6924
6925         if (!r->in.buffer && (r->in.offered != 0)) {
6926                 return WERR_INVALID_PARAM;
6927         }
6928
6929         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6930
6931         *r->out.needed = 0;
6932         *r->out.count = 0;
6933         *r->out.info = NULL;
6934
6935         cservername = canon_servername(r->in.server);
6936
6937         if (!is_myname_or_ipaddr(cservername)) {
6938                 return WERR_UNKNOWN_PRINTER_DRIVER;
6939         }
6940
6941         switch (r->in.level) {
6942         case 1:
6943                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6944                                                    r->in.environment,
6945                                                    r->out.info, r->out.count);
6946                 break;
6947         case 2:
6948                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6949                                                    r->in.environment,
6950                                                    r->out.info, r->out.count);
6951                 break;
6952         case 3:
6953                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6954                                                    r->in.environment,
6955                                                    r->out.info, r->out.count);
6956                 break;
6957         case 4:
6958                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6959                                                    r->in.environment,
6960                                                    r->out.info, r->out.count);
6961                 break;
6962         case 5:
6963                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6964                                                    r->in.environment,
6965                                                    r->out.info, r->out.count);
6966                 break;
6967         case 6:
6968                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6969                                                    r->in.environment,
6970                                                    r->out.info, r->out.count);
6971                 break;
6972         default:
6973                 return WERR_UNKNOWN_LEVEL;
6974         }
6975
6976         if (!W_ERROR_IS_OK(result)) {
6977                 return result;
6978         }
6979
6980         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6981                                                      spoolss_EnumPrinterDrivers, NULL,
6982                                                      *r->out.info, r->in.level,
6983                                                      *r->out.count);
6984         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6985         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6986
6987         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6988 }
6989
6990 /****************************************************************************
6991 ****************************************************************************/
6992
6993 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6994                                struct spoolss_FormInfo1 *r,
6995                                const nt_forms_struct *form)
6996 {
6997         r->form_name    = talloc_strdup(mem_ctx, form->name);
6998         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6999
7000         r->flags        = form->flag;
7001         r->size.width   = form->width;
7002         r->size.height  = form->length;
7003         r->area.left    = form->left;
7004         r->area.top     = form->top;
7005         r->area.right   = form->right;
7006         r->area.bottom  = form->bottom;
7007
7008         return WERR_OK;
7009 }
7010
7011 /****************************************************************
7012  spoolss_enumforms_level1
7013 ****************************************************************/
7014
7015 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7016                                        const nt_forms_struct *builtin_forms,
7017                                        uint32_t num_builtin_forms,
7018                                        const nt_forms_struct *user_forms,
7019                                        uint32_t num_user_forms,
7020                                        union spoolss_FormInfo **info_p,
7021                                        uint32_t *count)
7022 {
7023         union spoolss_FormInfo *info;
7024         WERROR result = WERR_OK;
7025         int i;
7026
7027         *count = num_builtin_forms + num_user_forms;
7028
7029         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7030         W_ERROR_HAVE_NO_MEMORY(info);
7031
7032         /* construct the list of form structures */
7033         for (i=0; i<num_builtin_forms; i++) {
7034                 DEBUGADD(6,("Filling form number [%d]\n",i));
7035                 result = fill_form_info_1(info, &info[i].info1,
7036                                           &builtin_forms[i]);
7037                 if (!W_ERROR_IS_OK(result)) {
7038                         goto out;
7039                 }
7040         }
7041
7042         for (; i<num_user_forms; i++) {
7043                 DEBUGADD(6,("Filling form number [%d]\n",i));
7044                 result = fill_form_info_1(info, &info[i].info1,
7045                                           &user_forms[i-num_builtin_forms]);
7046                 if (!W_ERROR_IS_OK(result)) {
7047                         goto out;
7048                 }
7049         }
7050
7051  out:
7052         if (!W_ERROR_IS_OK(result)) {
7053                 TALLOC_FREE(info);
7054                 *count = 0;
7055                 return result;
7056         }
7057
7058         *info_p = info;
7059
7060         return WERR_OK;
7061 }
7062
7063 /****************************************************************
7064  _spoolss_EnumForms
7065 ****************************************************************/
7066
7067 WERROR _spoolss_EnumForms(pipes_struct *p,
7068                           struct spoolss_EnumForms *r)
7069 {
7070         WERROR result;
7071         nt_forms_struct *user_forms = NULL;
7072         nt_forms_struct *builtin_forms = NULL;
7073         uint32_t num_user_forms;
7074         uint32_t num_builtin_forms;
7075
7076         *r->out.count = 0;
7077         *r->out.needed = 0;
7078         *r->out.info = NULL;
7079
7080         /* that's an [in out] buffer */
7081
7082         if (!r->in.buffer && (r->in.offered != 0) ) {
7083                 return WERR_INVALID_PARAM;
7084         }
7085
7086         DEBUG(4,("_spoolss_EnumForms\n"));
7087         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7088         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7089
7090         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7091         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7092         num_user_forms = get_ntforms(&user_forms);
7093         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7094
7095         if (num_user_forms + num_builtin_forms == 0) {
7096                 SAFE_FREE(builtin_forms);
7097                 SAFE_FREE(user_forms);
7098                 return WERR_NO_MORE_ITEMS;
7099         }
7100
7101         switch (r->in.level) {
7102         case 1:
7103                 result = spoolss_enumforms_level1(p->mem_ctx,
7104                                                   builtin_forms,
7105                                                   num_builtin_forms,
7106                                                   user_forms,
7107                                                   num_user_forms,
7108                                                   r->out.info,
7109                                                   r->out.count);
7110                 break;
7111         default:
7112                 result = WERR_UNKNOWN_LEVEL;
7113                 break;
7114         }
7115
7116         SAFE_FREE(user_forms);
7117         SAFE_FREE(builtin_forms);
7118
7119         if (!W_ERROR_IS_OK(result)) {
7120                 return result;
7121         }
7122
7123         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7124                                                      spoolss_EnumForms, NULL,
7125                                                      *r->out.info, r->in.level,
7126                                                      *r->out.count);
7127         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7128         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7129
7130         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7131 }
7132
7133 /****************************************************************
7134 ****************************************************************/
7135
7136 static WERROR find_form_byname(const char *name,
7137                                nt_forms_struct *form)
7138 {
7139         nt_forms_struct *list = NULL;
7140         int num_forms = 0, i = 0;
7141
7142         if (get_a_builtin_ntform_by_string(name, form)) {
7143                 return WERR_OK;
7144         }
7145
7146         num_forms = get_ntforms(&list);
7147         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7148
7149         if (num_forms == 0) {
7150                 return WERR_BADFID;
7151         }
7152
7153         /* Check if the requested name is in the list of form structures */
7154         for (i = 0; i < num_forms; i++) {
7155
7156                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7157
7158                 if (strequal(name, list[i].name)) {
7159                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7160                         *form = list[i];
7161                         SAFE_FREE(list);
7162                         return WERR_OK;
7163                 }
7164         }
7165
7166         SAFE_FREE(list);
7167
7168         return WERR_BADFID;
7169 }
7170
7171 /****************************************************************
7172  _spoolss_GetForm
7173 ****************************************************************/
7174
7175 WERROR _spoolss_GetForm(pipes_struct *p,
7176                         struct spoolss_GetForm *r)
7177 {
7178         WERROR result;
7179         nt_forms_struct form;
7180
7181         /* that's an [in out] buffer */
7182
7183         if (!r->in.buffer && (r->in.offered != 0)) {
7184                 return WERR_INVALID_PARAM;
7185         }
7186
7187         DEBUG(4,("_spoolss_GetForm\n"));
7188         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7189         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7190
7191         result = find_form_byname(r->in.form_name, &form);
7192         if (!W_ERROR_IS_OK(result)) {
7193                 TALLOC_FREE(r->out.info);
7194                 return result;
7195         }
7196
7197         switch (r->in.level) {
7198         case 1:
7199                 result = fill_form_info_1(p->mem_ctx,
7200                                           &r->out.info->info1,
7201                                           &form);
7202                 break;
7203
7204         default:
7205                 result = WERR_UNKNOWN_LEVEL;
7206                 break;
7207         }
7208
7209         if (!W_ERROR_IS_OK(result)) {
7210                 TALLOC_FREE(r->out.info);
7211                 return result;
7212         }
7213
7214         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7215                                                r->out.info, r->in.level);
7216         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7217
7218         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7219 }
7220
7221 /****************************************************************************
7222 ****************************************************************************/
7223
7224 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7225                           struct spoolss_PortInfo1 *r,
7226                           const char *name)
7227 {
7228         r->port_name = talloc_strdup(mem_ctx, name);
7229         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7230
7231         return WERR_OK;
7232 }
7233
7234 /****************************************************************************
7235  TODO: This probably needs distinguish between TCP/IP and Local ports
7236  somehow.
7237 ****************************************************************************/
7238
7239 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7240                           struct spoolss_PortInfo2 *r,
7241                           const char *name)
7242 {
7243         r->port_name = talloc_strdup(mem_ctx, name);
7244         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7245
7246         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7247         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7248
7249         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7250         W_ERROR_HAVE_NO_MEMORY(r->description);
7251
7252         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7253         r->reserved = 0;
7254
7255         return WERR_OK;
7256 }
7257
7258
7259 /****************************************************************************
7260  wrapper around the enumer ports command
7261 ****************************************************************************/
7262
7263 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7264 {
7265         char *cmd = lp_enumports_cmd();
7266         char **qlines = NULL;
7267         char *command = NULL;
7268         int numlines;
7269         int ret;
7270         int fd;
7271
7272         *count = 0;
7273         *lines = NULL;
7274
7275         /* if no hook then just fill in the default port */
7276
7277         if ( !*cmd ) {
7278                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7279                         return WERR_NOMEM;
7280                 }
7281                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7282                         TALLOC_FREE(qlines);
7283                         return WERR_NOMEM;
7284                 }
7285                 qlines[1] = NULL;
7286                 numlines = 1;
7287         }
7288         else {
7289                 /* we have a valid enumport command */
7290
7291                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7292                 if (!command) {
7293                         return WERR_NOMEM;
7294                 }
7295
7296                 DEBUG(10,("Running [%s]\n", command));
7297                 ret = smbrun(command, &fd);
7298                 DEBUG(10,("Returned [%d]\n", ret));
7299                 TALLOC_FREE(command);
7300                 if (ret != 0) {
7301                         if (fd != -1) {
7302                                 close(fd);
7303                         }
7304                         return WERR_ACCESS_DENIED;
7305                 }
7306
7307                 numlines = 0;
7308                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7309                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7310                 close(fd);
7311         }
7312
7313         *count = numlines;
7314         *lines = qlines;
7315
7316         return WERR_OK;
7317 }
7318
7319 /****************************************************************************
7320  enumports level 1.
7321 ****************************************************************************/
7322
7323 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7324                                 union spoolss_PortInfo **info_p,
7325                                 uint32_t *count)
7326 {
7327         union spoolss_PortInfo *info = NULL;
7328         int i=0;
7329         WERROR result = WERR_OK;
7330         char **qlines = NULL;
7331         int numlines = 0;
7332
7333         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7334         if (!W_ERROR_IS_OK(result)) {
7335                 goto out;
7336         }
7337
7338         if (numlines) {
7339                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7340                 if (!info) {
7341                         DEBUG(10,("Returning WERR_NOMEM\n"));
7342                         result = WERR_NOMEM;
7343                         goto out;
7344                 }
7345
7346                 for (i=0; i<numlines; i++) {
7347                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7348                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7349                         if (!W_ERROR_IS_OK(result)) {
7350                                 goto out;
7351                         }
7352                 }
7353         }
7354         TALLOC_FREE(qlines);
7355
7356 out:
7357         if (!W_ERROR_IS_OK(result)) {
7358                 TALLOC_FREE(info);
7359                 TALLOC_FREE(qlines);
7360                 *count = 0;
7361                 *info_p = NULL;
7362                 return result;
7363         }
7364
7365         *info_p = info;
7366         *count = numlines;
7367
7368         return WERR_OK;
7369 }
7370
7371 /****************************************************************************
7372  enumports level 2.
7373 ****************************************************************************/
7374
7375 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7376                                 union spoolss_PortInfo **info_p,
7377                                 uint32_t *count)
7378 {
7379         union spoolss_PortInfo *info = NULL;
7380         int i=0;
7381         WERROR result = WERR_OK;
7382         char **qlines = NULL;
7383         int numlines = 0;
7384
7385         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7386         if (!W_ERROR_IS_OK(result)) {
7387                 goto out;
7388         }
7389
7390         if (numlines) {
7391                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7392                 if (!info) {
7393                         DEBUG(10,("Returning WERR_NOMEM\n"));
7394                         result = WERR_NOMEM;
7395                         goto out;
7396                 }
7397
7398                 for (i=0; i<numlines; i++) {
7399                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7400                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7401                         if (!W_ERROR_IS_OK(result)) {
7402                                 goto out;
7403                         }
7404                 }
7405         }
7406         TALLOC_FREE(qlines);
7407
7408 out:
7409         if (!W_ERROR_IS_OK(result)) {
7410                 TALLOC_FREE(info);
7411                 TALLOC_FREE(qlines);
7412                 *count = 0;
7413                 *info_p = NULL;
7414                 return result;
7415         }
7416
7417         *info_p = info;
7418         *count = numlines;
7419
7420         return WERR_OK;
7421 }
7422
7423 /****************************************************************
7424  _spoolss_EnumPorts
7425 ****************************************************************/
7426
7427 WERROR _spoolss_EnumPorts(pipes_struct *p,
7428                           struct spoolss_EnumPorts *r)
7429 {
7430         WERROR result;
7431
7432         /* that's an [in out] buffer */
7433
7434         if (!r->in.buffer && (r->in.offered != 0)) {
7435                 return WERR_INVALID_PARAM;
7436         }
7437
7438         DEBUG(4,("_spoolss_EnumPorts\n"));
7439
7440         *r->out.count = 0;
7441         *r->out.needed = 0;
7442         *r->out.info = NULL;
7443
7444         switch (r->in.level) {
7445         case 1:
7446                 result = enumports_level_1(p->mem_ctx, r->out.info,
7447                                            r->out.count);
7448                 break;
7449         case 2:
7450                 result = enumports_level_2(p->mem_ctx, r->out.info,
7451                                            r->out.count);
7452                 break;
7453         default:
7454                 return WERR_UNKNOWN_LEVEL;
7455         }
7456
7457         if (!W_ERROR_IS_OK(result)) {
7458                 return result;
7459         }
7460
7461         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7462                                                      spoolss_EnumPorts, NULL,
7463                                                      *r->out.info, r->in.level,
7464                                                      *r->out.count);
7465         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7466         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7467
7468         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7469 }
7470
7471 /****************************************************************************
7472 ****************************************************************************/
7473
7474 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7475                                            const char *server,
7476                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7477                                            struct spoolss_DeviceMode *devmode,
7478                                            struct security_descriptor *sec_desc,
7479                                            struct spoolss_UserLevelCtr *user_ctr,
7480                                            struct policy_handle *handle)
7481 {
7482         NT_PRINTER_INFO_LEVEL *printer = NULL;
7483         fstring name;
7484         int     snum;
7485         WERROR err = WERR_OK;
7486
7487         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7488                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7489                 return WERR_NOMEM;
7490         }
7491
7492         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7493         if (!convert_printer_info(info_ctr, printer)) {
7494                 free_a_printer(&printer, 2);
7495                 return WERR_NOMEM;
7496         }
7497
7498         /* check to see if the printer already exists */
7499
7500         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7501                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7502                         printer->info_2->sharename));
7503                 free_a_printer(&printer, 2);
7504                 return WERR_PRINTER_ALREADY_EXISTS;
7505         }
7506
7507         /* FIXME!!!  smbd should check to see if the driver is installed before
7508            trying to add a printer like this  --jerry */
7509
7510         if (*lp_addprinter_cmd() ) {
7511                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7512                                        printer) ) {
7513                         free_a_printer(&printer,2);
7514                         return WERR_ACCESS_DENIED;
7515                 }
7516         } else {
7517                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7518                         "smb.conf parameter \"addprinter command\" is defined. This"
7519                         "parameter must exist for this call to succeed\n",
7520                         printer->info_2->sharename ));
7521         }
7522
7523         /* use our primary netbios name since get_a_printer() will convert
7524            it to what the client expects on a case by case basis */
7525
7526         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7527              printer->info_2->sharename);
7528
7529
7530         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7531                 free_a_printer(&printer,2);
7532                 return WERR_ACCESS_DENIED;
7533         }
7534
7535         /* you must be a printer admin to add a new printer */
7536         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7537                 free_a_printer(&printer,2);
7538                 return WERR_ACCESS_DENIED;
7539         }
7540
7541         /*
7542          * Do sanity check on the requested changes for Samba.
7543          */
7544
7545         if (!check_printer_ok(printer->info_2, snum)) {
7546                 free_a_printer(&printer,2);
7547                 return WERR_INVALID_PARAM;
7548         }
7549
7550         /*
7551          * When a printer is created, the drivername bound to the printer is used
7552          * to lookup previously saved driver initialization info, which is then
7553          * bound to the new printer, simulating what happens in the Windows arch.
7554          */
7555
7556         if (!devmode)
7557         {
7558                 set_driver_init(printer, 2);
7559         }
7560         else
7561         {
7562                 /* A valid devmode was included, convert and link it
7563                 */
7564                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7565
7566                 if (!convert_devicemode(printer->info_2->printername, devmode,
7567                                         &printer->info_2->devmode)) {
7568                         return  WERR_NOMEM;
7569                 }
7570         }
7571
7572         /* write the ASCII on disk */
7573         err = mod_a_printer(printer, 2);
7574         if (!W_ERROR_IS_OK(err)) {
7575                 free_a_printer(&printer,2);
7576                 return err;
7577         }
7578
7579         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7580                 /* Handle open failed - remove addition. */
7581                 del_a_printer(printer->info_2->sharename);
7582                 free_a_printer(&printer,2);
7583                 ZERO_STRUCTP(handle);
7584                 return WERR_ACCESS_DENIED;
7585         }
7586
7587         update_c_setprinter(false);
7588         free_a_printer(&printer,2);
7589
7590         return WERR_OK;
7591 }
7592
7593 /****************************************************************
7594  _spoolss_AddPrinterEx
7595 ****************************************************************/
7596
7597 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7598                              struct spoolss_AddPrinterEx *r)
7599 {
7600         switch (r->in.info_ctr->level) {
7601         case 1:
7602                 /* we don't handle yet */
7603                 /* but I know what to do ... */
7604                 return WERR_UNKNOWN_LEVEL;
7605         case 2:
7606                 return spoolss_addprinterex_level_2(p, r->in.server,
7607                                                     r->in.info_ctr,
7608                                                     r->in.devmode_ctr->devmode,
7609                                                     r->in.secdesc_ctr->sd,
7610                                                     r->in.userlevel_ctr,
7611                                                     r->out.handle);
7612         default:
7613                 return WERR_UNKNOWN_LEVEL;
7614         }
7615 }
7616
7617 /****************************************************************
7618  _spoolss_AddPrinterDriver
7619 ****************************************************************/
7620
7621 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7622                                  struct spoolss_AddPrinterDriver *r)
7623 {
7624         uint32_t level = r->in.info_ctr->level;
7625         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7626         WERROR err = WERR_OK;
7627         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7628         const char *driver_name = NULL;
7629         uint32_t version;
7630         const char *fn;
7631
7632         switch (p->hdr_req.opnum) {
7633                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7634                         fn = "_spoolss_AddPrinterDriver";
7635                         break;
7636                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7637                         fn = "_spoolss_AddPrinterDriverEx";
7638                         break;
7639                 default:
7640                         return WERR_INVALID_PARAM;
7641         }
7642
7643
7644         /* FIXME */
7645         if (level != 3 && level != 6) {
7646                 /* Clever hack from Martin Zielinski <mz@seh.de>
7647                  * to allow downgrade from level 8 (Vista).
7648                  */
7649                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7650                 return WERR_UNKNOWN_LEVEL;
7651         }
7652
7653         ZERO_STRUCT(driver);
7654
7655         if (!convert_printer_driver_info(info, &driver, level)) {
7656                 err = WERR_NOMEM;
7657                 goto done;
7658         }
7659
7660         DEBUG(5,("Cleaning driver's information\n"));
7661         err = clean_up_driver_struct(p, driver, level);
7662         if (!W_ERROR_IS_OK(err))
7663                 goto done;
7664
7665         DEBUG(5,("Moving driver to final destination\n"));
7666         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7667                                                               &err)) ) {
7668                 goto done;
7669         }
7670
7671         if (add_a_printer_driver(driver, level)!=0) {
7672                 err = WERR_ACCESS_DENIED;
7673                 goto done;
7674         }
7675
7676         switch(level) {
7677         case 3:
7678                 driver_name = driver.info_3->name ? driver.info_3->name : "";
7679                 break;
7680         case 6:
7681                 driver_name = driver.info_6->name ? driver.info_6->name : "";
7682                 break;
7683         }
7684
7685         /*
7686          * I think this is where he DrvUpgradePrinter() hook would be
7687          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7688          * server.  Right now, we just need to send ourselves a message
7689          * to update each printer bound to this driver.   --jerry
7690          */
7691
7692         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7693                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7694                         fn, driver_name));
7695         }
7696
7697         /*
7698          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7699          * decide if the driver init data should be deleted. The rules are:
7700          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7701          *  2) delete init data only if there is no 2k/Xp driver
7702          *  3) always delete init data
7703          * The generalized rule is always use init data from the highest order driver.
7704          * It is necessary to follow the driver install by an initialization step to
7705          * finish off this process.
7706         */
7707         if (level == 3)
7708                 version = driver.info_3->cversion;
7709         else if (level == 6)
7710                 version = driver.info_6->version;
7711         else
7712                 version = -1;
7713         switch (version) {
7714                 /*
7715                  * 9x printer driver - never delete init data
7716                 */
7717                 case 0:
7718                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7719                                 fn, driver_name));
7720                         break;
7721
7722                 /*
7723                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7724                  * there is no 2k/Xp driver init data for this driver name.
7725                 */
7726                 case 2:
7727                 {
7728                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7729
7730                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7731                                 /*
7732                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7733                                 */
7734                                 if (!del_driver_init(driver_name))
7735                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7736                                                 fn, driver_name));
7737                         } else {
7738                                 /*
7739                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7740                                 */
7741                                 free_a_printer_driver(driver1,3);
7742                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7743                                         fn, driver_name));
7744                         }
7745                 }
7746                 break;
7747
7748                 /*
7749                  * 2k or Xp printer driver - always delete init data
7750                 */
7751                 case 3:
7752                         if (!del_driver_init(driver_name))
7753                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7754                                         fn, driver_name));
7755                         break;
7756
7757                 default:
7758                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7759                         break;
7760         }
7761
7762
7763 done:
7764         free_a_printer_driver(driver, level);
7765         return err;
7766 }
7767
7768 /****************************************************************
7769  _spoolss_AddPrinterDriverEx
7770 ****************************************************************/
7771
7772 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7773                                    struct spoolss_AddPrinterDriverEx *r)
7774 {
7775         struct spoolss_AddPrinterDriver a;
7776
7777         /*
7778          * we only support the semantics of AddPrinterDriver()
7779          * i.e. only copy files that are newer than existing ones
7780          */
7781
7782         if (r->in.flags != APD_COPY_NEW_FILES) {
7783                 return WERR_ACCESS_DENIED;
7784         }
7785
7786         a.in.servername         = r->in.servername;
7787         a.in.info_ctr           = r->in.info_ctr;
7788
7789         return _spoolss_AddPrinterDriver(p, &a);
7790 }
7791
7792 /****************************************************************************
7793 ****************************************************************************/
7794
7795 struct _spoolss_paths {
7796         int type;
7797         const char *share;
7798         const char *dir;
7799 };
7800
7801 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7802
7803 static const struct _spoolss_paths spoolss_paths[]= {
7804         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7805         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7806 };
7807
7808 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7809                                           const char *servername,
7810                                           const char *environment,
7811                                           int component,
7812                                           char **path)
7813 {
7814         const char *pservername = NULL;
7815         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7816         const char *short_archi;
7817
7818         *path = NULL;
7819
7820         /* environment may be empty */
7821         if (environment && strlen(environment)) {
7822                 long_archi = environment;
7823         }
7824
7825         /* servername may be empty */
7826         if (servername && strlen(servername)) {
7827                 pservername = canon_servername(servername);
7828
7829                 if (!is_myname_or_ipaddr(pservername)) {
7830                         return WERR_INVALID_PARAM;
7831                 }
7832         }
7833
7834         if (!(short_archi = get_short_archi(long_archi))) {
7835                 return WERR_INVALID_ENVIRONMENT;
7836         }
7837
7838         switch (component) {
7839         case SPOOLSS_PRTPROCS_PATH:
7840         case SPOOLSS_DRIVER_PATH:
7841                 if (pservername) {
7842                         *path = talloc_asprintf(mem_ctx,
7843                                         "\\\\%s\\%s\\%s",
7844                                         pservername,
7845                                         spoolss_paths[component].share,
7846                                         short_archi);
7847                 } else {
7848                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7849                                         SPOOLSS_DEFAULT_SERVER_PATH,
7850                                         spoolss_paths[component].dir,
7851                                         short_archi);
7852                 }
7853                 break;
7854         default:
7855                 return WERR_INVALID_PARAM;
7856         }
7857
7858         if (!*path) {
7859                 return WERR_NOMEM;
7860         }
7861
7862         return WERR_OK;
7863 }
7864
7865 /****************************************************************************
7866 ****************************************************************************/
7867
7868 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7869                                           const char *servername,
7870                                           const char *environment,
7871                                           struct spoolss_DriverDirectoryInfo1 *r)
7872 {
7873         WERROR werr;
7874         char *path = NULL;
7875
7876         werr = compose_spoolss_server_path(mem_ctx,
7877                                            servername,
7878                                            environment,
7879                                            SPOOLSS_DRIVER_PATH,
7880                                            &path);
7881         if (!W_ERROR_IS_OK(werr)) {
7882                 return werr;
7883         }
7884
7885         DEBUG(4,("printer driver directory: [%s]\n", path));
7886
7887         r->directory_name = path;
7888
7889         return WERR_OK;
7890 }
7891
7892 /****************************************************************
7893  _spoolss_GetPrinterDriverDirectory
7894 ****************************************************************/
7895
7896 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7897                                           struct spoolss_GetPrinterDriverDirectory *r)
7898 {
7899         WERROR werror;
7900
7901         /* that's an [in out] buffer */
7902
7903         if (!r->in.buffer && (r->in.offered != 0)) {
7904                 return WERR_INVALID_PARAM;
7905         }
7906
7907         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7908                 r->in.level));
7909
7910         *r->out.needed = 0;
7911
7912         /* r->in.level is ignored */
7913
7914         werror = getprinterdriverdir_level_1(p->mem_ctx,
7915                                              r->in.server,
7916                                              r->in.environment,
7917                                              &r->out.info->info1);
7918         if (!W_ERROR_IS_OK(werror)) {
7919                 TALLOC_FREE(r->out.info);
7920                 return werror;
7921         }
7922
7923         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7924                                                r->out.info, r->in.level);
7925         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7926
7927         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7928 }
7929
7930 /****************************************************************
7931  _spoolss_EnumPrinterData
7932 ****************************************************************/
7933
7934 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7935                                 struct spoolss_EnumPrinterData *r)
7936 {
7937         NT_PRINTER_INFO_LEVEL *printer = NULL;
7938         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7939         int             snum;
7940         WERROR          result;
7941         struct regval_blob      *val = NULL;
7942         NT_PRINTER_DATA *p_data;
7943         int             i, key_index, num_values;
7944         int             name_length;
7945
7946         *r->out.value_needed    = 0;
7947         *r->out.type            = REG_NONE;
7948         *r->out.data_needed     = 0;
7949
7950         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7951
7952         if (!Printer) {
7953                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7954                         OUR_HANDLE(r->in.handle)));
7955                 return WERR_BADFID;
7956         }
7957
7958         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7959                 return WERR_BADFID;
7960         }
7961
7962         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7963         if (!W_ERROR_IS_OK(result)) {
7964                 return result;
7965         }
7966
7967         p_data = printer->info_2->data;
7968         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7969
7970         result = WERR_OK;
7971
7972         /*
7973          * The NT machine wants to know the biggest size of value and data
7974          *
7975          * cf: MSDN EnumPrinterData remark section
7976          */
7977
7978         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7979
7980                 uint32_t biggest_valuesize = 0;
7981                 uint32_t biggest_datasize = 0;
7982
7983                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7984
7985                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7986
7987                 for ( i=0; i<num_values; i++ )
7988                 {
7989                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7990
7991                         name_length = strlen(val->valuename);
7992                         if ( strlen(val->valuename) > biggest_valuesize )
7993                                 biggest_valuesize = name_length;
7994
7995                         if ( val->size > biggest_datasize )
7996                                 biggest_datasize = val->size;
7997
7998                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7999                                 biggest_datasize));
8000                 }
8001
8002                 /* the value is an UNICODE string but real_value_size is the length
8003                    in bytes including the trailing 0 */
8004
8005                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8006                 *r->out.data_needed  = biggest_datasize;
8007
8008                 DEBUG(6,("final values: [%d], [%d]\n",
8009                         *r->out.value_needed, *r->out.data_needed));
8010
8011                 goto done;
8012         }
8013
8014         /*
8015          * the value len is wrong in NT sp3
8016          * that's the number of bytes not the number of unicode chars
8017          */
8018
8019         if (key_index != -1) {
8020                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8021                                                 r->in.enum_index);
8022         }
8023
8024         if (!val) {
8025
8026                 /* out_value should default to "" or else NT4 has
8027                    problems unmarshalling the response */
8028
8029                 if (r->in.value_offered) {
8030                         *r->out.value_needed = 1;
8031                         r->out.value_name = talloc_strdup(r, "");
8032                         if (!r->out.value_name) {
8033                                 result = WERR_NOMEM;
8034                                 goto done;
8035                         }
8036                 } else {
8037                         r->out.value_name = NULL;
8038                         *r->out.value_needed = 0;
8039                 }
8040
8041                 /* the data is counted in bytes */
8042
8043                 *r->out.data_needed = r->in.data_offered;
8044
8045                 result = WERR_NO_MORE_ITEMS;
8046         } else {
8047                 /*
8048                  * the value is:
8049                  * - counted in bytes in the request
8050                  * - counted in UNICODE chars in the max reply
8051                  * - counted in bytes in the real size
8052                  *
8053                  * take a pause *before* coding not *during* coding
8054                  */
8055
8056                 /* name */
8057                 if (r->in.value_offered) {
8058                         r->out.value_name = talloc_strdup(r, regval_name(val));
8059                         if (!r->out.value_name) {
8060                                 result = WERR_NOMEM;
8061                                 goto done;
8062                         }
8063                         *r->out.value_needed = strlen_m(regval_name(val));
8064                 } else {
8065                         r->out.value_name = NULL;
8066                         *r->out.value_needed = 0;
8067                 }
8068
8069                 /* type */
8070
8071                 *r->out.type = regval_type(val);
8072
8073                 /* data - counted in bytes */
8074
8075                 if (r->out.data && regval_size(val)) {
8076                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
8077                 }
8078
8079                 *r->out.data_needed = regval_size(val);
8080         }
8081
8082 done:
8083         free_a_printer(&printer, 2);
8084         return result;
8085 }
8086
8087 /****************************************************************
8088  _spoolss_SetPrinterData
8089 ****************************************************************/
8090
8091 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8092                                struct spoolss_SetPrinterData *r)
8093 {
8094         NT_PRINTER_INFO_LEVEL *printer = NULL;
8095         int snum=0;
8096         WERROR result = WERR_OK;
8097         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8098         DATA_BLOB blob;
8099
8100         DEBUG(5,("_spoolss_SetPrinterData\n"));
8101
8102         if (!Printer) {
8103                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8104                         OUR_HANDLE(r->in.handle)));
8105                 return WERR_BADFID;
8106         }
8107
8108         if (Printer->printer_type == SPLHND_SERVER) {
8109                 DEBUG(10,("_spoolss_SetPrinterData: "
8110                         "Not implemented for server handles yet\n"));
8111                 return WERR_INVALID_PARAM;
8112         }
8113
8114         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8115                 return WERR_BADFID;
8116         }
8117
8118         /*
8119          * Access check : NT returns "access denied" if you make a
8120          * SetPrinterData call without the necessary privildge.
8121          * we were originally returning OK if nothing changed
8122          * which made Win2k issue **a lot** of SetPrinterData
8123          * when connecting to a printer  --jerry
8124          */
8125
8126         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8127                 DEBUG(3,("_spoolss_SetPrinterData: "
8128                         "change denied by handle access permissions\n"));
8129                 result = WERR_ACCESS_DENIED;
8130                 goto done;
8131         }
8132
8133         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8134         if (!W_ERROR_IS_OK(result)) {
8135                 return result;
8136         }
8137
8138         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8139                                           r->in.type, &r->in.data);
8140         if (!W_ERROR_IS_OK(result)) {
8141                 goto done;
8142         }
8143
8144         /*
8145          * When client side code sets a magic printer data key, detect it and save
8146          * the current printer data and the magic key's data (its the DEVMODE) for
8147          * future printer/driver initializations.
8148          */
8149         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8150                 /* Set devmode and printer initialization info */
8151                 result = save_driver_init(printer, 2, blob.data, blob.length);
8152
8153                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8154
8155                 goto done;
8156         }
8157
8158         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8159                                     r->in.value_name, r->in.type,
8160                                     blob.data, blob.length);
8161         if (W_ERROR_IS_OK(result)) {
8162                 result = mod_a_printer(printer, 2);
8163         }
8164
8165 done:
8166         free_a_printer(&printer, 2);
8167
8168         return result;
8169 }
8170
8171 /****************************************************************
8172  _spoolss_ResetPrinter
8173 ****************************************************************/
8174
8175 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8176                              struct spoolss_ResetPrinter *r)
8177 {
8178         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8179         int             snum;
8180
8181         DEBUG(5,("_spoolss_ResetPrinter\n"));
8182
8183         /*
8184          * All we do is to check to see if the handle and queue is valid.
8185          * This call really doesn't mean anything to us because we only
8186          * support RAW printing.   --jerry
8187          */
8188
8189         if (!Printer) {
8190                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8191                         OUR_HANDLE(r->in.handle)));
8192                 return WERR_BADFID;
8193         }
8194
8195         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8196                 return WERR_BADFID;
8197
8198
8199         /* blindly return success */
8200         return WERR_OK;
8201 }
8202
8203 /****************************************************************
8204  _spoolss_DeletePrinterData
8205 ****************************************************************/
8206
8207 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8208                                   struct spoolss_DeletePrinterData *r)
8209 {
8210         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8211         int             snum=0;
8212         WERROR          status = WERR_OK;
8213         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8214
8215         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8216
8217         if (!Printer) {
8218                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8219                         OUR_HANDLE(r->in.handle)));
8220                 return WERR_BADFID;
8221         }
8222
8223         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8224                 return WERR_BADFID;
8225
8226         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8227                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8228                         "printer properties change denied by handle\n"));
8229                 return WERR_ACCESS_DENIED;
8230         }
8231
8232         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8233         if (!W_ERROR_IS_OK(status))
8234                 return status;
8235
8236         if (!r->in.value_name) {
8237                 free_a_printer(&printer, 2);
8238                 return WERR_NOMEM;
8239         }
8240
8241         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8242                                         r->in.value_name );
8243
8244         if ( W_ERROR_IS_OK(status) )
8245                 mod_a_printer( printer, 2 );
8246
8247         free_a_printer(&printer, 2);
8248
8249         return status;
8250 }
8251
8252 /****************************************************************
8253  _spoolss_AddForm
8254 ****************************************************************/
8255
8256 WERROR _spoolss_AddForm(pipes_struct *p,
8257                         struct spoolss_AddForm *r)
8258 {
8259         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8260         nt_forms_struct tmpForm;
8261         int snum = -1;
8262         WERROR status = WERR_OK;
8263         NT_PRINTER_INFO_LEVEL *printer = NULL;
8264         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8265
8266         int count=0;
8267         nt_forms_struct *list=NULL;
8268         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8269
8270         DEBUG(5,("_spoolss_AddForm\n"));
8271
8272         if (!Printer) {
8273                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8274                         OUR_HANDLE(r->in.handle)));
8275                 return WERR_BADFID;
8276         }
8277
8278
8279         /* forms can be added on printer of on the print server handle */
8280
8281         if ( Printer->printer_type == SPLHND_PRINTER )
8282         {
8283                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8284                         return WERR_BADFID;
8285
8286                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8287                 if (!W_ERROR_IS_OK(status))
8288                         goto done;
8289         }
8290
8291         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8292            and not a printer admin, then fail */
8293
8294         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8295              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8296              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8297                                           NULL, NULL,
8298                                           p->server_info->ptok,
8299                                           lp_printer_admin(snum))) {
8300                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8301                 return WERR_ACCESS_DENIED;
8302         }
8303
8304         /* can't add if builtin */
8305
8306         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8307                 status = WERR_FILE_EXISTS;
8308                 goto done;
8309         }
8310
8311         count = get_ntforms(&list);
8312
8313         if(!add_a_form(&list, form, &count)) {
8314                 status =  WERR_NOMEM;
8315                 goto done;
8316         }
8317
8318         become_root();
8319         write_ntforms(&list, count);
8320         unbecome_root();
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_DeleteForm
8339 ****************************************************************/
8340
8341 WERROR _spoolss_DeleteForm(pipes_struct *p,
8342                            struct spoolss_DeleteForm *r)
8343 {
8344         const char *form_name = r->in.form_name;
8345         nt_forms_struct tmpForm;
8346         int count=0;
8347         nt_forms_struct *list=NULL;
8348         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8349         int snum = -1;
8350         WERROR status = WERR_OK;
8351         NT_PRINTER_INFO_LEVEL *printer = NULL;
8352         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8353         bool ret = false;
8354
8355         DEBUG(5,("_spoolss_DeleteForm\n"));
8356
8357         if (!Printer) {
8358                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8359                         OUR_HANDLE(r->in.handle)));
8360                 return WERR_BADFID;
8361         }
8362
8363         /* forms can be deleted 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 ((p->server_info->utok.uid != sec_initial_uid()) &&
8376              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8377              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8378                                           NULL, NULL,
8379                                           p->server_info->ptok,
8380                                           lp_printer_admin(snum))) {
8381                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8382                 return WERR_ACCESS_DENIED;
8383         }
8384
8385
8386         /* can't delete if builtin */
8387
8388         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8389                 status = WERR_INVALID_PARAM;
8390                 goto done;
8391         }
8392
8393         count = get_ntforms(&list);
8394
8395         become_root();
8396         ret = delete_a_form(&list, form_name, &count, &status);
8397         unbecome_root();
8398         if (ret == false) {
8399                 goto done;
8400         }
8401
8402         /*
8403          * ChangeID must always be set if this is a printer
8404          */
8405
8406         if ( Printer->printer_type == SPLHND_PRINTER )
8407                 status = mod_a_printer(printer, 2);
8408
8409 done:
8410         if ( printer )
8411                 free_a_printer(&printer, 2);
8412         SAFE_FREE(list);
8413
8414         return status;
8415 }
8416
8417 /****************************************************************
8418  _spoolss_SetForm
8419 ****************************************************************/
8420
8421 WERROR _spoolss_SetForm(pipes_struct *p,
8422                         struct spoolss_SetForm *r)
8423 {
8424         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8425         nt_forms_struct tmpForm;
8426         int snum = -1;
8427         WERROR status = WERR_OK;
8428         NT_PRINTER_INFO_LEVEL *printer = NULL;
8429         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8430
8431         int count=0;
8432         nt_forms_struct *list=NULL;
8433         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8434
8435         DEBUG(5,("_spoolss_SetForm\n"));
8436
8437         if (!Printer) {
8438                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8439                         OUR_HANDLE(r->in.handle)));
8440                 return WERR_BADFID;
8441         }
8442
8443         /* forms can be modified on printer of on the print server handle */
8444
8445         if ( Printer->printer_type == SPLHND_PRINTER )
8446         {
8447                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8448                         return WERR_BADFID;
8449
8450                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8451                 if (!W_ERROR_IS_OK(status))
8452                         goto done;
8453         }
8454
8455         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8456            and not a printer admin, then fail */
8457
8458         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8459              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8460              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8461                                           NULL, NULL,
8462                                           p->server_info->ptok,
8463                                           lp_printer_admin(snum))) {
8464                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8465                 return WERR_ACCESS_DENIED;
8466         }
8467
8468         /* can't set if builtin */
8469         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8470                 status = WERR_INVALID_PARAM;
8471                 goto done;
8472         }
8473
8474         count = get_ntforms(&list);
8475         update_a_form(&list, form, count);
8476         become_root();
8477         write_ntforms(&list, count);
8478         unbecome_root();
8479
8480         /*
8481          * ChangeID must always be set if this is a printer
8482          */
8483
8484         if ( Printer->printer_type == SPLHND_PRINTER )
8485                 status = mod_a_printer(printer, 2);
8486
8487
8488 done:
8489         if ( printer )
8490                 free_a_printer(&printer, 2);
8491         SAFE_FREE(list);
8492
8493         return status;
8494 }
8495
8496 /****************************************************************************
8497  fill_print_processor1
8498 ****************************************************************************/
8499
8500 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8501                                     struct spoolss_PrintProcessorInfo1 *r,
8502                                     const char *print_processor_name)
8503 {
8504         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8505         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8506
8507         return WERR_OK;
8508 }
8509
8510 /****************************************************************************
8511  enumprintprocessors level 1.
8512 ****************************************************************************/
8513
8514 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8515                                           union spoolss_PrintProcessorInfo **info_p,
8516                                           uint32_t *count)
8517 {
8518         union spoolss_PrintProcessorInfo *info;
8519         WERROR result;
8520
8521         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8522         W_ERROR_HAVE_NO_MEMORY(info);
8523
8524         *count = 1;
8525
8526         result = fill_print_processor1(info, &info[0].info1, "winprint");
8527         if (!W_ERROR_IS_OK(result)) {
8528                 goto out;
8529         }
8530
8531  out:
8532         if (!W_ERROR_IS_OK(result)) {
8533                 TALLOC_FREE(info);
8534                 *count = 0;
8535                 return result;
8536         }
8537
8538         *info_p = info;
8539
8540         return WERR_OK;
8541 }
8542
8543 /****************************************************************
8544  _spoolss_EnumPrintProcessors
8545 ****************************************************************/
8546
8547 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8548                                     struct spoolss_EnumPrintProcessors *r)
8549 {
8550         WERROR result;
8551
8552         /* that's an [in out] buffer */
8553
8554         if (!r->in.buffer && (r->in.offered != 0)) {
8555                 return WERR_INVALID_PARAM;
8556         }
8557
8558         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8559
8560         /*
8561          * Enumerate the print processors ...
8562          *
8563          * Just reply with "winprint", to keep NT happy
8564          * and I can use my nice printer checker.
8565          */
8566
8567         *r->out.count = 0;
8568         *r->out.needed = 0;
8569         *r->out.info = NULL;
8570
8571         switch (r->in.level) {
8572         case 1:
8573                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8574                                                      r->out.count);
8575                 break;
8576         default:
8577                 return WERR_UNKNOWN_LEVEL;
8578         }
8579
8580         if (!W_ERROR_IS_OK(result)) {
8581                 return result;
8582         }
8583
8584         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8585                                                      spoolss_EnumPrintProcessors, NULL,
8586                                                      *r->out.info, r->in.level,
8587                                                      *r->out.count);
8588         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8589         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8590
8591         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8592 }
8593
8594 /****************************************************************************
8595  fill_printprocdatatype1
8596 ****************************************************************************/
8597
8598 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8599                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8600                                       const char *name_array)
8601 {
8602         r->name_array = talloc_strdup(mem_ctx, name_array);
8603         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8604
8605         return WERR_OK;
8606 }
8607
8608 /****************************************************************************
8609  enumprintprocdatatypes level 1.
8610 ****************************************************************************/
8611
8612 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8613                                              union spoolss_PrintProcDataTypesInfo **info_p,
8614                                              uint32_t *count)
8615 {
8616         WERROR result;
8617         union spoolss_PrintProcDataTypesInfo *info;
8618
8619         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8620         W_ERROR_HAVE_NO_MEMORY(info);
8621
8622         *count = 1;
8623
8624         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8625         if (!W_ERROR_IS_OK(result)) {
8626                 goto out;
8627         }
8628
8629  out:
8630         if (!W_ERROR_IS_OK(result)) {
8631                 TALLOC_FREE(info);
8632                 *count = 0;
8633                 return result;
8634         }
8635
8636         *info_p = info;
8637
8638         return WERR_OK;
8639 }
8640
8641 /****************************************************************
8642  _spoolss_EnumPrintProcDataTypes
8643 ****************************************************************/
8644
8645 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8646                                        struct spoolss_EnumPrintProcDataTypes *r)
8647 {
8648         WERROR result;
8649
8650         /* that's an [in out] buffer */
8651
8652         if (!r->in.buffer && (r->in.offered != 0)) {
8653                 return WERR_INVALID_PARAM;
8654         }
8655
8656         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8657
8658         *r->out.count = 0;
8659         *r->out.needed = 0;
8660         *r->out.info = NULL;
8661
8662         switch (r->in.level) {
8663         case 1:
8664                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8665                                                         r->out.count);
8666                 break;
8667         default:
8668                 return WERR_UNKNOWN_LEVEL;
8669         }
8670
8671         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8672                                                      spoolss_EnumPrintProcDataTypes, NULL,
8673                                                      *r->out.info, r->in.level,
8674                                                      *r->out.count);
8675         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8676         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8677
8678         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8679 }
8680
8681 /****************************************************************************
8682  fill_monitor_1
8683 ****************************************************************************/
8684
8685 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8686                              struct spoolss_MonitorInfo1 *r,
8687                              const char *monitor_name)
8688 {
8689         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8690         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8691
8692         return WERR_OK;
8693 }
8694
8695 /****************************************************************************
8696  fill_monitor_2
8697 ****************************************************************************/
8698
8699 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8700                              struct spoolss_MonitorInfo2 *r,
8701                              const char *monitor_name,
8702                              const char *environment,
8703                              const char *dll_name)
8704 {
8705         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8706         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8707         r->environment                  = talloc_strdup(mem_ctx, environment);
8708         W_ERROR_HAVE_NO_MEMORY(r->environment);
8709         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8710         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8711
8712         return WERR_OK;
8713 }
8714
8715 /****************************************************************************
8716  enumprintmonitors level 1.
8717 ****************************************************************************/
8718
8719 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8720                                         union spoolss_MonitorInfo **info_p,
8721                                         uint32_t *count)
8722 {
8723         union spoolss_MonitorInfo *info;
8724         WERROR result = WERR_OK;
8725
8726         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8727         W_ERROR_HAVE_NO_MEMORY(info);
8728
8729         *count = 2;
8730
8731         result = fill_monitor_1(info, &info[0].info1,
8732                                 SPL_LOCAL_PORT);
8733         if (!W_ERROR_IS_OK(result)) {
8734                 goto out;
8735         }
8736
8737         result = fill_monitor_1(info, &info[1].info1,
8738                                 SPL_TCPIP_PORT);
8739         if (!W_ERROR_IS_OK(result)) {
8740                 goto out;
8741         }
8742
8743 out:
8744         if (!W_ERROR_IS_OK(result)) {
8745                 TALLOC_FREE(info);
8746                 *count = 0;
8747                 return result;
8748         }
8749
8750         *info_p = info;
8751
8752         return WERR_OK;
8753 }
8754
8755 /****************************************************************************
8756  enumprintmonitors level 2.
8757 ****************************************************************************/
8758
8759 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8760                                         union spoolss_MonitorInfo **info_p,
8761                                         uint32_t *count)
8762 {
8763         union spoolss_MonitorInfo *info;
8764         WERROR result = WERR_OK;
8765
8766         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8767         W_ERROR_HAVE_NO_MEMORY(info);
8768
8769         *count = 2;
8770
8771         result = fill_monitor_2(info, &info[0].info2,
8772                                 SPL_LOCAL_PORT,
8773                                 "Windows NT X86", /* FIXME */
8774                                 "localmon.dll");
8775         if (!W_ERROR_IS_OK(result)) {
8776                 goto out;
8777         }
8778
8779         result = fill_monitor_2(info, &info[1].info2,
8780                                 SPL_TCPIP_PORT,
8781                                 "Windows NT X86", /* FIXME */
8782                                 "tcpmon.dll");
8783         if (!W_ERROR_IS_OK(result)) {
8784                 goto out;
8785         }
8786
8787 out:
8788         if (!W_ERROR_IS_OK(result)) {
8789                 TALLOC_FREE(info);
8790                 *count = 0;
8791                 return result;
8792         }
8793
8794         *info_p = info;
8795
8796         return WERR_OK;
8797 }
8798
8799 /****************************************************************
8800  _spoolss_EnumMonitors
8801 ****************************************************************/
8802
8803 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8804                              struct spoolss_EnumMonitors *r)
8805 {
8806         WERROR result;
8807
8808         /* that's an [in out] buffer */
8809
8810         if (!r->in.buffer && (r->in.offered != 0)) {
8811                 return WERR_INVALID_PARAM;
8812         }
8813
8814         DEBUG(5,("_spoolss_EnumMonitors\n"));
8815
8816         /*
8817          * Enumerate the print monitors ...
8818          *
8819          * Just reply with "Local Port", to keep NT happy
8820          * and I can use my nice printer checker.
8821          */
8822
8823         *r->out.count = 0;
8824         *r->out.needed = 0;
8825         *r->out.info = NULL;
8826
8827         switch (r->in.level) {
8828         case 1:
8829                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8830                                                    r->out.count);
8831                 break;
8832         case 2:
8833                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8834                                                    r->out.count);
8835                 break;
8836         default:
8837                 return WERR_UNKNOWN_LEVEL;
8838         }
8839
8840         if (!W_ERROR_IS_OK(result)) {
8841                 return result;
8842         }
8843
8844         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8845                                                      spoolss_EnumMonitors, NULL,
8846                                                      *r->out.info, r->in.level,
8847                                                      *r->out.count);
8848         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8849         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8850
8851         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8852 }
8853
8854 /****************************************************************************
8855 ****************************************************************************/
8856
8857 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8858                              const print_queue_struct *queue,
8859                              int count, int snum,
8860                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8861                              uint32_t jobid,
8862                              struct spoolss_JobInfo1 *r)
8863 {
8864         int i = 0;
8865         bool found = false;
8866
8867         for (i=0; i<count && found == false; i++) {
8868                 if (queue[i].job == (int)jobid) {
8869                         found = true;
8870                 }
8871         }
8872
8873         if (found == false) {
8874                 /* NT treats not found as bad param... yet another bad choice */
8875                 return WERR_INVALID_PARAM;
8876         }
8877
8878         return fill_job_info1(mem_ctx,
8879                               r,
8880                               &queue[i-1],
8881                               i,
8882                               snum,
8883                               ntprinter);
8884 }
8885
8886 /****************************************************************************
8887 ****************************************************************************/
8888
8889 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8890                              const print_queue_struct *queue,
8891                              int count, int snum,
8892                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8893                              uint32_t jobid,
8894                              struct spoolss_JobInfo2 *r)
8895 {
8896         int i = 0;
8897         bool found = false;
8898         struct spoolss_DeviceMode *devmode;
8899         NT_DEVICEMODE *nt_devmode;
8900         WERROR result;
8901
8902         for (i=0; i<count && found == false; i++) {
8903                 if (queue[i].job == (int)jobid) {
8904                         found = true;
8905                 }
8906         }
8907
8908         if (found == false) {
8909                 /* NT treats not found as bad param... yet another bad
8910                    choice */
8911                 return WERR_INVALID_PARAM;
8912         }
8913
8914         /*
8915          * if the print job does not have a DEVMODE associated with it,
8916          * just use the one for the printer. A NULL devicemode is not
8917          *  a failure condition
8918          */
8919
8920         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8921         if (nt_devmode) {
8922                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8923                 W_ERROR_HAVE_NO_MEMORY(devmode);
8924                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8925                 if (!W_ERROR_IS_OK(result)) {
8926                         return result;
8927                 }
8928         } else {
8929                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8930                 W_ERROR_HAVE_NO_MEMORY(devmode);
8931         }
8932
8933         return fill_job_info2(mem_ctx,
8934                               r,
8935                               &queue[i-1],
8936                               i,
8937                               snum,
8938                               ntprinter,
8939                               devmode);
8940 }
8941
8942 /****************************************************************
8943  _spoolss_GetJob
8944 ****************************************************************/
8945
8946 WERROR _spoolss_GetJob(pipes_struct *p,
8947                        struct spoolss_GetJob *r)
8948 {
8949         WERROR result = WERR_OK;
8950         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8951         int snum;
8952         int count;
8953         print_queue_struct      *queue = NULL;
8954         print_status_struct prt_status;
8955
8956         /* that's an [in out] buffer */
8957
8958         if (!r->in.buffer && (r->in.offered != 0)) {
8959                 return WERR_INVALID_PARAM;
8960         }
8961
8962         DEBUG(5,("_spoolss_GetJob\n"));
8963
8964         *r->out.needed = 0;
8965
8966         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8967                 return WERR_BADFID;
8968         }
8969
8970         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8971         if (!W_ERROR_IS_OK(result)) {
8972                 return result;
8973         }
8974
8975         count = print_queue_status(snum, &queue, &prt_status);
8976
8977         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8978                      count, prt_status.status, prt_status.message));
8979
8980         switch (r->in.level) {
8981         case 1:
8982                 result = getjob_level_1(p->mem_ctx,
8983                                         queue, count, snum, ntprinter,
8984                                         r->in.job_id, &r->out.info->info1);
8985                 break;
8986         case 2:
8987                 result = getjob_level_2(p->mem_ctx,
8988                                         queue, count, snum, ntprinter,
8989                                         r->in.job_id, &r->out.info->info2);
8990                 break;
8991         default:
8992                 result = WERR_UNKNOWN_LEVEL;
8993                 break;
8994         }
8995
8996         SAFE_FREE(queue);
8997         free_a_printer(&ntprinter, 2);
8998
8999         if (!W_ERROR_IS_OK(result)) {
9000                 TALLOC_FREE(r->out.info);
9001                 return result;
9002         }
9003
9004         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9005                                                r->out.info, r->in.level);
9006         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9007
9008         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9009 }
9010
9011 /****************************************************************
9012  _spoolss_GetPrinterDataEx
9013
9014  From MSDN documentation of GetPrinterDataEx: pass request
9015  to GetPrinterData if key is "PrinterDriverData".
9016 ****************************************************************/
9017
9018 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9019                                  struct spoolss_GetPrinterDataEx *r)
9020 {
9021
9022         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9023         struct regval_blob              *val = NULL;
9024         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9025         int                     snum = 0;
9026         WERROR result = WERR_OK;
9027
9028         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9029
9030         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9031                 r->in.key_name, r->in.value_name));
9032
9033         /* in case of problem, return some default values */
9034
9035         *r->out.needed  = 0;
9036         *r->out.type    = REG_NONE;
9037
9038         if (!Printer) {
9039                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9040                         OUR_HANDLE(r->in.handle)));
9041                 result = WERR_BADFID;
9042                 goto done;
9043         }
9044
9045         /* Is the handle to a printer or to the server? */
9046
9047         if (Printer->printer_type == SPLHND_SERVER) {
9048                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9049                         "Not implemented for server handles yet\n"));
9050                 result = WERR_INVALID_PARAM;
9051                 goto done;
9052         }
9053
9054         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9055                 return WERR_BADFID;
9056         }
9057
9058         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9059         if (!W_ERROR_IS_OK(result)) {
9060                 goto done;
9061         }
9062
9063         /* check to see if the keyname is valid */
9064         if (!strlen(r->in.key_name)) {
9065                 result = WERR_INVALID_PARAM;
9066                 goto done;
9067         }
9068
9069         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9070                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9071                         "Invalid keyname [%s]\n", r->in.key_name ));
9072                 result = WERR_BADFILE;
9073                 goto done;
9074         }
9075
9076         /* When given a new keyname, we should just create it */
9077
9078         val = get_printer_data(printer->info_2,
9079                                r->in.key_name, r->in.value_name);
9080         if (!val) {
9081                 result = WERR_BADFILE;
9082                 goto done;
9083         }
9084
9085         *r->out.needed = regval_size(val);
9086
9087         if (*r->out.needed > r->in.offered) {
9088                 result = WERR_MORE_DATA;
9089                 goto done;
9090         }
9091
9092         *r->out.type = regval_type(val);
9093
9094         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9095
9096  done:
9097         if (printer) {
9098                 free_a_printer(&printer, 2);
9099         }
9100
9101         return result;
9102 }
9103
9104 /****************************************************************
9105  _spoolss_SetPrinterDataEx
9106 ****************************************************************/
9107
9108 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9109                                  struct spoolss_SetPrinterDataEx *r)
9110 {
9111         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9112         int                     snum = 0;
9113         WERROR                  result = WERR_OK;
9114         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9115         char                    *oid_string;
9116
9117         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9118
9119         /* From MSDN documentation of SetPrinterDataEx: pass request to
9120            SetPrinterData if key is "PrinterDriverData" */
9121
9122         if (!Printer) {
9123                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9124                         OUR_HANDLE(r->in.handle)));
9125                 return WERR_BADFID;
9126         }
9127
9128         if (Printer->printer_type == SPLHND_SERVER) {
9129                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9130                         "Not implemented for server handles yet\n"));
9131                 return WERR_INVALID_PARAM;
9132         }
9133
9134         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9135                 return WERR_BADFID;
9136         }
9137
9138         /*
9139          * Access check : NT returns "access denied" if you make a
9140          * SetPrinterData call without the necessary privildge.
9141          * we were originally returning OK if nothing changed
9142          * which made Win2k issue **a lot** of SetPrinterData
9143          * when connecting to a printer  --jerry
9144          */
9145
9146         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9147                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9148                         "change denied by handle access permissions\n"));
9149                 return WERR_ACCESS_DENIED;
9150         }
9151
9152         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9153         if (!W_ERROR_IS_OK(result)) {
9154                 return result;
9155         }
9156
9157         /* check for OID in valuename */
9158
9159         oid_string = strchr(r->in.value_name, ',');
9160         if (oid_string) {
9161                 *oid_string = '\0';
9162                 oid_string++;
9163         }
9164
9165         /* save the registry data */
9166
9167         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9168                                     r->in.type, r->in.buffer, r->in.offered);
9169
9170         if (W_ERROR_IS_OK(result)) {
9171                 /* save the OID if one was specified */
9172                 if (oid_string) {
9173                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9174                                 r->in.key_name, SPOOL_OID_KEY);
9175                         if (!str) {
9176                                 result = WERR_NOMEM;
9177                                 goto done;
9178                         }
9179
9180                         /*
9181                          * I'm not checking the status here on purpose.  Don't know
9182                          * if this is right, but I'm returning the status from the
9183                          * previous set_printer_dataex() call.  I have no idea if
9184                          * this is right.    --jerry
9185                          */
9186
9187                         set_printer_dataex(printer, str, r->in.value_name,
9188                                            REG_SZ, (uint8_t *)oid_string,
9189                                            strlen(oid_string)+1);
9190                 }
9191
9192                 result = mod_a_printer(printer, 2);
9193         }
9194
9195  done:
9196         free_a_printer(&printer, 2);
9197
9198         return result;
9199 }
9200
9201 /****************************************************************
9202  _spoolss_DeletePrinterDataEx
9203 ****************************************************************/
9204
9205 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9206                                     struct spoolss_DeletePrinterDataEx *r)
9207 {
9208         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9209         int             snum=0;
9210         WERROR          status = WERR_OK;
9211         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9212
9213         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9214
9215         if (!Printer) {
9216                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9217                         "Invalid handle (%s:%u:%u).\n",
9218                         OUR_HANDLE(r->in.handle)));
9219                 return WERR_BADFID;
9220         }
9221
9222         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9223                 return WERR_BADFID;
9224
9225         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9226                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9227                         "printer properties change denied by handle\n"));
9228                 return WERR_ACCESS_DENIED;
9229         }
9230
9231         if (!r->in.value_name || !r->in.key_name) {
9232                 return WERR_NOMEM;
9233         }
9234
9235         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9236         if (!W_ERROR_IS_OK(status))
9237                 return status;
9238
9239         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9240
9241         if ( W_ERROR_IS_OK(status) )
9242                 mod_a_printer( printer, 2 );
9243
9244         free_a_printer(&printer, 2);
9245
9246         return status;
9247 }
9248
9249 /****************************************************************
9250  _spoolss_EnumPrinterKey
9251 ****************************************************************/
9252
9253 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9254                                struct spoolss_EnumPrinterKey *r)
9255 {
9256         fstring         *keynames = NULL;
9257         int             num_keys;
9258         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9259         NT_PRINTER_DATA *data;
9260         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9261         int             snum = 0;
9262         WERROR          result = WERR_BADFILE;
9263         int i;
9264         const char **array = NULL;
9265
9266
9267         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9268
9269         if (!Printer) {
9270                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9271                         OUR_HANDLE(r->in.handle)));
9272                 return WERR_BADFID;
9273         }
9274
9275         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9276                 return WERR_BADFID;
9277         }
9278
9279         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9280         if (!W_ERROR_IS_OK(result)) {
9281                 return result;
9282         }
9283
9284         /* get the list of subkey names */
9285
9286         data = printer->info_2->data;
9287
9288         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9289         if (num_keys == -1) {
9290                 result = WERR_BADFILE;
9291                 goto done;
9292         }
9293
9294         *r->out.needed = 4;
9295
9296         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9297         if (!array) {
9298                 result = WERR_NOMEM;
9299                 goto done;
9300         }
9301
9302         for (i=0; i < num_keys; i++) {
9303                 array[i] = talloc_strdup(array, keynames[i]);
9304                 if (!array[i]) {
9305                         result = WERR_NOMEM;
9306                         goto done;
9307                 }
9308
9309                 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9310         }
9311
9312         if (r->in.offered < *r->out.needed) {
9313                 result = WERR_MORE_DATA;
9314                 goto done;
9315         }
9316
9317         result = WERR_OK;
9318
9319         *r->out.key_buffer = array;
9320
9321  done:
9322         if (!W_ERROR_IS_OK(result)) {
9323                 TALLOC_FREE(array);
9324                 ZERO_STRUCTP(r->out.key_buffer);
9325         }
9326
9327         free_a_printer(&printer, 2);
9328         SAFE_FREE(keynames);
9329
9330         return result;
9331 }
9332
9333 /****************************************************************
9334  _spoolss_DeletePrinterKey
9335 ****************************************************************/
9336
9337 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9338                                  struct spoolss_DeletePrinterKey *r)
9339 {
9340         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9341         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9342         int                     snum=0;
9343         WERROR                  status;
9344
9345         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9346
9347         if (!Printer) {
9348                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9349                         OUR_HANDLE(r->in.handle)));
9350                 return WERR_BADFID;
9351         }
9352
9353         /* if keyname == NULL, return error */
9354
9355         if ( !r->in.key_name )
9356                 return WERR_INVALID_PARAM;
9357
9358         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9359                 return WERR_BADFID;
9360
9361         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9362                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9363                         "printer properties change denied by handle\n"));
9364                 return WERR_ACCESS_DENIED;
9365         }
9366
9367         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9368         if (!W_ERROR_IS_OK(status))
9369                 return status;
9370
9371         /* delete the key and all subneys */
9372
9373         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9374
9375         if ( W_ERROR_IS_OK(status) )
9376                 status = mod_a_printer(printer, 2);
9377
9378         free_a_printer( &printer, 2 );
9379
9380         return status;
9381 }
9382
9383 /****************************************************************
9384 ****************************************************************/
9385
9386 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9387                                                    struct regval_blob *v,
9388                                                    struct spoolss_PrinterEnumValues *r)
9389 {
9390         WERROR result;
9391
9392         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9393         W_ERROR_HAVE_NO_MEMORY(r->data);
9394
9395         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9396         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9397
9398         r->type         = regval_type(v);
9399         r->data_length  = regval_size(v);
9400
9401         if (r->data_length) {
9402                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9403                                                  regval_size(v));
9404                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9405                                                   r->data,
9406                                                   r->type);
9407                 if (!W_ERROR_IS_OK(result)) {
9408                         return result;
9409                 }
9410         }
9411
9412         return WERR_OK;
9413 }
9414
9415 /****************************************************************
9416  _spoolss_EnumPrinterDataEx
9417 ****************************************************************/
9418
9419 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9420                                   struct spoolss_EnumPrinterDataEx *r)
9421 {
9422         uint32_t        count = 0;
9423         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9424         struct spoolss_PrinterEnumValues *info = NULL;
9425         NT_PRINTER_DATA         *p_data;
9426         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9427         int             snum;
9428         WERROR          result;
9429         int             key_index;
9430         int             i;
9431
9432         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9433
9434         *r->out.count = 0;
9435         *r->out.needed = 0;
9436         *r->out.info = NULL;
9437
9438         if (!Printer) {
9439                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9440                         OUR_HANDLE(r->in.handle)));
9441                 return WERR_BADFID;
9442         }
9443
9444         /*
9445          * first check for a keyname of NULL or "".  Win2k seems to send
9446          * this a lot and we should send back WERR_INVALID_PARAM
9447          * no need to spend time looking up the printer in this case.
9448          * --jerry
9449          */
9450
9451         if (!strlen(r->in.key_name)) {
9452                 result = WERR_INVALID_PARAM;
9453                 goto done;
9454         }
9455
9456         /* get the printer off of disk */
9457
9458         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9459                 return WERR_BADFID;
9460         }
9461
9462         ZERO_STRUCT(printer);
9463         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9464         if (!W_ERROR_IS_OK(result)) {
9465                 return result;
9466         }
9467
9468         /* now look for a match on the key name */
9469
9470         p_data = printer->info_2->data;
9471
9472         key_index = lookup_printerkey(p_data, r->in.key_name);
9473         if (key_index == -1) {
9474                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9475                         r->in.key_name));
9476                 result = WERR_INVALID_PARAM;
9477                 goto done;
9478         }
9479
9480         /* allocate the memory for the array of pointers -- if necessary */
9481
9482         count = regval_ctr_numvals(p_data->keys[key_index].values);
9483         if (!count) {
9484                 result = WERR_OK; /* ??? */
9485                 goto done;
9486         }
9487
9488         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9489                                  struct spoolss_PrinterEnumValues,
9490                                  count);
9491         if (!info) {
9492                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9493                 result = WERR_NOMEM;
9494                 goto done;
9495         }
9496
9497         /*
9498          * loop through all params and build the array to pass
9499          * back to the  client
9500          */
9501
9502         for (i=0; i < count; i++) {
9503
9504                 struct regval_blob      *val;
9505
9506                 /* lookup the registry value */
9507
9508                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9509
9510                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9511
9512                 /* copy the data */
9513
9514                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9515                 if (!W_ERROR_IS_OK(result)) {
9516                         goto done;
9517                 }
9518         }
9519
9520 #if 0 /* FIXME - gd */
9521         /* housekeeping information in the reply */
9522
9523         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9524          * the hand marshalled container size is a multiple
9525          * of 4 bytes for RPC alignment.
9526          */
9527
9528         if (needed % 4) {
9529                 needed += 4-(needed % 4);
9530         }
9531 #endif
9532         *r->out.count   = count;
9533         *r->out.info    = info;
9534
9535  done:
9536
9537         if (printer) {
9538                 free_a_printer(&printer, 2);
9539         }
9540
9541         if (!W_ERROR_IS_OK(result)) {
9542                 return result;
9543         }
9544
9545         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9546                                                spoolss_EnumPrinterDataEx, NULL,
9547                                                *r->out.info,
9548                                                *r->out.count);
9549         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9550         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9551
9552         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9553 }
9554
9555 /****************************************************************************
9556 ****************************************************************************/
9557
9558 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9559                                                  const char *servername,
9560                                                  const char *environment,
9561                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9562 {
9563         WERROR werr;
9564         char *path = NULL;
9565
9566         werr = compose_spoolss_server_path(mem_ctx,
9567                                            servername,
9568                                            environment,
9569                                            SPOOLSS_PRTPROCS_PATH,
9570                                            &path);
9571         if (!W_ERROR_IS_OK(werr)) {
9572                 return werr;
9573         }
9574
9575         DEBUG(4,("print processor directory: [%s]\n", path));
9576
9577         r->directory_name = path;
9578
9579         return WERR_OK;
9580 }
9581
9582 /****************************************************************
9583  _spoolss_GetPrintProcessorDirectory
9584 ****************************************************************/
9585
9586 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9587                                            struct spoolss_GetPrintProcessorDirectory *r)
9588 {
9589         WERROR result;
9590
9591         /* that's an [in out] buffer */
9592
9593         if (!r->in.buffer && (r->in.offered != 0)) {
9594                 return WERR_INVALID_PARAM;
9595         }
9596
9597         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9598                 r->in.level));
9599
9600         *r->out.needed = 0;
9601
9602         /* r->in.level is ignored */
9603
9604         result = getprintprocessordirectory_level_1(p->mem_ctx,
9605                                                     r->in.server,
9606                                                     r->in.environment,
9607                                                     &r->out.info->info1);
9608         if (!W_ERROR_IS_OK(result)) {
9609                 TALLOC_FREE(r->out.info);
9610                 return result;
9611         }
9612
9613         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9614                                                r->out.info, r->in.level);
9615         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9616
9617         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9618 }
9619
9620 /*******************************************************************
9621  ********************************************************************/
9622
9623 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9624                                const char *dllname)
9625 {
9626         enum ndr_err_code ndr_err;
9627         struct spoolss_MonitorUi ui;
9628
9629         ui.dll_name = dllname;
9630
9631         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9632                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9633         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9634                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9635         }
9636         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9637 }
9638
9639 /*******************************************************************
9640  Streams the monitor UI DLL name in UNICODE
9641 *******************************************************************/
9642
9643 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9644                                NT_USER_TOKEN *token, DATA_BLOB *in,
9645                                DATA_BLOB *out, uint32_t *needed)
9646 {
9647         const char *dllname = "tcpmonui.dll";
9648
9649         *needed = (strlen(dllname)+1) * 2;
9650
9651         if (out->length < *needed) {
9652                 return WERR_INSUFFICIENT_BUFFER;
9653         }
9654
9655         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9656                 return WERR_NOMEM;
9657         }
9658
9659         return WERR_OK;
9660 }
9661
9662 /*******************************************************************
9663  ********************************************************************/
9664
9665 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9666                              struct spoolss_PortData1 *port1,
9667                              const DATA_BLOB *buf)
9668 {
9669         enum ndr_err_code ndr_err;
9670         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9671                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9672         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9673                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9674         }
9675         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9676 }
9677
9678 /*******************************************************************
9679  ********************************************************************/
9680
9681 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9682                              struct spoolss_PortData2 *port2,
9683                              const DATA_BLOB *buf)
9684 {
9685         enum ndr_err_code ndr_err;
9686         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9687                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9688         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9689                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9690         }
9691         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9692 }
9693
9694 /*******************************************************************
9695  Create a new TCP/IP port
9696 *******************************************************************/
9697
9698 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9699                              NT_USER_TOKEN *token, DATA_BLOB *in,
9700                              DATA_BLOB *out, uint32_t *needed)
9701 {
9702         struct spoolss_PortData1 port1;
9703         struct spoolss_PortData2 port2;
9704         char *device_uri = NULL;
9705         uint32_t version;
9706
9707         const char *portname;
9708         const char *hostaddress;
9709         const char *queue;
9710         uint32_t port_number;
9711         uint32_t protocol;
9712
9713         /* peek for spoolss_PortData version */
9714
9715         if (!in || (in->length < (128 + 4))) {
9716                 return WERR_GENERAL_FAILURE;
9717         }
9718
9719         version = IVAL(in->data, 128);
9720
9721         switch (version) {
9722                 case 1:
9723                         ZERO_STRUCT(port1);
9724
9725                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9726                                 return WERR_NOMEM;
9727                         }
9728
9729                         portname        = port1.portname;
9730                         hostaddress     = port1.hostaddress;
9731                         queue           = port1.queue;
9732                         protocol        = port1.protocol;
9733                         port_number     = port1.port_number;
9734
9735                         break;
9736                 case 2:
9737                         ZERO_STRUCT(port2);
9738
9739                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9740                                 return WERR_NOMEM;
9741                         }
9742
9743                         portname        = port2.portname;
9744                         hostaddress     = port2.hostaddress;
9745                         queue           = port2.queue;
9746                         protocol        = port2.protocol;
9747                         port_number     = port2.port_number;
9748
9749                         break;
9750                 default:
9751                         DEBUG(1,("xcvtcp_addport: "
9752                                 "unknown version of port_data: %d\n", version));
9753                         return WERR_UNKNOWN_PORT;
9754         }
9755
9756         /* create the device URI and call the add_port_hook() */
9757
9758         switch (protocol) {
9759         case PROTOCOL_RAWTCP_TYPE:
9760                 device_uri = talloc_asprintf(mem_ctx,
9761                                 "socket://%s:%d/", hostaddress,
9762                                 port_number);
9763                 break;
9764
9765         case PROTOCOL_LPR_TYPE:
9766                 device_uri = talloc_asprintf(mem_ctx,
9767                         "lpr://%s/%s", hostaddress, queue );
9768                 break;
9769
9770         default:
9771                 return WERR_UNKNOWN_PORT;
9772         }
9773
9774         if (!device_uri) {
9775                 return WERR_NOMEM;
9776         }
9777
9778         return add_port_hook(mem_ctx, token, portname, device_uri);
9779 }
9780
9781 /*******************************************************************
9782 *******************************************************************/
9783
9784 struct xcv_api_table xcvtcp_cmds[] = {
9785         { "MonitorUI",  xcvtcp_monitorui },
9786         { "AddPort",    xcvtcp_addport},
9787         { NULL,         NULL }
9788 };
9789
9790 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9791                                      NT_USER_TOKEN *token, const char *command,
9792                                      DATA_BLOB *inbuf,
9793                                      DATA_BLOB *outbuf,
9794                                      uint32_t *needed )
9795 {
9796         int i;
9797
9798         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9799
9800         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9801                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9802                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9803         }
9804
9805         return WERR_BADFUNC;
9806 }
9807
9808 /*******************************************************************
9809 *******************************************************************/
9810 #if 0   /* don't support management using the "Local Port" monitor */
9811
9812 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9813                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9814                                  DATA_BLOB *out, uint32_t *needed)
9815 {
9816         const char *dllname = "localui.dll";
9817
9818         *needed = (strlen(dllname)+1) * 2;
9819
9820         if (out->length < *needed) {
9821                 return WERR_INSUFFICIENT_BUFFER;
9822         }
9823
9824         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9825                 return WERR_NOMEM;
9826         }
9827
9828         return WERR_OK;
9829 }
9830
9831 /*******************************************************************
9832 *******************************************************************/
9833
9834 struct xcv_api_table xcvlocal_cmds[] = {
9835         { "MonitorUI",  xcvlocal_monitorui },
9836         { NULL,         NULL }
9837 };
9838 #else
9839 struct xcv_api_table xcvlocal_cmds[] = {
9840         { NULL,         NULL }
9841 };
9842 #endif
9843
9844
9845
9846 /*******************************************************************
9847 *******************************************************************/
9848
9849 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9850                                        NT_USER_TOKEN *token, const char *command,
9851                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9852                                        uint32_t *needed)
9853 {
9854         int i;
9855
9856         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9857
9858         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9859                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9860                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9861         }
9862         return WERR_BADFUNC;
9863 }
9864
9865 /****************************************************************
9866  _spoolss_XcvData
9867 ****************************************************************/
9868
9869 WERROR _spoolss_XcvData(pipes_struct *p,
9870                         struct spoolss_XcvData *r)
9871 {
9872         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9873         DATA_BLOB out_data = data_blob_null;
9874         WERROR werror;
9875
9876         if (!Printer) {
9877                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9878                         OUR_HANDLE(r->in.handle)));
9879                 return WERR_BADFID;
9880         }
9881
9882         /* Has to be a handle to the TCP/IP port monitor */
9883
9884         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9885                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9886                 return WERR_BADFID;
9887         }
9888
9889         /* requires administrative access to the server */
9890
9891         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9892                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9893                 return WERR_ACCESS_DENIED;
9894         }
9895
9896         /* Allocate the outgoing buffer */
9897
9898         if (r->in.out_data_size) {
9899                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9900                 if (out_data.data == NULL) {
9901                         return WERR_NOMEM;
9902                 }
9903         }
9904
9905         switch ( Printer->printer_type ) {
9906         case SPLHND_PORTMON_TCP:
9907                 werror = process_xcvtcp_command(p->mem_ctx,
9908                                                 p->server_info->ptok,
9909                                                 r->in.function_name,
9910                                                 &r->in.in_data, &out_data,
9911                                                 r->out.needed);
9912                 break;
9913         case SPLHND_PORTMON_LOCAL:
9914                 werror = process_xcvlocal_command(p->mem_ctx,
9915                                                   p->server_info->ptok,
9916                                                   r->in.function_name,
9917                                                   &r->in.in_data, &out_data,
9918                                                   r->out.needed);
9919                 break;
9920         default:
9921                 werror = WERR_INVALID_PRINT_MONITOR;
9922         }
9923
9924         if (!W_ERROR_IS_OK(werror)) {
9925                 return werror;
9926         }
9927
9928         *r->out.status_code = 0;
9929
9930         memcpy(r->out.out_data, out_data.data, out_data.length);
9931
9932         return WERR_OK;
9933 }
9934
9935 /****************************************************************
9936  _spoolss_AddPrintProcessor
9937 ****************************************************************/
9938
9939 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9940                                   struct spoolss_AddPrintProcessor *r)
9941 {
9942         /* for now, just indicate success and ignore the add.  We'll
9943            automatically set the winprint processor for printer
9944            entries later.  Used to debug the LexMark Optra S 1855 PCL
9945            driver --jerry */
9946
9947         return WERR_OK;
9948 }
9949
9950 /****************************************************************
9951  _spoolss_AddPort
9952 ****************************************************************/
9953
9954 WERROR _spoolss_AddPort(pipes_struct *p,
9955                         struct spoolss_AddPort *r)
9956 {
9957         /* do what w2k3 does */
9958
9959         return WERR_NOT_SUPPORTED;
9960 }
9961
9962 /****************************************************************
9963  _spoolss_AddPrinter
9964 ****************************************************************/
9965
9966 WERROR _spoolss_AddPrinter(pipes_struct *p,
9967                            struct spoolss_AddPrinter *r)
9968 {
9969         p->rng_fault_state = true;
9970         return WERR_NOT_SUPPORTED;
9971 }
9972
9973 /****************************************************************
9974  _spoolss_GetPrinterDriver
9975 ****************************************************************/
9976
9977 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9978                                  struct spoolss_GetPrinterDriver *r)
9979 {
9980         p->rng_fault_state = true;
9981         return WERR_NOT_SUPPORTED;
9982 }
9983
9984 /****************************************************************
9985  _spoolss_ReadPrinter
9986 ****************************************************************/
9987
9988 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9989                             struct spoolss_ReadPrinter *r)
9990 {
9991         p->rng_fault_state = true;
9992         return WERR_NOT_SUPPORTED;
9993 }
9994
9995 /****************************************************************
9996  _spoolss_WaitForPrinterChange
9997 ****************************************************************/
9998
9999 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10000                                      struct spoolss_WaitForPrinterChange *r)
10001 {
10002         p->rng_fault_state = true;
10003         return WERR_NOT_SUPPORTED;
10004 }
10005
10006 /****************************************************************
10007  _spoolss_ConfigurePort
10008 ****************************************************************/
10009
10010 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10011                               struct spoolss_ConfigurePort *r)
10012 {
10013         p->rng_fault_state = true;
10014         return WERR_NOT_SUPPORTED;
10015 }
10016
10017 /****************************************************************
10018  _spoolss_DeletePort
10019 ****************************************************************/
10020
10021 WERROR _spoolss_DeletePort(pipes_struct *p,
10022                            struct spoolss_DeletePort *r)
10023 {
10024         p->rng_fault_state = true;
10025         return WERR_NOT_SUPPORTED;
10026 }
10027
10028 /****************************************************************
10029  _spoolss_CreatePrinterIC
10030 ****************************************************************/
10031
10032 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10033                                 struct spoolss_CreatePrinterIC *r)
10034 {
10035         p->rng_fault_state = true;
10036         return WERR_NOT_SUPPORTED;
10037 }
10038
10039 /****************************************************************
10040  _spoolss_PlayGDIScriptOnPrinterIC
10041 ****************************************************************/
10042
10043 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10044                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10045 {
10046         p->rng_fault_state = true;
10047         return WERR_NOT_SUPPORTED;
10048 }
10049
10050 /****************************************************************
10051  _spoolss_DeletePrinterIC
10052 ****************************************************************/
10053
10054 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10055                                 struct spoolss_DeletePrinterIC *r)
10056 {
10057         p->rng_fault_state = true;
10058         return WERR_NOT_SUPPORTED;
10059 }
10060
10061 /****************************************************************
10062  _spoolss_AddPrinterConnection
10063 ****************************************************************/
10064
10065 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10066                                      struct spoolss_AddPrinterConnection *r)
10067 {
10068         p->rng_fault_state = true;
10069         return WERR_NOT_SUPPORTED;
10070 }
10071
10072 /****************************************************************
10073  _spoolss_DeletePrinterConnection
10074 ****************************************************************/
10075
10076 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10077                                         struct spoolss_DeletePrinterConnection *r)
10078 {
10079         p->rng_fault_state = true;
10080         return WERR_NOT_SUPPORTED;
10081 }
10082
10083 /****************************************************************
10084  _spoolss_PrinterMessageBox
10085 ****************************************************************/
10086
10087 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10088                                   struct spoolss_PrinterMessageBox *r)
10089 {
10090         p->rng_fault_state = true;
10091         return WERR_NOT_SUPPORTED;
10092 }
10093
10094 /****************************************************************
10095  _spoolss_AddMonitor
10096 ****************************************************************/
10097
10098 WERROR _spoolss_AddMonitor(pipes_struct *p,
10099                            struct spoolss_AddMonitor *r)
10100 {
10101         p->rng_fault_state = true;
10102         return WERR_NOT_SUPPORTED;
10103 }
10104
10105 /****************************************************************
10106  _spoolss_DeleteMonitor
10107 ****************************************************************/
10108
10109 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10110                               struct spoolss_DeleteMonitor *r)
10111 {
10112         p->rng_fault_state = true;
10113         return WERR_NOT_SUPPORTED;
10114 }
10115
10116 /****************************************************************
10117  _spoolss_DeletePrintProcessor
10118 ****************************************************************/
10119
10120 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10121                                      struct spoolss_DeletePrintProcessor *r)
10122 {
10123         p->rng_fault_state = true;
10124         return WERR_NOT_SUPPORTED;
10125 }
10126
10127 /****************************************************************
10128  _spoolss_AddPrintProvidor
10129 ****************************************************************/
10130
10131 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10132                                  struct spoolss_AddPrintProvidor *r)
10133 {
10134         p->rng_fault_state = true;
10135         return WERR_NOT_SUPPORTED;
10136 }
10137
10138 /****************************************************************
10139  _spoolss_DeletePrintProvidor
10140 ****************************************************************/
10141
10142 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10143                                     struct spoolss_DeletePrintProvidor *r)
10144 {
10145         p->rng_fault_state = true;
10146         return WERR_NOT_SUPPORTED;
10147 }
10148
10149 /****************************************************************
10150  _spoolss_FindFirstPrinterChangeNotification
10151 ****************************************************************/
10152
10153 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10154                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10155 {
10156         p->rng_fault_state = true;
10157         return WERR_NOT_SUPPORTED;
10158 }
10159
10160 /****************************************************************
10161  _spoolss_FindNextPrinterChangeNotification
10162 ****************************************************************/
10163
10164 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10165                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10166 {
10167         p->rng_fault_state = true;
10168         return WERR_NOT_SUPPORTED;
10169 }
10170
10171 /****************************************************************
10172  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10173 ****************************************************************/
10174
10175 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10176                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10177 {
10178         p->rng_fault_state = true;
10179         return WERR_NOT_SUPPORTED;
10180 }
10181
10182 /****************************************************************
10183  _spoolss_ReplyOpenPrinter
10184 ****************************************************************/
10185
10186 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10187                                  struct spoolss_ReplyOpenPrinter *r)
10188 {
10189         p->rng_fault_state = true;
10190         return WERR_NOT_SUPPORTED;
10191 }
10192
10193 /****************************************************************
10194  _spoolss_RouterReplyPrinter
10195 ****************************************************************/
10196
10197 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10198                                    struct spoolss_RouterReplyPrinter *r)
10199 {
10200         p->rng_fault_state = true;
10201         return WERR_NOT_SUPPORTED;
10202 }
10203
10204 /****************************************************************
10205  _spoolss_ReplyClosePrinter
10206 ****************************************************************/
10207
10208 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10209                                   struct spoolss_ReplyClosePrinter *r)
10210 {
10211         p->rng_fault_state = true;
10212         return WERR_NOT_SUPPORTED;
10213 }
10214
10215 /****************************************************************
10216  _spoolss_AddPortEx
10217 ****************************************************************/
10218
10219 WERROR _spoolss_AddPortEx(pipes_struct *p,
10220                           struct spoolss_AddPortEx *r)
10221 {
10222         p->rng_fault_state = true;
10223         return WERR_NOT_SUPPORTED;
10224 }
10225
10226 /****************************************************************
10227  _spoolss_RouterFindFirstPrinterChangeNotification
10228 ****************************************************************/
10229
10230 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10231                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10232 {
10233         p->rng_fault_state = true;
10234         return WERR_NOT_SUPPORTED;
10235 }
10236
10237 /****************************************************************
10238  _spoolss_SpoolerInit
10239 ****************************************************************/
10240
10241 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10242                             struct spoolss_SpoolerInit *r)
10243 {
10244         p->rng_fault_state = true;
10245         return WERR_NOT_SUPPORTED;
10246 }
10247
10248 /****************************************************************
10249  _spoolss_ResetPrinterEx
10250 ****************************************************************/
10251
10252 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10253                                struct spoolss_ResetPrinterEx *r)
10254 {
10255         p->rng_fault_state = true;
10256         return WERR_NOT_SUPPORTED;
10257 }
10258
10259 /****************************************************************
10260  _spoolss_RouterReplyPrinterEx
10261 ****************************************************************/
10262
10263 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10264                                      struct spoolss_RouterReplyPrinterEx *r)
10265 {
10266         p->rng_fault_state = true;
10267         return WERR_NOT_SUPPORTED;
10268 }
10269
10270 /****************************************************************
10271  _spoolss_44
10272 ****************************************************************/
10273
10274 WERROR _spoolss_44(pipes_struct *p,
10275                    struct spoolss_44 *r)
10276 {
10277         p->rng_fault_state = true;
10278         return WERR_NOT_SUPPORTED;
10279 }
10280
10281 /****************************************************************
10282  _spoolss_47
10283 ****************************************************************/
10284
10285 WERROR _spoolss_47(pipes_struct *p,
10286                    struct spoolss_47 *r)
10287 {
10288         p->rng_fault_state = true;
10289         return WERR_NOT_SUPPORTED;
10290 }
10291
10292 /****************************************************************
10293  _spoolss_4a
10294 ****************************************************************/
10295
10296 WERROR _spoolss_4a(pipes_struct *p,
10297                    struct spoolss_4a *r)
10298 {
10299         p->rng_fault_state = true;
10300         return WERR_NOT_SUPPORTED;
10301 }
10302
10303 /****************************************************************
10304  _spoolss_4b
10305 ****************************************************************/
10306
10307 WERROR _spoolss_4b(pipes_struct *p,
10308                    struct spoolss_4b *r)
10309 {
10310         p->rng_fault_state = true;
10311         return WERR_NOT_SUPPORTED;
10312 }
10313
10314 /****************************************************************
10315  _spoolss_4c
10316 ****************************************************************/
10317
10318 WERROR _spoolss_4c(pipes_struct *p,
10319                    struct spoolss_4c *r)
10320 {
10321         p->rng_fault_state = true;
10322         return WERR_NOT_SUPPORTED;
10323 }
10324
10325 /****************************************************************
10326  _spoolss_53
10327 ****************************************************************/
10328
10329 WERROR _spoolss_53(pipes_struct *p,
10330                    struct spoolss_53 *r)
10331 {
10332         p->rng_fault_state = true;
10333         return WERR_NOT_SUPPORTED;
10334 }
10335
10336 /****************************************************************
10337  _spoolss_55
10338 ****************************************************************/
10339
10340 WERROR _spoolss_55(pipes_struct *p,
10341                    struct spoolss_55 *r)
10342 {
10343         p->rng_fault_state = true;
10344         return WERR_NOT_SUPPORTED;
10345 }
10346
10347 /****************************************************************
10348  _spoolss_56
10349 ****************************************************************/
10350
10351 WERROR _spoolss_56(pipes_struct *p,
10352                    struct spoolss_56 *r)
10353 {
10354         p->rng_fault_state = true;
10355         return WERR_NOT_SUPPORTED;
10356 }
10357
10358 /****************************************************************
10359  _spoolss_57
10360 ****************************************************************/
10361
10362 WERROR _spoolss_57(pipes_struct *p,
10363                    struct spoolss_57 *r)
10364 {
10365         p->rng_fault_state = true;
10366         return WERR_NOT_SUPPORTED;
10367 }
10368
10369 /****************************************************************
10370  _spoolss_5a
10371 ****************************************************************/
10372
10373 WERROR _spoolss_5a(pipes_struct *p,
10374                    struct spoolss_5a *r)
10375 {
10376         p->rng_fault_state = true;
10377         return WERR_NOT_SUPPORTED;
10378 }
10379
10380 /****************************************************************
10381  _spoolss_5b
10382 ****************************************************************/
10383
10384 WERROR _spoolss_5b(pipes_struct *p,
10385                    struct spoolss_5b *r)
10386 {
10387         p->rng_fault_state = true;
10388         return WERR_NOT_SUPPORTED;
10389 }
10390
10391 /****************************************************************
10392  _spoolss_5c
10393 ****************************************************************/
10394
10395 WERROR _spoolss_5c(pipes_struct *p,
10396                    struct spoolss_5c *r)
10397 {
10398         p->rng_fault_state = true;
10399         return WERR_NOT_SUPPORTED;
10400 }
10401
10402 /****************************************************************
10403  _spoolss_5d
10404 ****************************************************************/
10405
10406 WERROR _spoolss_5d(pipes_struct *p,
10407                    struct spoolss_5d *r)
10408 {
10409         p->rng_fault_state = true;
10410         return WERR_NOT_SUPPORTED;
10411 }
10412
10413 /****************************************************************
10414  _spoolss_5e
10415 ****************************************************************/
10416
10417 WERROR _spoolss_5e(pipes_struct *p,
10418                    struct spoolss_5e *r)
10419 {
10420         p->rng_fault_state = true;
10421         return WERR_NOT_SUPPORTED;
10422 }
10423
10424 /****************************************************************
10425  _spoolss_5f
10426 ****************************************************************/
10427
10428 WERROR _spoolss_5f(pipes_struct *p,
10429                    struct spoolss_5f *r)
10430 {
10431         p->rng_fault_state = true;
10432         return WERR_NOT_SUPPORTED;
10433 }
10434