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