s3: Remove procid_self() from srv_spoolss_drv_upgrade_printer()
[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 "rpc_client/init_spoolss.h"
33 #include "librpc/gen_ndr/messaging.h"
34 #include "registry.h"
35 #include "registry/reg_objects.h"
36
37 /* macros stolen from s4 spoolss server */
38 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
39         ((info)?ndr_size_##fn(info, level, 0):0)
40
41 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
42         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
43
44 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
45         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
46
47 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
48
49
50 extern userdom_struct current_user_info;
51
52 #undef DBGC_CLASS
53 #define DBGC_CLASS DBGC_RPC_SRV
54
55 #ifndef MAX_OPEN_PRINTER_EXS
56 #define MAX_OPEN_PRINTER_EXS 50
57 #endif
58
59 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
60
61 static Printer_entry *printers_list;
62
63 typedef struct _counter_printer_0 {
64         struct _counter_printer_0 *next;
65         struct _counter_printer_0 *prev;
66
67         int snum;
68         uint32_t counter;
69 } counter_printer_0;
70
71 static counter_printer_0 *counter_list;
72
73 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
74 static uint32_t smb_connections = 0;
75
76
77 /* in printing/nt_printing.c */
78
79 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
80
81 /* API table for Xcv Monitor functions */
82
83 struct xcv_api_table {
84         const char *name;
85         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
86 };
87
88 /********************************************************************
89  * Canonicalize servername.
90  ********************************************************************/
91
92 static const char *canon_servername(const char *servername)
93 {
94         const char *pservername = servername;
95         while (*pservername == '\\') {
96                 pservername++;
97         }
98         return pservername;
99 }
100
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
103 {
104         switch (v) {
105         case LPQ_QUEUED:
106                 return 0;
107         case LPQ_PAUSED:
108                 return JOB_STATUS_PAUSED;
109         case LPQ_SPOOLING:
110                 return JOB_STATUS_SPOOLING;
111         case LPQ_PRINTING:
112                 return JOB_STATUS_PRINTING;
113         case LPQ_ERROR:
114                 return JOB_STATUS_ERROR;
115         case LPQ_DELETING:
116                 return JOB_STATUS_DELETING;
117         case LPQ_OFFLINE:
118                 return JOB_STATUS_OFFLINE;
119         case LPQ_PAPEROUT:
120                 return JOB_STATUS_PAPEROUT;
121         case LPQ_PRINTED:
122                 return JOB_STATUS_PRINTED;
123         case LPQ_DELETED:
124                 return JOB_STATUS_DELETED;
125         case LPQ_BLOCKED:
126                 return JOB_STATUS_BLOCKED_DEVQ;
127         case LPQ_USER_INTERVENTION:
128                 return JOB_STATUS_USER_INTERVENTION;
129         }
130         return 0;
131 }
132
133 static int nt_printq_status(int v)
134 {
135         switch (v) {
136         case LPQ_PAUSED:
137                 return PRINTER_STATUS_PAUSED;
138         case LPQ_QUEUED:
139         case LPQ_SPOOLING:
140         case LPQ_PRINTING:
141                 return 0;
142         }
143         return 0;
144 }
145
146 /***************************************************************************
147  Disconnect from the client
148 ****************************************************************************/
149
150 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
151 {
152         WERROR result;
153         NTSTATUS status;
154
155         /*
156          * Tell the specific printing tdb we no longer want messages for this printer
157          * by deregistering our PID.
158          */
159
160         if (!print_notify_deregister_pid(snum))
161                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
162
163         /* weird if the test succeds !!! */
164         if (smb_connections==0) {
165                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166                 return;
167         }
168
169         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
170                                                   handle,
171                                                   &result);
172         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174                         win_errstr(result)));
175
176         /* if it's the last connection, deconnect the IPC$ share */
177         if (smb_connections==1) {
178
179                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181
182                 messaging_deregister(smbd_messaging_context(),
183                                      MSG_PRINTER_NOTIFY2, NULL);
184
185                 /* Tell the connections db we're no longer interested in
186                  * printer notify messages. */
187
188                 serverid_register_msg_flags(
189                         procid_self(),
190                         false, FLAG_MSG_PRINT_NOTIFY);
191         }
192
193         smb_connections--;
194 }
195
196 /****************************************************************************
197  Functions to free a printer entry datastruct.
198 ****************************************************************************/
199
200 static int printer_entry_destructor(Printer_entry *Printer)
201 {
202         if (Printer->notify.client_connected == true) {
203                 int snum = -1;
204
205                 if ( Printer->printer_type == SPLHND_SERVER) {
206                         snum = -1;
207                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
208                 } else if (Printer->printer_type == SPLHND_PRINTER) {
209                         snum = print_queue_snum(Printer->sharename);
210                         if (snum != -1)
211                                 srv_spoolss_replycloseprinter(snum,
212                                                 &Printer->notify.client_hnd);
213                 }
214         }
215
216         Printer->notify.flags=0;
217         Printer->notify.options=0;
218         Printer->notify.localmachine[0]='\0';
219         Printer->notify.printerlocal=0;
220         TALLOC_FREE(Printer->notify.option);
221         Printer->notify.client_connected = false;
222
223         free_nt_devicemode( &Printer->nt_devmode );
224         free_a_printer( &Printer->printer_info, 2 );
225
226         /* Remove from the internal list. */
227         DLIST_REMOVE(printers_list, Printer);
228         return 0;
229 }
230
231 /****************************************************************************
232   find printer index by handle
233 ****************************************************************************/
234
235 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
236                                                 struct policy_handle *hnd)
237 {
238         Printer_entry *find_printer = NULL;
239
240         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
241                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
242                 return NULL;
243         }
244
245         return find_printer;
246 }
247
248 /****************************************************************************
249  Close printer index by handle.
250 ****************************************************************************/
251
252 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
253 {
254         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
255
256         if (!Printer) {
257                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
258                         OUR_HANDLE(hnd)));
259                 return false;
260         }
261
262         close_policy_hnd(p, hnd);
263
264         return true;
265 }
266
267 /****************************************************************************
268  Delete a printer given a handle.
269 ****************************************************************************/
270
271 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
272 {
273         char *cmd = lp_deleteprinter_cmd();
274         char *command = NULL;
275         int ret;
276         SE_PRIV se_printop = SE_PRINT_OPERATOR;
277         bool is_print_op = false;
278
279         /* can't fail if we don't try */
280
281         if ( !*cmd )
282                 return WERR_OK;
283
284         command = talloc_asprintf(ctx,
285                         "%s \"%s\"",
286                         cmd, sharename);
287         if (!command) {
288                 return WERR_NOMEM;
289         }
290         if ( token )
291                 is_print_op = user_has_privileges( token, &se_printop );
292
293         DEBUG(10,("Running [%s]\n", command));
294
295         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
296
297         if ( is_print_op )
298                 become_root();
299
300         if ( (ret = smbrun(command, NULL)) == 0 ) {
301                 /* Tell everyone we updated smb.conf. */
302                 message_send_all(smbd_messaging_context(),
303                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
304         }
305
306         if ( is_print_op )
307                 unbecome_root();
308
309         /********** END SePrintOperatorPrivlege BLOCK **********/
310
311         DEBUGADD(10,("returned [%d]\n", ret));
312
313         TALLOC_FREE(command);
314
315         if (ret != 0)
316                 return WERR_BADFID; /* What to return here? */
317
318         /* go ahead and re-read the services immediately */
319         become_root();
320         reload_services(false);
321         unbecome_root();
322
323         if ( lp_servicenumber( sharename )  > 0 )
324                 return WERR_ACCESS_DENIED;
325
326         return WERR_OK;
327 }
328
329 /****************************************************************************
330  Delete a printer given a handle.
331 ****************************************************************************/
332
333 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
334 {
335         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
336
337         if (!Printer) {
338                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
339                         OUR_HANDLE(hnd)));
340                 return WERR_BADFID;
341         }
342
343         /*
344          * It turns out that Windows allows delete printer on a handle
345          * opened by an admin user, then used on a pipe handle created
346          * by an anonymous user..... but they're working on security.... riiight !
347          * JRA.
348          */
349
350         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
351                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
352                 return WERR_ACCESS_DENIED;
353         }
354
355         /* this does not need a become root since the access check has been
356            done on the handle already */
357
358         if (del_a_printer( Printer->sharename ) != 0) {
359                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
360                 return WERR_BADFID;
361         }
362
363         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
364                                    Printer->sharename );
365 }
366
367 /****************************************************************************
368  Return the snum of a printer corresponding to an handle.
369 ****************************************************************************/
370
371 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
372                              int *number, struct share_params **params)
373 {
374         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
375
376         if (!Printer) {
377                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
378                         OUR_HANDLE(hnd)));
379                 return false;
380         }
381
382         switch (Printer->printer_type) {
383                 case SPLHND_PRINTER:
384                         DEBUG(4,("short name:%s\n", Printer->sharename));
385                         *number = print_queue_snum(Printer->sharename);
386                         return (*number != -1);
387                 case SPLHND_SERVER:
388                         return false;
389                 default:
390                         return false;
391         }
392 }
393
394 /****************************************************************************
395  Set printer handle type.
396  Check if it's \\server or \\server\printer
397 ****************************************************************************/
398
399 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
400 {
401         DEBUG(3,("Setting printer type=%s\n", handlename));
402
403         if ( strlen(handlename) < 3 ) {
404                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
405                 return false;
406         }
407
408         /* it's a print server */
409         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
410                 DEBUGADD(4,("Printer is a print server\n"));
411                 Printer->printer_type = SPLHND_SERVER;
412         }
413         /* it's a printer (set_printer_hnd_name() will handle port monitors */
414         else {
415                 DEBUGADD(4,("Printer is a printer\n"));
416                 Printer->printer_type = SPLHND_PRINTER;
417         }
418
419         return true;
420 }
421
422 /****************************************************************************
423  Set printer handle name..  Accept names like \\server, \\server\printer,
424  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
425  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
426  XcvDataPort() interface.
427 ****************************************************************************/
428
429 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
430 {
431         int snum;
432         int n_services=lp_numservices();
433         char *aprinter, *printername;
434         const char *servername;
435         fstring sname;
436         bool found = false;
437         NT_PRINTER_INFO_LEVEL *printer = NULL;
438         WERROR result;
439
440         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
441                 (unsigned long)strlen(handlename)));
442
443         aprinter = CONST_DISCARD(char *, handlename);
444         if ( *handlename == '\\' ) {
445                 servername = canon_servername(handlename);
446                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
447                         *aprinter = '\0';
448                         aprinter++;
449                 }
450         } else {
451                 servername = global_myname();
452         }
453
454         /* save the servername to fill in replies on this handle */
455
456         if ( !is_myname_or_ipaddr( servername ) )
457                 return false;
458
459         fstrcpy( Printer->servername, servername );
460
461         if ( Printer->printer_type == SPLHND_SERVER )
462                 return true;
463
464         if ( Printer->printer_type != SPLHND_PRINTER )
465                 return false;
466
467         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
468
469         /* check for the Port Monitor Interface */
470
471         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_TCP;
473                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
474                 found = true;
475         }
476         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
477                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
478                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
479                 found = true;
480         }
481
482         /* Search all sharenames first as this is easier than pulling
483            the printer_info_2 off of disk. Don't use find_service() since
484            that calls out to map_username() */
485
486         /* do another loop to look for printernames */
487
488         for (snum=0; !found && snum<n_services; snum++) {
489
490                 /* no point going on if this is not a printer */
491
492                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
493                         continue;
494
495                 fstrcpy(sname, lp_servicename(snum));
496                 if ( strequal( aprinter, sname ) ) {
497                         found = true;
498                         break;
499                 }
500
501                 /* no point looking up the printer object if
502                    we aren't allowing printername != sharename */
503
504                 if ( lp_force_printername(snum) )
505                         continue;
506
507                 fstrcpy(sname, lp_servicename(snum));
508
509                 printer = NULL;
510
511                 /* This call doesn't fill in the location or comment from
512                  * a CUPS server for efficiency with large numbers of printers.
513                  * JRA.
514                  */
515
516                 result = get_a_printer_search( NULL, &printer, 2, sname );
517                 if ( !W_ERROR_IS_OK(result) ) {
518                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
519                                 sname, win_errstr(result)));
520                         continue;
521                 }
522
523                 /* printername is always returned as \\server\printername */
524                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
525                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
526                                 printer->info_2->printername));
527                         free_a_printer( &printer, 2);
528                         continue;
529                 }
530
531                 printername++;
532
533                 if ( strequal(printername, aprinter) ) {
534                         free_a_printer( &printer, 2);
535                         found = true;
536                         break;
537                 }
538
539                 DEBUGADD(10, ("printername: %s\n", printername));
540
541                 free_a_printer( &printer, 2);
542         }
543
544         free_a_printer( &printer, 2);
545
546         if ( !found ) {
547                 DEBUGADD(4,("Printer not found\n"));
548                 return false;
549         }
550
551         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
552
553         fstrcpy(Printer->sharename, sname);
554
555         return true;
556 }
557
558 /****************************************************************************
559  Find first available printer slot. creates a printer handle for you.
560  ****************************************************************************/
561
562 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
563                              const char *name, uint32_t access_granted)
564 {
565         Printer_entry *new_printer;
566
567         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
568
569         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
570         if (new_printer == NULL) {
571                 return false;
572         }
573         talloc_set_destructor(new_printer, printer_entry_destructor);
574
575         if (!create_policy_hnd(p, hnd, new_printer)) {
576                 TALLOC_FREE(new_printer);
577                 return false;
578         }
579
580         /* Add to the internal list. */
581         DLIST_ADD(printers_list, new_printer);
582
583         new_printer->notify.option=NULL;
584
585         if (!set_printer_hnd_printertype(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         if (!set_printer_hnd_name(new_printer, name)) {
591                 close_printer_handle(p, hnd);
592                 return false;
593         }
594
595         new_printer->access_granted = access_granted;
596
597         DEBUG(5, ("%d printer handles active\n",
598                   (int)num_pipe_handles(p)));
599
600         return true;
601 }
602
603 /***************************************************************************
604  check to see if the client motify handle is monitoring the notification
605  given by (notify_type, notify_field).
606  **************************************************************************/
607
608 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
609                                       uint16_t notify_field)
610 {
611         return true;
612 }
613
614 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
615                                 uint16_t notify_field)
616 {
617         struct spoolss_NotifyOption *option = p->notify.option;
618         uint32_t i, j;
619
620         /*
621          * Flags should always be zero when the change notify
622          * is registered by the client's spooler.  A user Win32 app
623          * might use the flags though instead of the NOTIFY_OPTION_INFO
624          * --jerry
625          */
626
627         if (!option) {
628                 return false;
629         }
630
631         if (p->notify.flags)
632                 return is_monitoring_event_flags(
633                         p->notify.flags, notify_type, notify_field);
634
635         for (i = 0; i < option->count; i++) {
636
637                 /* Check match for notify_type */
638
639                 if (option->types[i].type != notify_type)
640                         continue;
641
642                 /* Check match for field */
643
644                 for (j = 0; j < option->types[i].count; j++) {
645                         if (option->types[i].fields[j].field == notify_field) {
646                                 return true;
647                         }
648                 }
649         }
650
651         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
652                    p->servername, p->sharename, notify_type, notify_field));
653
654         return false;
655 }
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
658         _data->data.integer[0] = _integer; \
659         _data->data.integer[1] = 0;
660
661
662 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
663         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
664         if (!_data->data.string.string) {\
665                 _data->data.string.size = 0; \
666         } \
667         _data->data.string.size = strlen_m_term(_p) * 2;
668
669 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
670         _data->data.devmode.devmode = _devmode;
671
672 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
673         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
674         if (!_data->data.sd.sd) { \
675                 _data->data.sd.sd_size = 0; \
676         } \
677         _data->data.sd.sd_size = _size;
678
679 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
680                                    struct tm *t,
681                                    const char **pp,
682                                    uint32_t *plen)
683 {
684         struct spoolss_Time st;
685         uint32_t len = 16;
686         char *p;
687
688         if (!init_systemtime(&st, t)) {
689                 return;
690         }
691
692         p = talloc_array(mem_ctx, char, len);
693         if (!p) {
694                 return;
695         }
696
697         /*
698          * Systemtime must be linearized as a set of UINT16's.
699          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
700          */
701
702         SSVAL(p, 0, st.year);
703         SSVAL(p, 2, st.month);
704         SSVAL(p, 4, st.day_of_week);
705         SSVAL(p, 6, st.day);
706         SSVAL(p, 8, st.hour);
707         SSVAL(p, 10, st.minute);
708         SSVAL(p, 12, st.second);
709         SSVAL(p, 14, st.millisecond);
710
711         *pp = p;
712         *plen = len;
713 }
714
715 /* Convert a notification message to a struct spoolss_Notify */
716
717 static void notify_one_value(struct spoolss_notify_msg *msg,
718                              struct spoolss_Notify *data,
719                              TALLOC_CTX *mem_ctx)
720 {
721         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
722 }
723
724 static void notify_string(struct spoolss_notify_msg *msg,
725                           struct spoolss_Notify *data,
726                           TALLOC_CTX *mem_ctx)
727 {
728         /* The length of the message includes the trailing \0 */
729
730         data->data.string.size = msg->len * 2;
731         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
732         if (!data->data.string.string) {
733                 data->data.string.size = 0;
734                 return;
735         }
736 }
737
738 static void notify_system_time(struct spoolss_notify_msg *msg,
739                                struct spoolss_Notify *data,
740                                TALLOC_CTX *mem_ctx)
741 {
742         data->data.string.string = NULL;
743         data->data.string.size = 0;
744
745         if (msg->len != sizeof(time_t)) {
746                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747                           msg->len));
748                 return;
749         }
750
751         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
752                                &data->data.string.string,
753                                &data->data.string.size);
754 }
755
756 struct notify2_message_table {
757         const char *name;
758         void (*fn)(struct spoolss_notify_msg *msg,
759                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
760 };
761
762 static struct notify2_message_table printer_notify_table[] = {
763         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
764         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
765         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
766         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
767         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
768         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
769         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
770         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
771         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
772         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
773         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
774         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
775         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
776         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
777         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
778         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
779         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
780         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
781         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
782 };
783
784 static struct notify2_message_table job_notify_table[] = {
785         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
786         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
787         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
788         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
789         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
790         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
791         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
792         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
793         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
794         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
795         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
796         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
797         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
798         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
799         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
800         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
801         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
802         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
803         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
804         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
805         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
806         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
807         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
808         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
809 };
810
811
812 /***********************************************************************
813  Allocate talloc context for container object
814  **********************************************************************/
815
816 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
817 {
818         if ( !ctr )
819                 return;
820
821         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
822
823         return;
824 }
825
826 /***********************************************************************
827  release all allocated memory and zero out structure
828  **********************************************************************/
829
830 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
831 {
832         if ( !ctr )
833                 return;
834
835         if ( ctr->ctx )
836                 talloc_destroy(ctr->ctx);
837
838         ZERO_STRUCTP(ctr);
839
840         return;
841 }
842
843 /***********************************************************************
844  **********************************************************************/
845
846 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
847 {
848         if ( !ctr )
849                 return NULL;
850
851         return ctr->ctx;
852 }
853
854 /***********************************************************************
855  **********************************************************************/
856
857 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
858 {
859         if ( !ctr || !ctr->msg_groups )
860                 return NULL;
861
862         if ( idx >= ctr->num_groups )
863                 return NULL;
864
865         return &ctr->msg_groups[idx];
866
867 }
868
869 /***********************************************************************
870  How many groups of change messages do we have ?
871  **********************************************************************/
872
873 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
874 {
875         if ( !ctr )
876                 return 0;
877
878         return ctr->num_groups;
879 }
880
881 /***********************************************************************
882  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
883  **********************************************************************/
884
885 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
886 {
887         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
888         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
889         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
890         int                             i, new_slot;
891
892         if ( !ctr || !msg )
893                 return 0;
894
895         /* loop over all groups looking for a matching printer name */
896
897         for ( i=0; i<ctr->num_groups; i++ ) {
898                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
899                         break;
900         }
901
902         /* add a new group? */
903
904         if ( i == ctr->num_groups ) {
905                 ctr->num_groups++;
906
907                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
908                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
909                         return 0;
910                 }
911                 ctr->msg_groups = groups;
912
913                 /* clear the new entry and set the printer name */
914
915                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
916                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
917         }
918
919         /* add the change messages; 'i' is the correct index now regardless */
920
921         msg_grp = &ctr->msg_groups[i];
922
923         msg_grp->num_msgs++;
924
925         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
926                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
927                 return 0;
928         }
929         msg_grp->msgs = msg_list;
930
931         new_slot = msg_grp->num_msgs-1;
932         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
933
934         /* need to allocate own copy of data */
935
936         if ( msg->len != 0 )
937                 msg_grp->msgs[new_slot].notify.data = (char *)
938                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
939
940         return ctr->num_groups;
941 }
942
943 void construct_info_data(struct spoolss_Notify *info_data,
944                          enum spoolss_NotifyType type,
945                          uint16_t field,
946                          int id);
947
948 /***********************************************************************
949  Send a change notication message on all handles which have a call
950  back registered
951  **********************************************************************/
952
953 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
954 {
955         Printer_entry            *p;
956         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
957         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
958         SPOOLSS_NOTIFY_MSG       *messages;
959         int                      sending_msg_count;
960
961         if ( !msg_group ) {
962                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
963                 return;
964         }
965
966         messages = msg_group->msgs;
967
968         if ( !messages ) {
969                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
970                 return;
971         }
972
973         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
974
975         /* loop over all printers */
976
977         for (p = printers_list; p; p = p->next) {
978                 struct spoolss_Notify *notifies;
979                 uint32_t count = 0;
980                 uint32_t id;
981                 int     i;
982
983                 /* Is there notification on this handle? */
984
985                 if ( !p->notify.client_connected )
986                         continue;
987
988                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
989
990                 /* For this printer?  Print servers always receive
991                    notifications. */
992
993                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
994                     ( !strequal(msg_group->printername, p->sharename) ) )
995                         continue;
996
997                 DEBUG(10,("Our printer\n"));
998
999                 /* allocate the max entries possible */
1000
1001                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1002                 if (!notifies) {
1003                         return;
1004                 }
1005
1006                 /* build the array of change notifications */
1007
1008                 sending_msg_count = 0;
1009
1010                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1011                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1012
1013                         /* Are we monitoring this event? */
1014
1015                         if (!is_monitoring_event(p, msg->type, msg->field))
1016                                 continue;
1017
1018                         sending_msg_count++;
1019
1020
1021                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1022                                 msg->type, msg->field, p->sharename));
1023
1024                         /*
1025                          * if the is a printer notification handle and not a job notification
1026                          * type, then set the id to 0.  Other wise just use what was specified
1027                          * in the message.
1028                          *
1029                          * When registering change notification on a print server handle
1030                          * we always need to send back the id (snum) matching the printer
1031                          * for which the change took place.  For change notify registered
1032                          * on a printer handle, this does not matter and the id should be 0.
1033                          *
1034                          * --jerry
1035                          */
1036
1037                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1038                                 id = 0;
1039                         else
1040                                 id = msg->id;
1041
1042
1043                         /* Convert unix jobid to smb jobid */
1044
1045                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1046                                 id = sysjob_to_jobid(msg->id);
1047
1048                                 if (id == -1) {
1049                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1050                                         goto done;
1051                                 }
1052                         }
1053
1054                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1055
1056                         switch(msg->type) {
1057                         case PRINTER_NOTIFY_TYPE:
1058                                 if ( printer_notify_table[msg->field].fn )
1059                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1060                                 break;
1061
1062                         case JOB_NOTIFY_TYPE:
1063                                 if ( job_notify_table[msg->field].fn )
1064                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1065                                 break;
1066
1067                         default:
1068                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1069                                 goto done;
1070                         }
1071
1072                         count++;
1073                 }
1074
1075                 if ( sending_msg_count ) {
1076                         NTSTATUS status;
1077                         WERROR werr;
1078                         union spoolss_ReplyPrinterInfo info;
1079                         struct spoolss_NotifyInfo info0;
1080                         uint32_t reply_result;
1081
1082                         info0.version   = 0x2;
1083                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1084                         info0.count     = count;
1085                         info0.notifies  = notifies;
1086
1087                         info.info0 = &info0;
1088
1089                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1090                                                                      &p->notify.client_hnd,
1091                                                                      p->notify.change, /* color */
1092                                                                      p->notify.flags,
1093                                                                      &reply_result,
1094                                                                      0, /* reply_type, must be 0 */
1095                                                                      info,
1096                                                                      &werr);
1097                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1098                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1099                                         notify_cli_pipe->srv_name_slash,
1100                                         win_errstr(werr)));
1101                         }
1102                         switch (reply_result) {
1103                                 case 0:
1104                                         break;
1105                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1106                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1107                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1108                                         break;
1109                                 default:
1110                                         break;
1111                         }
1112                 }
1113         }
1114
1115 done:
1116         DEBUG(8,("send_notify2_changes: Exit...\n"));
1117         return;
1118 }
1119
1120 /***********************************************************************
1121  **********************************************************************/
1122
1123 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1124 {
1125
1126         uint32_t tv_sec, tv_usec;
1127         size_t offset = 0;
1128
1129         /* Unpack message */
1130
1131         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1132                              msg->printer);
1133
1134         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1135                                 &tv_sec, &tv_usec,
1136                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1137
1138         if (msg->len == 0)
1139                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1140                            &msg->notify.value[0], &msg->notify.value[1]);
1141         else
1142                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1143                            &msg->len, &msg->notify.data);
1144
1145         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1146                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1147
1148         tv->tv_sec = tv_sec;
1149         tv->tv_usec = tv_usec;
1150
1151         if (msg->len == 0)
1152                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1153                           msg->notify.value[1]));
1154         else
1155                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1156
1157         return true;
1158 }
1159
1160 /********************************************************************
1161  Receive a notify2 message list
1162  ********************************************************************/
1163
1164 static void receive_notify2_message_list(struct messaging_context *msg,
1165                                          void *private_data,
1166                                          uint32_t msg_type,
1167                                          struct server_id server_id,
1168                                          DATA_BLOB *data)
1169 {
1170         size_t                  msg_count, i;
1171         char                    *buf = (char *)data->data;
1172         char                    *msg_ptr;
1173         size_t                  msg_len;
1174         SPOOLSS_NOTIFY_MSG      notify;
1175         SPOOLSS_NOTIFY_MSG_CTR  messages;
1176         int                     num_groups;
1177
1178         if (data->length < 4) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1180                 return;
1181         }
1182
1183         msg_count = IVAL(buf, 0);
1184         msg_ptr = buf + 4;
1185
1186         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1187
1188         if (msg_count == 0) {
1189                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1190                 return;
1191         }
1192
1193         /* initialize the container */
1194
1195         ZERO_STRUCT( messages );
1196         notify_msg_ctr_init( &messages );
1197
1198         /*
1199          * build message groups for each printer identified
1200          * in a change_notify msg.  Remember that a PCN message
1201          * includes the handle returned for the srv_spoolss_replyopenprinter()
1202          * call.  Therefore messages are grouped according to printer handle.
1203          */
1204
1205         for ( i=0; i<msg_count; i++ ) {
1206                 struct timeval msg_tv;
1207
1208                 if (msg_ptr + 4 - buf > data->length) {
1209                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1210                         return;
1211                 }
1212
1213                 msg_len = IVAL(msg_ptr,0);
1214                 msg_ptr += 4;
1215
1216                 if (msg_ptr + msg_len - buf > data->length) {
1217                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1218                         return;
1219                 }
1220
1221                 /* unpack messages */
1222
1223                 ZERO_STRUCT( notify );
1224                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1225                 msg_ptr += msg_len;
1226
1227                 /* add to correct list in container */
1228
1229                 notify_msg_ctr_addmsg( &messages, &notify );
1230
1231                 /* free memory that might have been allocated by notify2_unpack_msg() */
1232
1233                 if ( notify.len != 0 )
1234                         SAFE_FREE( notify.notify.data );
1235         }
1236
1237         /* process each group of messages */
1238
1239         num_groups = notify_msg_ctr_numgroups( &messages );
1240         for ( i=0; i<num_groups; i++ )
1241                 send_notify2_changes( &messages, i );
1242
1243
1244         /* cleanup */
1245
1246         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1247                 (uint32_t)msg_count ));
1248
1249         notify_msg_ctr_destroy( &messages );
1250
1251         return;
1252 }
1253
1254 /********************************************************************
1255  Send a message to ourself about new driver being installed
1256  so we can upgrade the information for each printer bound to this
1257  driver
1258  ********************************************************************/
1259
1260 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1261 {
1262         int len = strlen(drivername);
1263
1264         if (!len)
1265                 return false;
1266
1267         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1268                 drivername));
1269
1270         messaging_send_buf(smbd_messaging_context(),
1271                            messaging_server_id(smbd_messaging_context()),
1272                            MSG_PRINTER_DRVUPGRADE,
1273                            (uint8_t *)drivername, len+1);
1274
1275         return true;
1276 }
1277
1278 /**********************************************************************
1279  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1280  over all printers, upgrading ones as necessary
1281  **********************************************************************/
1282
1283 void do_drv_upgrade_printer(struct messaging_context *msg,
1284                             void *private_data,
1285                             uint32_t msg_type,
1286                             struct server_id server_id,
1287                             DATA_BLOB *data)
1288 {
1289         fstring drivername;
1290         int snum;
1291         int n_services = lp_numservices();
1292         size_t len;
1293
1294         len = MIN(data->length,sizeof(drivername)-1);
1295         strncpy(drivername, (const char *)data->data, len);
1296
1297         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1298
1299         /* Iterate the printer list */
1300
1301         for (snum=0; snum<n_services; snum++)
1302         {
1303                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1304                 {
1305                         WERROR result;
1306                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1307
1308                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1309                         if (!W_ERROR_IS_OK(result))
1310                                 continue;
1311
1312                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1313                         {
1314                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1315
1316                                 /* all we care about currently is the change_id */
1317
1318                                 result = mod_a_printer(printer, 2);
1319                                 if (!W_ERROR_IS_OK(result)) {
1320                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1321                                                 win_errstr(result)));
1322                                 }
1323                         }
1324
1325                         free_a_printer(&printer, 2);
1326                 }
1327         }
1328
1329         /* all done */
1330 }
1331
1332 /********************************************************************
1333  Update the cache for all printq's with a registered client
1334  connection
1335  ********************************************************************/
1336
1337 void update_monitored_printq_cache( void )
1338 {
1339         Printer_entry *printer = printers_list;
1340         int snum;
1341
1342         /* loop through all printers and update the cache where
1343            client_connected == true */
1344         while ( printer )
1345         {
1346                 if ( (printer->printer_type == SPLHND_PRINTER)
1347                         && printer->notify.client_connected )
1348                 {
1349                         snum = print_queue_snum(printer->sharename);
1350                         print_queue_status( snum, NULL, NULL );
1351                 }
1352
1353                 printer = printer->next;
1354         }
1355
1356         return;
1357 }
1358
1359 /****************************************************************
1360  _spoolss_OpenPrinter
1361 ****************************************************************/
1362
1363 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1364                             struct spoolss_OpenPrinter *r)
1365 {
1366         struct spoolss_OpenPrinterEx e;
1367         WERROR werr;
1368
1369         ZERO_STRUCT(e.in.userlevel);
1370
1371         e.in.printername        = r->in.printername;
1372         e.in.datatype           = r->in.datatype;
1373         e.in.devmode_ctr        = r->in.devmode_ctr;
1374         e.in.access_mask        = r->in.access_mask;
1375         e.in.level              = 0;
1376
1377         e.out.handle            = r->out.handle;
1378
1379         werr = _spoolss_OpenPrinterEx(p, &e);
1380
1381         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1382                 /* OpenPrinterEx returns this for a bad
1383                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1384                  * instead.
1385                  */
1386                 werr = WERR_INVALID_PRINTER_NAME;
1387         }
1388
1389         return werr;
1390 }
1391
1392 /********************************************************************
1393  ********************************************************************/
1394
1395 bool convert_devicemode(const char *printername,
1396                         const struct spoolss_DeviceMode *devmode,
1397                         NT_DEVICEMODE **pp_nt_devmode)
1398 {
1399         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1400
1401         /*
1402          * Ensure nt_devmode is a valid pointer
1403          * as we will be overwriting it.
1404          */
1405
1406         if (nt_devmode == NULL) {
1407                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1408                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1409                         return false;
1410         }
1411
1412         fstrcpy(nt_devmode->devicename, devmode->devicename);
1413         fstrcpy(nt_devmode->formname, devmode->formname);
1414
1415         nt_devmode->devicename[31] = '\0';
1416         nt_devmode->formname[31] = '\0';
1417
1418         nt_devmode->specversion         = devmode->specversion;
1419         nt_devmode->driverversion       = devmode->driverversion;
1420         nt_devmode->size                = devmode->size;
1421         nt_devmode->fields              = devmode->fields;
1422         nt_devmode->orientation         = devmode->orientation;
1423         nt_devmode->papersize           = devmode->papersize;
1424         nt_devmode->paperlength         = devmode->paperlength;
1425         nt_devmode->paperwidth          = devmode->paperwidth;
1426         nt_devmode->scale               = devmode->scale;
1427         nt_devmode->copies              = devmode->copies;
1428         nt_devmode->defaultsource       = devmode->defaultsource;
1429         nt_devmode->printquality        = devmode->printquality;
1430         nt_devmode->color               = devmode->color;
1431         nt_devmode->duplex              = devmode->duplex;
1432         nt_devmode->yresolution         = devmode->yresolution;
1433         nt_devmode->ttoption            = devmode->ttoption;
1434         nt_devmode->collate             = devmode->collate;
1435
1436         nt_devmode->logpixels           = devmode->logpixels;
1437         nt_devmode->bitsperpel          = devmode->bitsperpel;
1438         nt_devmode->pelswidth           = devmode->pelswidth;
1439         nt_devmode->pelsheight          = devmode->pelsheight;
1440         nt_devmode->displayflags        = devmode->displayflags;
1441         nt_devmode->displayfrequency    = devmode->displayfrequency;
1442         nt_devmode->icmmethod           = devmode->icmmethod;
1443         nt_devmode->icmintent           = devmode->icmintent;
1444         nt_devmode->mediatype           = devmode->mediatype;
1445         nt_devmode->dithertype          = devmode->dithertype;
1446         nt_devmode->reserved1           = devmode->reserved1;
1447         nt_devmode->reserved2           = devmode->reserved2;
1448         nt_devmode->panningwidth        = devmode->panningwidth;
1449         nt_devmode->panningheight       = devmode->panningheight;
1450
1451         /*
1452          * Only change private and driverextra if the incoming devmode
1453          * has a new one. JRA.
1454          */
1455
1456         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1457                 SAFE_FREE(nt_devmode->nt_dev_private);
1458                 nt_devmode->driverextra = devmode->__driverextra_length;
1459                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1460                         return false;
1461                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1462         }
1463
1464         *pp_nt_devmode = nt_devmode;
1465
1466         return true;
1467 }
1468
1469 /****************************************************************
1470  _spoolss_OpenPrinterEx
1471 ****************************************************************/
1472
1473 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1474                               struct spoolss_OpenPrinterEx *r)
1475 {
1476         int snum;
1477         Printer_entry *Printer=NULL;
1478
1479         if (!r->in.printername) {
1480                 return WERR_INVALID_PARAM;
1481         }
1482
1483         /* some sanity check because you can open a printer or a print server */
1484         /* aka: \\server\printer or \\server */
1485
1486         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1487
1488         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1489                 ZERO_STRUCTP(r->out.handle);
1490                 return WERR_INVALID_PARAM;
1491         }
1492
1493         Printer = find_printer_index_by_hnd(p, r->out.handle);
1494         if ( !Printer ) {
1495                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1496                         "handle we created for printer %s\n", r->in.printername));
1497                 close_printer_handle(p, r->out.handle);
1498                 ZERO_STRUCTP(r->out.handle);
1499                 return WERR_INVALID_PARAM;
1500         }
1501
1502         /*
1503          * First case: the user is opening the print server:
1504          *
1505          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1506          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1507          *
1508          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1509          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1510          * or if the user is listed in the smb.conf printer admin parameter.
1511          *
1512          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1513          * client view printer folder, but does not show the MSAPW.
1514          *
1515          * Note: this test needs code to check access rights here too. Jeremy
1516          * could you look at this?
1517          *
1518          * Second case: the user is opening a printer:
1519          * NT doesn't let us connect to a printer if the connecting user
1520          * doesn't have print permission.
1521          *
1522          * Third case: user is opening a Port Monitor
1523          * access checks same as opening a handle to the print server.
1524          */
1525
1526         switch (Printer->printer_type )
1527         {
1528         case SPLHND_SERVER:
1529         case SPLHND_PORTMON_TCP:
1530         case SPLHND_PORTMON_LOCAL:
1531                 /* Printserver handles use global struct... */
1532
1533                 snum = -1;
1534
1535                 /* Map standard access rights to object specific access rights */
1536
1537                 se_map_standard(&r->in.access_mask,
1538                                 &printserver_std_mapping);
1539
1540                 /* Deny any object specific bits that don't apply to print
1541                    servers (i.e printer and job specific bits) */
1542
1543                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1544
1545                 if (r->in.access_mask &
1546                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1547                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1548                         close_printer_handle(p, r->out.handle);
1549                         ZERO_STRUCTP(r->out.handle);
1550                         return WERR_ACCESS_DENIED;
1551                 }
1552
1553                 /* Allow admin access */
1554
1555                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1556                 {
1557                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1558
1559                         if (!lp_ms_add_printer_wizard()) {
1560                                 close_printer_handle(p, r->out.handle);
1561                                 ZERO_STRUCTP(r->out.handle);
1562                                 return WERR_ACCESS_DENIED;
1563                         }
1564
1565                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1566                            and not a printer admin, then fail */
1567
1568                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1569                             !user_has_privileges(p->server_info->ptok,
1570                                                  &se_printop ) &&
1571                             !token_contains_name_in_list(
1572                                     uidtoname(p->server_info->utok.uid),
1573                                     p->server_info->info3->base.domain.string,
1574                                     NULL,
1575                                     p->server_info->ptok,
1576                                     lp_printer_admin(snum))) {
1577                                 close_printer_handle(p, r->out.handle);
1578                                 ZERO_STRUCTP(r->out.handle);
1579                                 return WERR_ACCESS_DENIED;
1580                         }
1581
1582                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1583                 }
1584                 else
1585                 {
1586                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1587                 }
1588
1589                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1590                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1591
1592                 /* We fall through to return WERR_OK */
1593                 break;
1594
1595         case SPLHND_PRINTER:
1596                 /* NT doesn't let us connect to a printer if the connecting user
1597                    doesn't have print permission.  */
1598
1599                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1600                         close_printer_handle(p, r->out.handle);
1601                         ZERO_STRUCTP(r->out.handle);
1602                         return WERR_BADFID;
1603                 }
1604
1605                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1606                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1607                 }
1608
1609                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1610
1611                 /* map an empty access mask to the minimum access mask */
1612                 if (r->in.access_mask == 0x0)
1613                         r->in.access_mask = PRINTER_ACCESS_USE;
1614
1615                 /*
1616                  * If we are not serving the printer driver for this printer,
1617                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1618                  * will keep NT clients happy  --jerry
1619                  */
1620
1621                 if (lp_use_client_driver(snum)
1622                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1623                 {
1624                         r->in.access_mask = PRINTER_ACCESS_USE;
1625                 }
1626
1627                 /* check smb.conf parameters and the the sec_desc */
1628
1629                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1630                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1631                         ZERO_STRUCTP(r->out.handle);
1632                         return WERR_ACCESS_DENIED;
1633                 }
1634
1635                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1636                                    p->server_info->ptok, snum) ||
1637                     !print_access_check(p->server_info, snum,
1638                                         r->in.access_mask)) {
1639                         DEBUG(3, ("access DENIED for printer open\n"));
1640                         close_printer_handle(p, r->out.handle);
1641                         ZERO_STRUCTP(r->out.handle);
1642                         return WERR_ACCESS_DENIED;
1643                 }
1644
1645                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1646                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1647                         close_printer_handle(p, r->out.handle);
1648                         ZERO_STRUCTP(r->out.handle);
1649                         return WERR_ACCESS_DENIED;
1650                 }
1651
1652                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1653                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1654                 else
1655                         r->in.access_mask = PRINTER_ACCESS_USE;
1656
1657                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1658                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1659
1660                 break;
1661
1662         default:
1663                 /* sanity check to prevent programmer error */
1664                 ZERO_STRUCTP(r->out.handle);
1665                 return WERR_BADFID;
1666         }
1667
1668         Printer->access_granted = r->in.access_mask;
1669
1670         /*
1671          * If the client sent a devmode in the OpenPrinter() call, then
1672          * save it here in case we get a job submission on this handle
1673          */
1674
1675          if ((Printer->printer_type != SPLHND_SERVER) &&
1676              r->in.devmode_ctr.devmode) {
1677                 convert_devicemode(Printer->sharename,
1678                                    r->in.devmode_ctr.devmode,
1679                                    &Printer->nt_devmode);
1680          }
1681
1682 #if 0   /* JERRY -- I'm doubtful this is really effective */
1683         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1684            optimization in Windows 2000 clients  --jerry */
1685
1686         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1687                 && (RA_WIN2K == get_remote_arch()) )
1688         {
1689                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1690                 sys_usleep( 500000 );
1691         }
1692 #endif
1693
1694         return WERR_OK;
1695 }
1696
1697 /****************************************************************************
1698 ****************************************************************************/
1699
1700 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1701                                               NT_PRINTER_INFO_LEVEL_2 *d)
1702 {
1703         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1704
1705         if (!r || !d) {
1706                 return false;
1707         }
1708
1709         d->attributes           = r->attributes;
1710         d->priority             = r->priority;
1711         d->default_priority     = r->defaultpriority;
1712         d->starttime            = r->starttime;
1713         d->untiltime            = r->untiltime;
1714         d->status               = r->status;
1715         d->cjobs                = r->cjobs;
1716
1717         fstrcpy(d->servername,  r->servername);
1718         fstrcpy(d->printername, r->printername);
1719         fstrcpy(d->sharename,   r->sharename);
1720         fstrcpy(d->portname,    r->portname);
1721         fstrcpy(d->drivername,  r->drivername);
1722         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1723         fstrcpy(d->location,    r->location);
1724         fstrcpy(d->sepfile,     r->sepfile);
1725         fstrcpy(d->printprocessor, r->printprocessor);
1726         fstrcpy(d->datatype,    r->datatype);
1727         fstrcpy(d->parameters,  r->parameters);
1728
1729         return true;
1730 }
1731
1732 /****************************************************************************
1733 ****************************************************************************/
1734
1735 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1736                                  NT_PRINTER_INFO_LEVEL *printer)
1737 {
1738         bool ret;
1739
1740         switch (info_ctr->level) {
1741         case 2:
1742                 /* allocate memory if needed.  Messy because
1743                    convert_printer_info is used to update an existing
1744                    printer or build a new one */
1745
1746                 if (!printer->info_2) {
1747                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1748                         if (!printer->info_2) {
1749                                 DEBUG(0,("convert_printer_info: "
1750                                         "talloc() failed!\n"));
1751                                 return false;
1752                         }
1753                 }
1754
1755                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1756                                                         printer->info_2);
1757                 printer->info_2->setuptime = time(NULL);
1758                 return ret;
1759         }
1760
1761         return false;
1762 }
1763
1764 /****************************************************************
1765  _spoolss_ClosePrinter
1766 ****************************************************************/
1767
1768 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1769                              struct spoolss_ClosePrinter *r)
1770 {
1771         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1772
1773         if (Printer && Printer->document_started) {
1774                 struct spoolss_EndDocPrinter e;
1775
1776                 e.in.handle = r->in.handle;
1777
1778                 _spoolss_EndDocPrinter(p, &e);
1779         }
1780
1781         if (!close_printer_handle(p, r->in.handle))
1782                 return WERR_BADFID;
1783
1784         /* clear the returned printer handle.  Observed behavior
1785            from Win2k server.  Don't think this really matters.
1786            Previous code just copied the value of the closed
1787            handle.    --jerry */
1788
1789         ZERO_STRUCTP(r->out.handle);
1790
1791         return WERR_OK;
1792 }
1793
1794 /****************************************************************
1795  _spoolss_DeletePrinter
1796 ****************************************************************/
1797
1798 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1799                               struct spoolss_DeletePrinter *r)
1800 {
1801         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1802         WERROR result;
1803
1804         if (Printer && Printer->document_started) {
1805                 struct spoolss_EndDocPrinter e;
1806
1807                 e.in.handle = r->in.handle;
1808
1809                 _spoolss_EndDocPrinter(p, &e);
1810         }
1811
1812         result = delete_printer_handle(p, r->in.handle);
1813
1814         update_c_setprinter(false);
1815
1816         return result;
1817 }
1818
1819 /*******************************************************************
1820  * static function to lookup the version id corresponding to an
1821  * long architecture string
1822  ******************************************************************/
1823
1824 static const struct print_architecture_table_node archi_table[]= {
1825
1826         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1827         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1828         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1829         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1830         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1831         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1832         {"Windows x64",          SPL_ARCH_X64,          3 },
1833         {NULL,                   "",            -1 }
1834 };
1835
1836 static int get_version_id(const char *arch)
1837 {
1838         int i;
1839
1840         for (i=0; archi_table[i].long_archi != NULL; i++)
1841         {
1842                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1843                         return (archi_table[i].version);
1844         }
1845
1846         return -1;
1847 }
1848
1849 /****************************************************************
1850  _spoolss_DeletePrinterDriver
1851 ****************************************************************/
1852
1853 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1854                                     struct spoolss_DeletePrinterDriver *r)
1855 {
1856
1857         struct spoolss_DriverInfo8 *info = NULL;
1858         struct spoolss_DriverInfo8 *info_win2k = NULL;
1859         int                             version;
1860         WERROR                          status;
1861         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1862         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1863
1864         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1865            and not a printer admin, then fail */
1866
1867         if ( (p->server_info->utok.uid != sec_initial_uid())
1868                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1869                 && !token_contains_name_in_list(
1870                         uidtoname(p->server_info->utok.uid),
1871                         p->server_info->info3->base.domain.string,
1872                         NULL,
1873                         p->server_info->ptok,
1874                         lp_printer_admin(-1)) )
1875         {
1876                 return WERR_ACCESS_DENIED;
1877         }
1878
1879         /* check that we have a valid driver name first */
1880
1881         if ((version = get_version_id(r->in.architecture)) == -1)
1882                 return WERR_INVALID_ENVIRONMENT;
1883
1884         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1885                                                 r->in.architecture,
1886                                                 version)))
1887         {
1888                 /* try for Win2k driver if "Windows NT x86" */
1889
1890                 if ( version == 2 ) {
1891                         version = 3;
1892                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1893                                                                 &info,
1894                                                                 r->in.driver,
1895                                                                 r->in.architecture,
1896                                                                 version))) {
1897                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1898                                 goto done;
1899                         }
1900                 }
1901                 /* otherwise it was a failure */
1902                 else {
1903                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1904                         goto done;
1905                 }
1906
1907         }
1908
1909         if (printer_driver_in_use(info)) {
1910                 status = WERR_PRINTER_DRIVER_IN_USE;
1911                 goto done;
1912         }
1913
1914         if ( version == 2 )
1915         {
1916                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1917                                                        &info_win2k,
1918                                                        r->in.driver,
1919                                                        r->in.architecture, 3)))
1920                 {
1921                         /* if we get to here, we now have 2 driver info structures to remove */
1922                         /* remove the Win2k driver first*/
1923
1924                         status_win2k = delete_printer_driver(
1925                                 p, info_win2k, 3, false);
1926                         free_a_printer_driver(info_win2k);
1927
1928                         /* this should not have failed---if it did, report to client */
1929                         if ( !W_ERROR_IS_OK(status_win2k) )
1930                         {
1931                                 status = status_win2k;
1932                                 goto done;
1933                         }
1934                 }
1935         }
1936
1937         status = delete_printer_driver(p, info, version, false);
1938
1939         /* if at least one of the deletes succeeded return OK */
1940
1941         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1942                 status = WERR_OK;
1943
1944 done:
1945         free_a_printer_driver(info);
1946
1947         return status;
1948 }
1949
1950 /****************************************************************
1951  _spoolss_DeletePrinterDriverEx
1952 ****************************************************************/
1953
1954 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1955                                       struct spoolss_DeletePrinterDriverEx *r)
1956 {
1957         struct spoolss_DriverInfo8      *info = NULL;
1958         struct spoolss_DriverInfo8      *info_win2k = NULL;
1959         int                             version;
1960         bool                            delete_files;
1961         WERROR                          status;
1962         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1963         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1964
1965         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1966            and not a printer admin, then fail */
1967
1968         if ( (p->server_info->utok.uid != sec_initial_uid())
1969                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1970                 && !token_contains_name_in_list(
1971                         uidtoname(p->server_info->utok.uid),
1972                         p->server_info->info3->base.domain.string,
1973                         NULL,
1974                         p->server_info->ptok, lp_printer_admin(-1)) )
1975         {
1976                 return WERR_ACCESS_DENIED;
1977         }
1978
1979         /* check that we have a valid driver name first */
1980         if ((version = get_version_id(r->in.architecture)) == -1) {
1981                 /* this is what NT returns */
1982                 return WERR_INVALID_ENVIRONMENT;
1983         }
1984
1985         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1986                 version = r->in.version;
1987
1988         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1989                                       r->in.architecture, version);
1990
1991         if ( !W_ERROR_IS_OK(status) )
1992         {
1993                 /*
1994                  * if the client asked for a specific version,
1995                  * or this is something other than Windows NT x86,
1996                  * then we've failed
1997                  */
1998
1999                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2000                         goto done;
2001
2002                 /* try for Win2k driver if "Windows NT x86" */
2003
2004                 version = 3;
2005                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2006                                                         r->in.architecture,
2007                                                         version))) {
2008                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2009                         goto done;
2010                 }
2011         }
2012
2013         if (printer_driver_in_use(info)) {
2014                 status = WERR_PRINTER_DRIVER_IN_USE;
2015                 goto done;
2016         }
2017
2018         /*
2019          * we have a couple of cases to consider.
2020          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2021          *     then the delete should fail if **any** files overlap with
2022          *     other drivers
2023          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2024          *     non-overlapping files
2025          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2026          *     is set, the do not delete any files
2027          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2028          */
2029
2030         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2031
2032         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2033
2034         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2035                 /* no idea of the correct error here */
2036                 status = WERR_ACCESS_DENIED;
2037                 goto done;
2038         }
2039
2040
2041         /* also check for W32X86/3 if necessary; maybe we already have? */
2042
2043         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2044                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2045                                                        r->in.driver,
2046                                                        r->in.architecture, 3)))
2047                 {
2048
2049                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2050                                 /* no idea of the correct error here */
2051                                 free_a_printer_driver(info_win2k);
2052                                 status = WERR_ACCESS_DENIED;
2053                                 goto done;
2054                         }
2055
2056                         /* if we get to here, we now have 2 driver info structures to remove */
2057                         /* remove the Win2k driver first*/
2058
2059                         status_win2k = delete_printer_driver(
2060                                 p, info_win2k, 3, delete_files);
2061                         free_a_printer_driver(info_win2k);
2062
2063                         /* this should not have failed---if it did, report to client */
2064
2065                         if ( !W_ERROR_IS_OK(status_win2k) )
2066                                 goto done;
2067                 }
2068         }
2069
2070         status = delete_printer_driver(p, info, version, delete_files);
2071
2072         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2073                 status = WERR_OK;
2074 done:
2075         free_a_printer_driver(info);
2076
2077         return status;
2078 }
2079
2080
2081 /****************************************************************************
2082  Internal routine for removing printerdata
2083  ***************************************************************************/
2084
2085 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2086 {
2087         return delete_printer_data( printer->info_2, key, value );
2088 }
2089
2090 /****************************************************************************
2091  Internal routine for storing printerdata
2092  ***************************************************************************/
2093
2094 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2095                           const char *key, const char *value,
2096                           uint32_t type, uint8_t *data, int real_len)
2097 {
2098         /* the registry objects enforce uniqueness based on value name */
2099
2100         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2101 }
2102
2103 /********************************************************************
2104  GetPrinterData on a printer server Handle.
2105 ********************************************************************/
2106
2107 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2108                                             const char *value,
2109                                             enum winreg_Type *type,
2110                                             union spoolss_PrinterData *data)
2111 {
2112         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2113
2114         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2115                 *type = REG_DWORD;
2116                 data->value = 0x00;
2117                 return WERR_OK;
2118         }
2119
2120         if (!StrCaseCmp(value, "BeepEnabled")) {
2121                 *type = REG_DWORD;
2122                 data->value = 0x00;
2123                 return WERR_OK;
2124         }
2125
2126         if (!StrCaseCmp(value, "EventLog")) {
2127                 *type = REG_DWORD;
2128                 /* formally was 0x1b */
2129                 data->value = 0x00;
2130                 return WERR_OK;
2131         }
2132
2133         if (!StrCaseCmp(value, "NetPopup")) {
2134                 *type = REG_DWORD;
2135                 data->value = 0x00;
2136                 return WERR_OK;
2137         }
2138
2139         if (!StrCaseCmp(value, "MajorVersion")) {
2140                 *type = REG_DWORD;
2141
2142                 /* Windows NT 4.0 seems to not allow uploading of drivers
2143                    to a server that reports 0x3 as the MajorVersion.
2144                    need to investigate more how Win2k gets around this .
2145                    -- jerry */
2146
2147                 if (RA_WINNT == get_remote_arch()) {
2148                         data->value = 0x02;
2149                 } else {
2150                         data->value = 0x03;
2151                 }
2152
2153                 return WERR_OK;
2154         }
2155
2156         if (!StrCaseCmp(value, "MinorVersion")) {
2157                 *type = REG_DWORD;
2158                 data->value = 0x00;
2159                 return WERR_OK;
2160         }
2161
2162         /* REG_BINARY
2163          *  uint32_t size        = 0x114
2164          *  uint32_t major       = 5
2165          *  uint32_t minor       = [0|1]
2166          *  uint32_t build       = [2195|2600]
2167          *  extra unicode string = e.g. "Service Pack 3"
2168          */
2169         if (!StrCaseCmp(value, "OSVersion")) {
2170                 DATA_BLOB blob;
2171                 enum ndr_err_code ndr_err;
2172                 struct spoolss_OSVersion os;
2173
2174                 os.major                = 5;    /* Windows 2000 == 5.0 */
2175                 os.minor                = 0;
2176                 os.build                = 2195; /* build */
2177                 os.extra_string         = "";   /* leave extra string empty */
2178
2179                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2180                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2181                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2182                         return WERR_GENERAL_FAILURE;
2183                 }
2184
2185                 *type = REG_BINARY;
2186                 data->binary = blob;
2187
2188                 return WERR_OK;
2189         }
2190
2191
2192         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2193                 *type = REG_SZ;
2194
2195                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2196                 W_ERROR_HAVE_NO_MEMORY(data->string);
2197
2198                 return WERR_OK;
2199         }
2200
2201         if (!StrCaseCmp(value, "Architecture")) {
2202                 *type = REG_SZ;
2203                 data->string = talloc_strdup(mem_ctx,
2204                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2205                 W_ERROR_HAVE_NO_MEMORY(data->string);
2206
2207                 return WERR_OK;
2208         }
2209
2210         if (!StrCaseCmp(value, "DsPresent")) {
2211                 *type = REG_DWORD;
2212
2213                 /* only show the publish check box if we are a
2214                    member of a AD domain */
2215
2216                 if (lp_security() == SEC_ADS) {
2217                         data->value = 0x01;
2218                 } else {
2219                         data->value = 0x00;
2220                 }
2221                 return WERR_OK;
2222         }
2223
2224         if (!StrCaseCmp(value, "DNSMachineName")) {
2225                 const char *hostname = get_mydnsfullname();
2226
2227                 if (!hostname) {
2228                         return WERR_BADFILE;
2229                 }
2230
2231                 *type = REG_SZ;
2232                 data->string = talloc_strdup(mem_ctx, hostname);
2233                 W_ERROR_HAVE_NO_MEMORY(data->string);
2234
2235                 return WERR_OK;
2236         }
2237
2238         *type = REG_NONE;
2239
2240         return WERR_INVALID_PARAM;
2241 }
2242
2243 /****************************************************************
2244  _spoolss_GetPrinterData
2245 ****************************************************************/
2246
2247 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2248                                struct spoolss_GetPrinterData *r)
2249 {
2250         struct spoolss_GetPrinterDataEx r2;
2251
2252         r2.in.handle            = r->in.handle;
2253         r2.in.key_name          = "PrinterDriverData";
2254         r2.in.value_name        = r->in.value_name;
2255         r2.in.offered           = r->in.offered;
2256         r2.out.type             = r->out.type;
2257         r2.out.data             = r->out.data;
2258         r2.out.needed           = r->out.needed;
2259
2260         return _spoolss_GetPrinterDataEx(p, &r2);
2261 }
2262
2263 /*********************************************************
2264  Connect to the client machine.
2265 **********************************************************/
2266
2267 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2268                         struct sockaddr_storage *client_ss, const char *remote_machine)
2269 {
2270         NTSTATUS ret;
2271         struct cli_state *the_cli;
2272         struct sockaddr_storage rm_addr;
2273         char addr[INET6_ADDRSTRLEN];
2274
2275         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2276                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2277                         remote_machine));
2278                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2279                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2280                         return false;
2281                 }
2282                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2283         } else {
2284                 rm_addr = *client_ss;
2285                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2286                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2287                         addr));
2288         }
2289
2290         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2291                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2292                         addr));
2293                 return false;
2294         }
2295
2296         /* setup the connection */
2297         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2298                 &rm_addr, 0, "IPC$", "IPC",
2299                 "", /* username */
2300                 "", /* domain */
2301                 "", /* password */
2302                 0, lp_client_signing(), NULL );
2303
2304         if ( !NT_STATUS_IS_OK( ret ) ) {
2305                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2306                         remote_machine ));
2307                 return false;
2308         }
2309
2310         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2311                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2312                 cli_shutdown(the_cli);
2313                 return false;
2314         }
2315
2316         /*
2317          * Ok - we have an anonymous connection to the IPC$ share.
2318          * Now start the NT Domain stuff :-).
2319          */
2320
2321         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2322         if (!NT_STATUS_IS_OK(ret)) {
2323                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2324                         remote_machine, nt_errstr(ret)));
2325                 cli_shutdown(the_cli);
2326                 return false;
2327         }
2328
2329         return true;
2330 }
2331
2332 /***************************************************************************
2333  Connect to the client.
2334 ****************************************************************************/
2335
2336 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2337                                         uint32_t localprinter, uint32_t type,
2338                                         struct policy_handle *handle,
2339                                         struct sockaddr_storage *client_ss)
2340 {
2341         WERROR result;
2342         NTSTATUS status;
2343
2344         /*
2345          * If it's the first connection, contact the client
2346          * and connect to the IPC$ share anonymously
2347          */
2348         if (smb_connections==0) {
2349                 fstring unix_printer;
2350
2351                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2352
2353                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2354                         return false;
2355
2356                 messaging_register(smbd_messaging_context(), NULL,
2357                                    MSG_PRINTER_NOTIFY2,
2358                                    receive_notify2_message_list);
2359                 /* Tell the connections db we're now interested in printer
2360                  * notify messages. */
2361                 serverid_register_msg_flags(
2362                         procid_self(),
2363                         true, FLAG_MSG_PRINT_NOTIFY);
2364         }
2365
2366         /*
2367          * Tell the specific printing tdb we want messages for this printer
2368          * by registering our PID.
2369          */
2370
2371         if (!print_notify_register_pid(snum))
2372                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2373
2374         smb_connections++;
2375
2376         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2377                                                  printer,
2378                                                  localprinter,
2379                                                  type,
2380                                                  0,
2381                                                  NULL,
2382                                                  handle,
2383                                                  &result);
2384         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2385                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2386                         win_errstr(result)));
2387
2388         return (W_ERROR_IS_OK(result));
2389 }
2390
2391 /****************************************************************
2392  ****************************************************************/
2393
2394 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2395                                                              const struct spoolss_NotifyOption *r)
2396 {
2397         struct spoolss_NotifyOption *option;
2398         uint32_t i,k;
2399
2400         if (!r) {
2401                 return NULL;
2402         }
2403
2404         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2405         if (!option) {
2406                 return NULL;
2407         }
2408
2409         *option = *r;
2410
2411         if (!option->count) {
2412                 return option;
2413         }
2414
2415         option->types = talloc_zero_array(option,
2416                 struct spoolss_NotifyOptionType, option->count);
2417         if (!option->types) {
2418                 talloc_free(option);
2419                 return NULL;
2420         }
2421
2422         for (i=0; i < option->count; i++) {
2423                 option->types[i] = r->types[i];
2424
2425                 if (option->types[i].count) {
2426                         option->types[i].fields = talloc_zero_array(option,
2427                                 union spoolss_Field, option->types[i].count);
2428                         if (!option->types[i].fields) {
2429                                 talloc_free(option);
2430                                 return NULL;
2431                         }
2432                         for (k=0; k<option->types[i].count; k++) {
2433                                 option->types[i].fields[k] =
2434                                         r->types[i].fields[k];
2435                         }
2436                 }
2437         }
2438
2439         return option;
2440 }
2441
2442 /****************************************************************
2443  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2444  *
2445  * before replying OK: status=0 a rpc call is made to the workstation
2446  * asking ReplyOpenPrinter
2447  *
2448  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2449  * called from api_spoolss_rffpcnex
2450 ****************************************************************/
2451
2452 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2453                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2454 {
2455         int snum = -1;
2456         struct spoolss_NotifyOption *option = r->in.notify_options;
2457         struct sockaddr_storage client_ss;
2458
2459         /* store the notify value in the printer struct */
2460
2461         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2462
2463         if (!Printer) {
2464                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2465                         "Invalid handle (%s:%u:%u).\n",
2466                         OUR_HANDLE(r->in.handle)));
2467                 return WERR_BADFID;
2468         }
2469
2470         Printer->notify.flags           = r->in.flags;
2471         Printer->notify.options         = r->in.options;
2472         Printer->notify.printerlocal    = r->in.printer_local;
2473
2474         TALLOC_FREE(Printer->notify.option);
2475         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2476
2477         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2478
2479         /* Connect to the client machine and send a ReplyOpenPrinter */
2480
2481         if ( Printer->printer_type == SPLHND_SERVER)
2482                 snum = -1;
2483         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2484                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2485                 return WERR_BADFID;
2486
2487         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2488                 "client_address is %s\n", p->client_address));
2489
2490         if (!interpret_string_addr(&client_ss, p->client_address,
2491                                    AI_NUMERICHOST)) {
2492                 return WERR_SERVER_UNAVAILABLE;
2493         }
2494
2495         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2496                                         Printer->notify.printerlocal, 1,
2497                                         &Printer->notify.client_hnd, &client_ss))
2498                 return WERR_SERVER_UNAVAILABLE;
2499
2500         Printer->notify.client_connected = true;
2501
2502         return WERR_OK;
2503 }
2504
2505 /*******************************************************************
2506  * fill a notify_info_data with the servername
2507  ********************************************************************/
2508
2509 static void spoolss_notify_server_name(int snum,
2510                                        struct spoolss_Notify *data,
2511                                        print_queue_struct *queue,
2512                                        NT_PRINTER_INFO_LEVEL *printer,
2513                                        TALLOC_CTX *mem_ctx)
2514 {
2515         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2516 }
2517
2518 /*******************************************************************
2519  * fill a notify_info_data with the printername (not including the servername).
2520  ********************************************************************/
2521
2522 static void spoolss_notify_printer_name(int snum,
2523                                         struct spoolss_Notify *data,
2524                                         print_queue_struct *queue,
2525                                         NT_PRINTER_INFO_LEVEL *printer,
2526                                         TALLOC_CTX *mem_ctx)
2527 {
2528         /* the notify name should not contain the \\server\ part */
2529         char *p = strrchr(printer->info_2->printername, '\\');
2530
2531         if (!p) {
2532                 p = printer->info_2->printername;
2533         } else {
2534                 p++;
2535         }
2536
2537         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2538 }
2539
2540 /*******************************************************************
2541  * fill a notify_info_data with the servicename
2542  ********************************************************************/
2543
2544 static void spoolss_notify_share_name(int snum,
2545                                       struct spoolss_Notify *data,
2546                                       print_queue_struct *queue,
2547                                       NT_PRINTER_INFO_LEVEL *printer,
2548                                       TALLOC_CTX *mem_ctx)
2549 {
2550         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2551 }
2552
2553 /*******************************************************************
2554  * fill a notify_info_data with the port name
2555  ********************************************************************/
2556
2557 static void spoolss_notify_port_name(int snum,
2558                                      struct spoolss_Notify *data,
2559                                      print_queue_struct *queue,
2560                                      NT_PRINTER_INFO_LEVEL *printer,
2561                                      TALLOC_CTX *mem_ctx)
2562 {
2563         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2564 }
2565
2566 /*******************************************************************
2567  * fill a notify_info_data with the printername
2568  * but it doesn't exist, have to see what to do
2569  ********************************************************************/
2570
2571 static void spoolss_notify_driver_name(int snum,
2572                                        struct spoolss_Notify *data,
2573                                        print_queue_struct *queue,
2574                                        NT_PRINTER_INFO_LEVEL *printer,
2575                                        TALLOC_CTX *mem_ctx)
2576 {
2577         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2578 }
2579
2580 /*******************************************************************
2581  * fill a notify_info_data with the comment
2582  ********************************************************************/
2583
2584 static void spoolss_notify_comment(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         char *p;
2591
2592         if (*printer->info_2->comment == '\0') {
2593                 p = lp_comment(snum);
2594         } else {
2595                 p = printer->info_2->comment;
2596         }
2597
2598         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2599 }
2600
2601 /*******************************************************************
2602  * fill a notify_info_data with the comment
2603  * location = "Room 1, floor 2, building 3"
2604  ********************************************************************/
2605
2606 static void spoolss_notify_location(int snum,
2607                                     struct spoolss_Notify *data,
2608                                     print_queue_struct *queue,
2609                                     NT_PRINTER_INFO_LEVEL *printer,
2610                                     TALLOC_CTX *mem_ctx)
2611 {
2612         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2613 }
2614
2615 /*******************************************************************
2616  * fill a notify_info_data with the device mode
2617  * jfm:xxxx don't to it for know but that's a real problem !!!
2618  ********************************************************************/
2619
2620 static void spoolss_notify_devmode(int snum,
2621                                    struct spoolss_Notify *data,
2622                                    print_queue_struct *queue,
2623                                    NT_PRINTER_INFO_LEVEL *printer,
2624                                    TALLOC_CTX *mem_ctx)
2625 {
2626         /* for a dummy implementation we have to zero the fields */
2627         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2628 }
2629
2630 /*******************************************************************
2631  * fill a notify_info_data with the separator file name
2632  ********************************************************************/
2633
2634 static void spoolss_notify_sepfile(int snum,
2635                                    struct spoolss_Notify *data,
2636                                    print_queue_struct *queue,
2637                                    NT_PRINTER_INFO_LEVEL *printer,
2638                                    TALLOC_CTX *mem_ctx)
2639 {
2640         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2641 }
2642
2643 /*******************************************************************
2644  * fill a notify_info_data with the print processor
2645  * jfm:xxxx return always winprint to indicate we don't do anything to it
2646  ********************************************************************/
2647
2648 static void spoolss_notify_print_processor(int snum,
2649                                            struct spoolss_Notify *data,
2650                                            print_queue_struct *queue,
2651                                            NT_PRINTER_INFO_LEVEL *printer,
2652                                            TALLOC_CTX *mem_ctx)
2653 {
2654         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2655 }
2656
2657 /*******************************************************************
2658  * fill a notify_info_data with the print processor options
2659  * jfm:xxxx send an empty string
2660  ********************************************************************/
2661
2662 static void spoolss_notify_parameters(int snum,
2663                                       struct spoolss_Notify *data,
2664                                       print_queue_struct *queue,
2665                                       NT_PRINTER_INFO_LEVEL *printer,
2666                                       TALLOC_CTX *mem_ctx)
2667 {
2668         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2669 }
2670
2671 /*******************************************************************
2672  * fill a notify_info_data with the data type
2673  * jfm:xxxx always send RAW as data type
2674  ********************************************************************/
2675
2676 static void spoolss_notify_datatype(int snum,
2677                                     struct spoolss_Notify *data,
2678                                     print_queue_struct *queue,
2679                                     NT_PRINTER_INFO_LEVEL *printer,
2680                                     TALLOC_CTX *mem_ctx)
2681 {
2682         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2683 }
2684
2685 /*******************************************************************
2686  * fill a notify_info_data with the security descriptor
2687  * jfm:xxxx send an null pointer to say no security desc
2688  * have to implement security before !
2689  ********************************************************************/
2690
2691 static void spoolss_notify_security_desc(int snum,
2692                                          struct spoolss_Notify *data,
2693                                          print_queue_struct *queue,
2694                                          NT_PRINTER_INFO_LEVEL *printer,
2695                                          TALLOC_CTX *mem_ctx)
2696 {
2697         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2698                                           printer->info_2->secdesc_buf->sd_size,
2699                                           printer->info_2->secdesc_buf->sd);
2700 }
2701
2702 /*******************************************************************
2703  * fill a notify_info_data with the attributes
2704  * jfm:xxxx a samba printer is always shared
2705  ********************************************************************/
2706
2707 static void spoolss_notify_attributes(int snum,
2708                                       struct spoolss_Notify *data,
2709                                       print_queue_struct *queue,
2710                                       NT_PRINTER_INFO_LEVEL *printer,
2711                                       TALLOC_CTX *mem_ctx)
2712 {
2713         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2714 }
2715
2716 /*******************************************************************
2717  * fill a notify_info_data with the priority
2718  ********************************************************************/
2719
2720 static void spoolss_notify_priority(int snum,
2721                                     struct spoolss_Notify *data,
2722                                     print_queue_struct *queue,
2723                                     NT_PRINTER_INFO_LEVEL *printer,
2724                                     TALLOC_CTX *mem_ctx)
2725 {
2726         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2727 }
2728
2729 /*******************************************************************
2730  * fill a notify_info_data with the default priority
2731  ********************************************************************/
2732
2733 static void spoolss_notify_default_priority(int snum,
2734                                             struct spoolss_Notify *data,
2735                                             print_queue_struct *queue,
2736                                             NT_PRINTER_INFO_LEVEL *printer,
2737                                             TALLOC_CTX *mem_ctx)
2738 {
2739         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2740 }
2741
2742 /*******************************************************************
2743  * fill a notify_info_data with the start time
2744  ********************************************************************/
2745
2746 static void spoolss_notify_start_time(int snum,
2747                                       struct spoolss_Notify *data,
2748                                       print_queue_struct *queue,
2749                                       NT_PRINTER_INFO_LEVEL *printer,
2750                                       TALLOC_CTX *mem_ctx)
2751 {
2752         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2753 }
2754
2755 /*******************************************************************
2756  * fill a notify_info_data with the until time
2757  ********************************************************************/
2758
2759 static void spoolss_notify_until_time(int snum,
2760                                       struct spoolss_Notify *data,
2761                                       print_queue_struct *queue,
2762                                       NT_PRINTER_INFO_LEVEL *printer,
2763                                       TALLOC_CTX *mem_ctx)
2764 {
2765         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2766 }
2767
2768 /*******************************************************************
2769  * fill a notify_info_data with the status
2770  ********************************************************************/
2771
2772 static void spoolss_notify_status(int snum,
2773                                   struct spoolss_Notify *data,
2774                                   print_queue_struct *queue,
2775                                   NT_PRINTER_INFO_LEVEL *printer,
2776                                   TALLOC_CTX *mem_ctx)
2777 {
2778         print_status_struct status;
2779
2780         print_queue_length(snum, &status);
2781         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2782 }
2783
2784 /*******************************************************************
2785  * fill a notify_info_data with the number of jobs queued
2786  ********************************************************************/
2787
2788 static void spoolss_notify_cjobs(int snum,
2789                                  struct spoolss_Notify *data,
2790                                  print_queue_struct *queue,
2791                                  NT_PRINTER_INFO_LEVEL *printer,
2792                                  TALLOC_CTX *mem_ctx)
2793 {
2794         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2795 }
2796
2797 /*******************************************************************
2798  * fill a notify_info_data with the average ppm
2799  ********************************************************************/
2800
2801 static void spoolss_notify_average_ppm(int snum,
2802                                        struct spoolss_Notify *data,
2803                                        print_queue_struct *queue,
2804                                        NT_PRINTER_INFO_LEVEL *printer,
2805                                        TALLOC_CTX *mem_ctx)
2806 {
2807         /* always respond 8 pages per minutes */
2808         /* a little hard ! */
2809         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2810 }
2811
2812 /*******************************************************************
2813  * fill a notify_info_data with username
2814  ********************************************************************/
2815
2816 static void spoolss_notify_username(int snum,
2817                                     struct spoolss_Notify *data,
2818                                     print_queue_struct *queue,
2819                                     NT_PRINTER_INFO_LEVEL *printer,
2820                                     TALLOC_CTX *mem_ctx)
2821 {
2822         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2823 }
2824
2825 /*******************************************************************
2826  * fill a notify_info_data with job status
2827  ********************************************************************/
2828
2829 static void spoolss_notify_job_status(int snum,
2830                                       struct spoolss_Notify *data,
2831                                       print_queue_struct *queue,
2832                                       NT_PRINTER_INFO_LEVEL *printer,
2833                                       TALLOC_CTX *mem_ctx)
2834 {
2835         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2836 }
2837
2838 /*******************************************************************
2839  * fill a notify_info_data with job name
2840  ********************************************************************/
2841
2842 static void spoolss_notify_job_name(int snum,
2843                                     struct spoolss_Notify *data,
2844                                     print_queue_struct *queue,
2845                                     NT_PRINTER_INFO_LEVEL *printer,
2846                                     TALLOC_CTX *mem_ctx)
2847 {
2848         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2849 }
2850
2851 /*******************************************************************
2852  * fill a notify_info_data with job status
2853  ********************************************************************/
2854
2855 static void spoolss_notify_job_status_string(int snum,
2856                                              struct spoolss_Notify *data,
2857                                              print_queue_struct *queue,
2858                                              NT_PRINTER_INFO_LEVEL *printer,
2859                                              TALLOC_CTX *mem_ctx)
2860 {
2861         /*
2862          * Now we're returning job status codes we just return a "" here. JRA.
2863          */
2864
2865         const char *p = "";
2866
2867 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2868         p = "unknown";
2869
2870         switch (queue->status) {
2871         case LPQ_QUEUED:
2872                 p = "Queued";
2873                 break;
2874         case LPQ_PAUSED:
2875                 p = "";    /* NT provides the paused string */
2876                 break;
2877         case LPQ_SPOOLING:
2878                 p = "Spooling";
2879                 break;
2880         case LPQ_PRINTING:
2881                 p = "Printing";
2882                 break;
2883         }
2884 #endif /* NO LONGER NEEDED. */
2885
2886         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2887 }
2888
2889 /*******************************************************************
2890  * fill a notify_info_data with job time
2891  ********************************************************************/
2892
2893 static void spoolss_notify_job_time(int snum,
2894                                     struct spoolss_Notify *data,
2895                                     print_queue_struct *queue,
2896                                     NT_PRINTER_INFO_LEVEL *printer,
2897                                     TALLOC_CTX *mem_ctx)
2898 {
2899         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2900 }
2901
2902 /*******************************************************************
2903  * fill a notify_info_data with job size
2904  ********************************************************************/
2905
2906 static void spoolss_notify_job_size(int snum,
2907                                     struct spoolss_Notify *data,
2908                                     print_queue_struct *queue,
2909                                     NT_PRINTER_INFO_LEVEL *printer,
2910                                     TALLOC_CTX *mem_ctx)
2911 {
2912         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2913 }
2914
2915 /*******************************************************************
2916  * fill a notify_info_data with page info
2917  ********************************************************************/
2918 static void spoolss_notify_total_pages(int snum,
2919                                 struct spoolss_Notify *data,
2920                                 print_queue_struct *queue,
2921                                 NT_PRINTER_INFO_LEVEL *printer,
2922                                 TALLOC_CTX *mem_ctx)
2923 {
2924         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2925 }
2926
2927 /*******************************************************************
2928  * fill a notify_info_data with pages printed info.
2929  ********************************************************************/
2930 static void spoolss_notify_pages_printed(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         /* Add code when back-end tracks this */
2937         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2938 }
2939
2940 /*******************************************************************
2941  Fill a notify_info_data with job position.
2942  ********************************************************************/
2943
2944 static void spoolss_notify_job_position(int snum,
2945                                         struct spoolss_Notify *data,
2946                                         print_queue_struct *queue,
2947                                         NT_PRINTER_INFO_LEVEL *printer,
2948                                         TALLOC_CTX *mem_ctx)
2949 {
2950         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2951 }
2952
2953 /*******************************************************************
2954  Fill a notify_info_data with submitted time.
2955  ********************************************************************/
2956
2957 static void spoolss_notify_submitted_time(int snum,
2958                                           struct spoolss_Notify *data,
2959                                           print_queue_struct *queue,
2960                                           NT_PRINTER_INFO_LEVEL *printer,
2961                                           TALLOC_CTX *mem_ctx)
2962 {
2963         data->data.string.string = NULL;
2964         data->data.string.size = 0;
2965
2966         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2967                                &data->data.string.string,
2968                                &data->data.string.size);
2969
2970 }
2971
2972 struct s_notify_info_data_table
2973 {
2974         enum spoolss_NotifyType type;
2975         uint16_t field;
2976         const char *name;
2977         enum spoolss_NotifyTable variable_type;
2978         void (*fn) (int snum, struct spoolss_Notify *data,
2979                     print_queue_struct *queue,
2980                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2981 };
2982
2983 /* A table describing the various print notification constants and
2984    whether the notification data is a pointer to a variable sized
2985    buffer, a one value uint32_t or a two value uint32_t. */
2986
2987 static const struct s_notify_info_data_table notify_info_data_table[] =
2988 {
2989 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2990 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2991 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
2992 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2993 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2994 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
2995 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
2996 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2997 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
2998 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2999 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3000 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3001 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3002 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3003 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3004 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3005 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3006 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3007 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3008 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3009 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3010 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3011 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3012 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3013 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3014 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3015 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3016 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3017 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3018 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3019 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3020 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3021 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3022 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3023 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3024 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3025 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3026 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3027 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3028 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3029 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3030 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3031 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3032 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3033 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3034 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3035 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3036 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3037 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3038 };
3039
3040 /*******************************************************************
3041  Return the variable_type of info_data structure.
3042 ********************************************************************/
3043
3044 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3045                                                   uint16_t field)
3046 {
3047         int i=0;
3048
3049         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3050                 if ( (notify_info_data_table[i].type == type) &&
3051                      (notify_info_data_table[i].field == field) ) {
3052                         return notify_info_data_table[i].variable_type;
3053                 }
3054         }
3055
3056         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3057
3058         return 0;
3059 }
3060
3061 /****************************************************************************
3062 ****************************************************************************/
3063
3064 static bool search_notify(enum spoolss_NotifyType type,
3065                           uint16_t field,
3066                           int *value)
3067 {
3068         int i;
3069
3070         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3071                 if (notify_info_data_table[i].type == type &&
3072                     notify_info_data_table[i].field == field &&
3073                     notify_info_data_table[i].fn != NULL) {
3074                         *value = i;
3075                         return true;
3076                 }
3077         }
3078
3079         return false;
3080 }
3081
3082 /****************************************************************************
3083 ****************************************************************************/
3084
3085 void construct_info_data(struct spoolss_Notify *info_data,
3086                          enum spoolss_NotifyType type,
3087                          uint16_t field,
3088                          int id)
3089 {
3090         info_data->type                 = type;
3091         info_data->field.field          = field;
3092         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3093         info_data->job_id               = id;
3094 }
3095
3096 /*******************************************************************
3097  *
3098  * fill a notify_info struct with info asked
3099  *
3100  ********************************************************************/
3101
3102 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3103                                           struct spoolss_NotifyInfo *info,
3104                                           int snum,
3105                                           const struct spoolss_NotifyOptionType *option_type,
3106                                           uint32_t id,
3107                                           TALLOC_CTX *mem_ctx)
3108 {
3109         int field_num,j;
3110         enum spoolss_NotifyType type;
3111         uint16_t field;
3112
3113         struct spoolss_Notify *current_data;
3114         NT_PRINTER_INFO_LEVEL *printer = NULL;
3115         print_queue_struct *queue=NULL;
3116
3117         type = option_type->type;
3118
3119         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3120                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3121                 option_type->count, lp_servicename(snum)));
3122
3123         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3124                 return false;
3125
3126         for(field_num=0; field_num < option_type->count; field_num++) {
3127                 field = option_type->fields[field_num].field;
3128
3129                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3130
3131                 if (!search_notify(type, field, &j) )
3132                         continue;
3133
3134                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3135                                                       struct spoolss_Notify,
3136                                                       info->count + 1);
3137                 if (info->notifies == NULL) {
3138                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3139                         free_a_printer(&printer, 2);
3140                         return false;
3141                 }
3142
3143                 current_data = &info->notifies[info->count];
3144
3145                 construct_info_data(current_data, type, field, id);
3146
3147                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3148                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3149
3150                 notify_info_data_table[j].fn(snum, current_data, queue,
3151                                              printer, mem_ctx);
3152
3153                 info->count++;
3154         }
3155
3156         free_a_printer(&printer, 2);
3157         return true;
3158 }
3159
3160 /*******************************************************************
3161  *
3162  * fill a notify_info struct with info asked
3163  *
3164  ********************************************************************/
3165
3166 static bool construct_notify_jobs_info(print_queue_struct *queue,
3167                                        struct spoolss_NotifyInfo *info,
3168                                        NT_PRINTER_INFO_LEVEL *printer,
3169                                        int snum,
3170                                        const struct spoolss_NotifyOptionType *option_type,
3171                                        uint32_t id,
3172                                        TALLOC_CTX *mem_ctx)
3173 {
3174         int field_num,j;
3175         enum spoolss_NotifyType type;
3176         uint16_t field;
3177         struct spoolss_Notify *current_data;
3178
3179         DEBUG(4,("construct_notify_jobs_info\n"));
3180
3181         type = option_type->type;
3182
3183         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3184                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3185                 option_type->count));
3186
3187         for(field_num=0; field_num<option_type->count; field_num++) {
3188                 field = option_type->fields[field_num].field;
3189
3190                 if (!search_notify(type, field, &j) )
3191                         continue;
3192
3193                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3194                                                       struct spoolss_Notify,
3195                                                       info->count + 1);
3196                 if (info->notifies == NULL) {
3197                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3198                         return false;
3199                 }
3200
3201                 current_data=&(info->notifies[info->count]);
3202
3203                 construct_info_data(current_data, type, field, id);
3204                 notify_info_data_table[j].fn(snum, current_data, queue,
3205                                              printer, mem_ctx);
3206                 info->count++;
3207         }
3208
3209         return true;
3210 }
3211
3212 /*
3213  * JFM: The enumeration is not that simple, it's even non obvious.
3214  *
3215  * let's take an example: I want to monitor the PRINTER SERVER for
3216  * the printer's name and the number of jobs currently queued.
3217  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3218  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3219  *
3220  * I have 3 printers on the back of my server.
3221  *
3222  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3223  * structures.
3224  *   Number     Data                    Id
3225  *      1       printer 1 name          1
3226  *      2       printer 1 cjob          1
3227  *      3       printer 2 name          2
3228  *      4       printer 2 cjob          2
3229  *      5       printer 3 name          3
3230  *      6       printer 3 name          3
3231  *
3232  * that's the print server case, the printer case is even worse.
3233  */
3234
3235 /*******************************************************************
3236  *
3237  * enumerate all printers on the printserver
3238  * fill a notify_info struct with info asked
3239  *
3240  ********************************************************************/
3241
3242 static WERROR printserver_notify_info(pipes_struct *p,
3243                                       struct policy_handle *hnd,
3244                                       struct spoolss_NotifyInfo *info,
3245                                       TALLOC_CTX *mem_ctx)
3246 {
3247         int snum;
3248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3249         int n_services=lp_numservices();
3250         int i;
3251         struct spoolss_NotifyOption *option;
3252         struct spoolss_NotifyOptionType option_type;
3253
3254         DEBUG(4,("printserver_notify_info\n"));
3255
3256         if (!Printer)
3257                 return WERR_BADFID;
3258
3259         option = Printer->notify.option;
3260
3261         info->version   = 2;
3262         info->notifies  = NULL;
3263         info->count     = 0;
3264
3265         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3266            sending a ffpcn() request first */
3267
3268         if ( !option )
3269                 return WERR_BADFID;
3270
3271         for (i=0; i<option->count; i++) {
3272                 option_type = option->types[i];
3273
3274                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3275                         continue;
3276
3277                 for (snum=0; snum<n_services; snum++)
3278                 {
3279                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3280                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3281                 }
3282         }
3283
3284 #if 0
3285         /*
3286          * Debugging information, don't delete.
3287          */
3288
3289         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3290         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3291         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3292
3293         for (i=0; i<info->count; i++) {
3294                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3295                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3296                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3297         }
3298 #endif
3299
3300         return WERR_OK;
3301 }
3302
3303 /*******************************************************************
3304  *
3305  * fill a notify_info struct with info asked
3306  *
3307  ********************************************************************/
3308
3309 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3310                                   struct spoolss_NotifyInfo *info,
3311                                   TALLOC_CTX *mem_ctx)
3312 {
3313         int snum;
3314         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3315         int i;
3316         uint32_t id;
3317         struct spoolss_NotifyOption *option;
3318         struct spoolss_NotifyOptionType option_type;
3319         int count,j;
3320         print_queue_struct *queue=NULL;
3321         print_status_struct status;
3322
3323         DEBUG(4,("printer_notify_info\n"));
3324
3325         if (!Printer)
3326                 return WERR_BADFID;
3327
3328         option = Printer->notify.option;
3329         id = 0x0;
3330
3331         info->version   = 2;
3332         info->notifies  = NULL;
3333         info->count     = 0;
3334
3335         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3336            sending a ffpcn() request first */
3337
3338         if ( !option )
3339                 return WERR_BADFID;
3340
3341         get_printer_snum(p, hnd, &snum, NULL);
3342
3343         for (i=0; i<option->count; i++) {
3344                 option_type = option->types[i];
3345
3346                 switch (option_type.type) {
3347                 case PRINTER_NOTIFY_TYPE:
3348                         if(construct_notify_printer_info(Printer, info, snum,
3349                                                          &option_type, id,
3350                                                          mem_ctx))
3351                                 id--;
3352                         break;
3353
3354                 case JOB_NOTIFY_TYPE: {
3355                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3356
3357                         count = print_queue_status(snum, &queue, &status);
3358
3359                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3360                                 goto done;
3361
3362                         for (j=0; j<count; j++) {
3363                                 construct_notify_jobs_info(&queue[j], info,
3364                                                            printer, snum,
3365                                                            &option_type,
3366                                                            queue[j].job,
3367                                                            mem_ctx);
3368                         }
3369
3370                         free_a_printer(&printer, 2);
3371
3372                 done:
3373                         SAFE_FREE(queue);
3374                         break;
3375                 }
3376                 }
3377         }
3378
3379         /*
3380          * Debugging information, don't delete.
3381          */
3382         /*
3383         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3384         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3385         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3386
3387         for (i=0; i<info->count; i++) {
3388                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3389                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3390                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3391         }
3392         */
3393         return WERR_OK;
3394 }
3395
3396 /****************************************************************
3397  _spoolss_RouterRefreshPrinterChangeNotify
3398 ****************************************************************/
3399
3400 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3401                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3402 {
3403         struct spoolss_NotifyInfo *info;
3404
3405         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3406         WERROR result = WERR_BADFID;
3407
3408         /* we always have a spoolss_NotifyInfo struct */
3409         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3410         if (!info) {
3411                 result = WERR_NOMEM;
3412                 goto done;
3413         }
3414
3415         *r->out.info = info;
3416
3417         if (!Printer) {
3418                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3419                         "Invalid handle (%s:%u:%u).\n",
3420                         OUR_HANDLE(r->in.handle)));
3421                 goto done;
3422         }
3423
3424         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3425
3426         /*
3427          *      We are now using the change value, and
3428          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3429          *      I don't have a global notification system, I'm sending back all the
3430          *      informations even when _NOTHING_ has changed.
3431          */
3432
3433         /* We need to keep track of the change value to send back in
3434            RRPCN replies otherwise our updates are ignored. */
3435
3436         Printer->notify.fnpcn = true;
3437
3438         if (Printer->notify.client_connected) {
3439                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3440                         "Saving change value in request [%x]\n",
3441                         r->in.change_low));
3442                 Printer->notify.change = r->in.change_low;
3443         }
3444
3445         /* just ignore the spoolss_NotifyOption */
3446
3447         switch (Printer->printer_type) {
3448                 case SPLHND_SERVER:
3449                         result = printserver_notify_info(p, r->in.handle,
3450                                                          info, p->mem_ctx);
3451                         break;
3452
3453                 case SPLHND_PRINTER:
3454                         result = printer_notify_info(p, r->in.handle,
3455                                                      info, p->mem_ctx);
3456                         break;
3457         }
3458
3459         Printer->notify.fnpcn = false;
3460
3461 done:
3462         return result;
3463 }
3464
3465 /********************************************************************
3466  * construct_printer_info_0
3467  * fill a printer_info_0 struct
3468  ********************************************************************/
3469
3470 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3471                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3472                                       struct spoolss_PrinterInfo0 *r,
3473                                       int snum)
3474 {
3475         int count;
3476         counter_printer_0 *session_counter;
3477         time_t setuptime;
3478         print_status_struct status;
3479
3480         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3481         W_ERROR_HAVE_NO_MEMORY(r->printername);
3482
3483         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3484         W_ERROR_HAVE_NO_MEMORY(r->servername);
3485
3486         count = print_queue_length(snum, &status);
3487
3488         /* check if we already have a counter for this printer */
3489         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3490                 if (session_counter->snum == snum)
3491                         break;
3492         }
3493
3494         /* it's the first time, add it to the list */
3495         if (session_counter == NULL) {
3496                 session_counter = SMB_MALLOC_P(counter_printer_0);
3497                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3498                 ZERO_STRUCTP(session_counter);
3499                 session_counter->snum           = snum;
3500                 session_counter->counter        = 0;
3501                 DLIST_ADD(counter_list, session_counter);
3502         }
3503
3504         /* increment it */
3505         session_counter->counter++;
3506
3507         r->cjobs                        = count;
3508         r->total_jobs                   = 0;
3509         r->total_bytes                  = 0;
3510
3511         setuptime = (time_t)ntprinter->info_2->setuptime;
3512
3513         init_systemtime(&r->time, gmtime(&setuptime));
3514
3515         /* JFM:
3516          * the global_counter should be stored in a TDB as it's common to all the clients
3517          * and should be zeroed on samba startup
3518          */
3519         r->global_counter               = session_counter->counter;
3520         r->total_pages                  = 0;
3521         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3522         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3523         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3524         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3525         r->spooling                     = 0;
3526         r->max_spooling                 = 0;
3527         r->session_counter              = session_counter->counter;
3528         r->num_error_out_of_paper       = 0x0;
3529         r->num_error_not_ready          = 0x0;          /* number of print failure */
3530         r->job_error                    = 0x0;
3531         r->number_of_processors         = 0x1;
3532         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3533         r->high_part_total_bytes        = 0x0;
3534         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3535         r->last_error                   = WERR_OK;
3536         r->status                       = nt_printq_status(status.status);
3537         r->enumerate_network_printers   = 0x0;
3538         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3539         r->processor_architecture       = 0x0;
3540         r->processor_level              = 0x6;          /* 6  ???*/
3541         r->ref_ic                       = 0;
3542         r->reserved2                    = 0;
3543         r->reserved3                    = 0;
3544
3545         return WERR_OK;
3546 }
3547
3548 /****************************************************************************
3549  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3550  should be valid upon entry
3551 ****************************************************************************/
3552
3553 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3554                                     struct spoolss_DeviceMode *r,
3555                                     const NT_DEVICEMODE *ntdevmode)
3556 {
3557         if (!r || !ntdevmode) {
3558                 return WERR_INVALID_PARAM;
3559         }
3560
3561         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3562         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3563
3564         r->specversion          = ntdevmode->specversion;
3565         r->driverversion        = ntdevmode->driverversion;
3566         r->size                 = ntdevmode->size;
3567         r->__driverextra_length = ntdevmode->driverextra;
3568         r->fields               = ntdevmode->fields;
3569
3570         r->orientation          = ntdevmode->orientation;
3571         r->papersize            = ntdevmode->papersize;
3572         r->paperlength          = ntdevmode->paperlength;
3573         r->paperwidth           = ntdevmode->paperwidth;
3574         r->scale                = ntdevmode->scale;
3575         r->copies               = ntdevmode->copies;
3576         r->defaultsource        = ntdevmode->defaultsource;
3577         r->printquality         = ntdevmode->printquality;
3578         r->color                = ntdevmode->color;
3579         r->duplex               = ntdevmode->duplex;
3580         r->yresolution          = ntdevmode->yresolution;
3581         r->ttoption             = ntdevmode->ttoption;
3582         r->collate              = ntdevmode->collate;
3583
3584         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3585         W_ERROR_HAVE_NO_MEMORY(r->formname);
3586
3587         r->logpixels            = ntdevmode->logpixels;
3588         r->bitsperpel           = ntdevmode->bitsperpel;
3589         r->pelswidth            = ntdevmode->pelswidth;
3590         r->pelsheight           = ntdevmode->pelsheight;
3591         r->displayflags         = ntdevmode->displayflags;
3592         r->displayfrequency     = ntdevmode->displayfrequency;
3593         r->icmmethod            = ntdevmode->icmmethod;
3594         r->icmintent            = ntdevmode->icmintent;
3595         r->mediatype            = ntdevmode->mediatype;
3596         r->dithertype           = ntdevmode->dithertype;
3597         r->reserved1            = ntdevmode->reserved1;
3598         r->reserved2            = ntdevmode->reserved2;
3599         r->panningwidth         = ntdevmode->panningwidth;
3600         r->panningheight        = ntdevmode->panningheight;
3601
3602         if (ntdevmode->nt_dev_private != NULL) {
3603                 r->driverextra_data = data_blob_talloc(mem_ctx,
3604                         ntdevmode->nt_dev_private,
3605                         ntdevmode->driverextra);
3606                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3607         }
3608
3609         return WERR_OK;
3610 }
3611
3612
3613 /****************************************************************************
3614  Create a spoolss_DeviceMode struct. Returns talloced memory.
3615 ****************************************************************************/
3616
3617 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3618                                               const char *servicename)
3619 {
3620         WERROR result;
3621         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3622         struct spoolss_DeviceMode *devmode = NULL;
3623
3624         DEBUG(7,("construct_dev_mode\n"));
3625
3626         DEBUGADD(8,("getting printer characteristics\n"));
3627
3628         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3629                 return NULL;
3630
3631         if (!printer->info_2->devmode) {
3632                 DEBUG(5, ("BONG! There was no device mode!\n"));
3633                 goto done;
3634         }
3635
3636         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3637         if (!devmode) {
3638                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3639                 goto done;
3640         }
3641
3642         DEBUGADD(8,("loading DEVICEMODE\n"));
3643
3644         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3645         if (!W_ERROR_IS_OK(result)) {
3646                 TALLOC_FREE(devmode);
3647         }
3648
3649 done:
3650         free_a_printer(&printer,2);
3651
3652         return devmode;
3653 }
3654
3655 /********************************************************************
3656  * construct_printer_info1
3657  * fill a spoolss_PrinterInfo1 struct
3658 ********************************************************************/
3659
3660 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3661                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3662                                       uint32_t flags,
3663                                       struct spoolss_PrinterInfo1 *r,
3664                                       int snum)
3665 {
3666         r->flags                = flags;
3667
3668         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3669                                                   ntprinter->info_2->printername,
3670                                                   ntprinter->info_2->drivername,
3671                                                   ntprinter->info_2->location);
3672         W_ERROR_HAVE_NO_MEMORY(r->description);
3673
3674         if (*ntprinter->info_2->comment == '\0') {
3675                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3676         } else {
3677                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3678         }
3679         W_ERROR_HAVE_NO_MEMORY(r->comment);
3680
3681         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3682         W_ERROR_HAVE_NO_MEMORY(r->name);
3683
3684         return WERR_OK;
3685 }
3686
3687 /********************************************************************
3688  * construct_printer_info2
3689  * fill a spoolss_PrinterInfo2 struct
3690 ********************************************************************/
3691
3692 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3693                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3694                                       struct spoolss_PrinterInfo2 *r,
3695                                       int snum)
3696 {
3697         int count;
3698
3699         print_status_struct status;
3700
3701         count = print_queue_length(snum, &status);
3702
3703         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3704         W_ERROR_HAVE_NO_MEMORY(r->servername);
3705         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3706         W_ERROR_HAVE_NO_MEMORY(r->printername);
3707         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3708         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3709         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3710         W_ERROR_HAVE_NO_MEMORY(r->portname);
3711         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3712         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3713
3714         if (*ntprinter->info_2->comment == '\0') {
3715                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3716         } else {
3717                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3718         }
3719         W_ERROR_HAVE_NO_MEMORY(r->comment);
3720
3721         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3722         W_ERROR_HAVE_NO_MEMORY(r->location);
3723         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3724         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3725         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3726         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3727         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3728         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3729         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3730         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3731
3732         r->attributes           = ntprinter->info_2->attributes;
3733
3734         r->priority             = ntprinter->info_2->priority;
3735         r->defaultpriority      = ntprinter->info_2->default_priority;
3736         r->starttime            = ntprinter->info_2->starttime;
3737         r->untiltime            = ntprinter->info_2->untiltime;
3738         r->status               = nt_printq_status(status.status);
3739         r->cjobs                = count;
3740         r->averageppm           = ntprinter->info_2->averageppm;
3741
3742         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3743         if (!r->devmode) {
3744                 DEBUG(8,("Returning NULL Devicemode!\n"));
3745         }
3746
3747         r->secdesc              = NULL;
3748
3749         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3750                 /* don't use talloc_steal() here unless you do a deep steal of all
3751                    the SEC_DESC members */
3752
3753                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3754         }
3755
3756         return WERR_OK;
3757 }
3758
3759 /********************************************************************
3760  * construct_printer_info3
3761  * fill a spoolss_PrinterInfo3 struct
3762  ********************************************************************/
3763
3764 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3765                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3766                                       struct spoolss_PrinterInfo3 *r,
3767                                       int snum)
3768 {
3769         /* These are the components of the SD we are returning. */
3770
3771         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3772                 /* don't use talloc_steal() here unless you do a deep steal of all
3773                    the SEC_DESC members */
3774
3775                 r->secdesc = dup_sec_desc(mem_ctx,
3776                                           ntprinter->info_2->secdesc_buf->sd);
3777                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3778         }
3779
3780         return WERR_OK;
3781 }
3782
3783 /********************************************************************
3784  * construct_printer_info4
3785  * fill a spoolss_PrinterInfo4 struct
3786  ********************************************************************/
3787
3788 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3789                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3790                                       struct spoolss_PrinterInfo4 *r,
3791                                       int snum)
3792 {
3793         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3794         W_ERROR_HAVE_NO_MEMORY(r->printername);
3795         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3796         W_ERROR_HAVE_NO_MEMORY(r->servername);
3797
3798         r->attributes   = ntprinter->info_2->attributes;
3799
3800         return WERR_OK;
3801 }
3802
3803 /********************************************************************
3804  * construct_printer_info5
3805  * fill a spoolss_PrinterInfo5 struct
3806  ********************************************************************/
3807
3808 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3809                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3810                                       struct spoolss_PrinterInfo5 *r,
3811                                       int snum)
3812 {
3813         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3814         W_ERROR_HAVE_NO_MEMORY(r->printername);
3815         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3816         W_ERROR_HAVE_NO_MEMORY(r->portname);
3817
3818         r->attributes   = ntprinter->info_2->attributes;
3819
3820         /* these two are not used by NT+ according to MSDN */
3821
3822         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3823         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3824
3825         return WERR_OK;
3826 }
3827
3828 /********************************************************************
3829  * construct_printer_info_6
3830  * fill a spoolss_PrinterInfo6 struct
3831  ********************************************************************/
3832
3833 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3834                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3835                                       struct spoolss_PrinterInfo6 *r,
3836                                       int snum)
3837 {
3838         int count;
3839         print_status_struct status;
3840
3841         count = print_queue_length(snum, &status);
3842
3843         r->status = nt_printq_status(status.status);
3844
3845         return WERR_OK;
3846 }
3847
3848 /********************************************************************
3849  * construct_printer_info7
3850  * fill a spoolss_PrinterInfo7 struct
3851  ********************************************************************/
3852
3853 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3854                                       Printer_entry *print_hnd,
3855                                       struct spoolss_PrinterInfo7 *r,
3856                                       int snum)
3857 {
3858         struct GUID guid;
3859
3860         if (is_printer_published(print_hnd, snum, &guid)) {
3861                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3862                 r->action = DSPRINT_PUBLISH;
3863         } else {
3864                 r->guid = talloc_strdup(mem_ctx, "");
3865                 r->action = DSPRINT_UNPUBLISH;
3866         }
3867         W_ERROR_HAVE_NO_MEMORY(r->guid);
3868
3869         return WERR_OK;
3870 }
3871
3872 /********************************************************************
3873  * construct_printer_info8
3874  * fill a spoolss_PrinterInfo8 struct
3875  ********************************************************************/
3876
3877 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3878                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3879                                       struct spoolss_DeviceModeInfo *r,
3880                                       int snum)
3881 {
3882         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3883         if (!r->devmode) {
3884                 DEBUG(8,("Returning NULL Devicemode!\n"));
3885         }
3886
3887         return WERR_OK;
3888 }
3889
3890
3891 /********************************************************************
3892 ********************************************************************/
3893
3894 static bool snum_is_shared_printer(int snum)
3895 {
3896         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3897 }
3898
3899 /********************************************************************
3900  Spoolss_enumprinters.
3901 ********************************************************************/
3902
3903 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3904                                            uint32_t level,
3905                                            uint32_t flags,
3906                                            union spoolss_PrinterInfo **info_p,
3907                                            uint32_t *count_p)
3908 {
3909         int snum;
3910         int n_services = lp_numservices();
3911         union spoolss_PrinterInfo *info = NULL;
3912         uint32_t count = 0;
3913         WERROR result = WERR_OK;
3914
3915         *count_p = 0;
3916         *info_p = NULL;
3917
3918         for (snum = 0; snum < n_services; snum++) {
3919
3920                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3921
3922                 if (!snum_is_shared_printer(snum)) {
3923                         continue;
3924                 }
3925
3926                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3927                         lp_servicename(snum), snum));
3928
3929                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3930                                             union spoolss_PrinterInfo,
3931                                             count + 1);
3932                 if (!info) {
3933                         result = WERR_NOMEM;
3934                         goto out;
3935                 }
3936
3937                 result = get_a_printer(NULL, &ntprinter, 2,
3938                                        lp_const_servicename(snum));
3939                 if (!W_ERROR_IS_OK(result)) {
3940                         goto out;
3941                 }
3942
3943                 switch (level) {
3944                 case 0:
3945                         result = construct_printer_info0(info, ntprinter,
3946                                                          &info[count].info0, snum);
3947                         break;
3948                 case 1:
3949                         result = construct_printer_info1(info, ntprinter, flags,
3950                                                          &info[count].info1, snum);
3951                         break;
3952                 case 2:
3953                         result = construct_printer_info2(info, ntprinter,
3954                                                          &info[count].info2, snum);
3955                         break;
3956                 case 4:
3957                         result = construct_printer_info4(info, ntprinter,
3958                                                          &info[count].info4, snum);
3959                         break;
3960                 case 5:
3961                         result = construct_printer_info5(info, ntprinter,
3962                                                          &info[count].info5, snum);
3963                         break;
3964
3965                 default:
3966                         result = WERR_UNKNOWN_LEVEL;
3967                         free_a_printer(&ntprinter, 2);
3968                         goto out;
3969                 }
3970
3971                 free_a_printer(&ntprinter, 2);
3972                 if (!W_ERROR_IS_OK(result)) {
3973                         goto out;
3974                 }
3975
3976                 count++;
3977         }
3978
3979         *count_p = count;
3980         *info_p = info;
3981
3982  out:
3983         if (!W_ERROR_IS_OK(result)) {
3984                 TALLOC_FREE(info);
3985                 return result;
3986         }
3987
3988         *info_p = info;
3989
3990         return WERR_OK;
3991 }
3992
3993 /********************************************************************
3994  * handle enumeration of printers at level 0
3995  ********************************************************************/
3996
3997 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3998                                   uint32_t flags,
3999                                   const char *servername,
4000                                   union spoolss_PrinterInfo **info,
4001                                   uint32_t *count)
4002 {
4003         DEBUG(4,("enum_all_printers_info_0\n"));
4004
4005         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4006 }
4007
4008
4009 /********************************************************************
4010 ********************************************************************/
4011
4012 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4013                                        uint32_t flags,
4014                                        union spoolss_PrinterInfo **info,
4015                                        uint32_t *count)
4016 {
4017         DEBUG(4,("enum_all_printers_info_1\n"));
4018
4019         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4020 }
4021
4022 /********************************************************************
4023  enum_all_printers_info_1_local.
4024 *********************************************************************/
4025
4026 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4027                                              union spoolss_PrinterInfo **info,
4028                                              uint32_t *count)
4029 {
4030         DEBUG(4,("enum_all_printers_info_1_local\n"));
4031
4032         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4033 }
4034
4035 /********************************************************************
4036  enum_all_printers_info_1_name.
4037 *********************************************************************/
4038
4039 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4040                                             const char *name,
4041                                             union spoolss_PrinterInfo **info,
4042                                             uint32_t *count)
4043 {
4044         const char *s = name;
4045
4046         DEBUG(4,("enum_all_printers_info_1_name\n"));
4047
4048         if ((name[0] == '\\') && (name[1] == '\\')) {
4049                 s = name + 2;
4050         }
4051
4052         if (!is_myname_or_ipaddr(s)) {
4053                 return WERR_INVALID_NAME;
4054         }
4055
4056         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4057 }
4058
4059 /********************************************************************
4060  enum_all_printers_info_1_network.
4061 *********************************************************************/
4062
4063 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4064                                                const char *name,
4065                                                union spoolss_PrinterInfo **info,
4066                                                uint32_t *count)
4067 {
4068         const char *s = name;
4069
4070         DEBUG(4,("enum_all_printers_info_1_network\n"));
4071
4072         /* If we respond to a enum_printers level 1 on our name with flags
4073            set to PRINTER_ENUM_REMOTE with a list of printers then these
4074            printers incorrectly appear in the APW browse list.
4075            Specifically the printers for the server appear at the workgroup
4076            level where all the other servers in the domain are
4077            listed. Windows responds to this call with a
4078            WERR_CAN_NOT_COMPLETE so we should do the same. */
4079
4080         if (name[0] == '\\' && name[1] == '\\') {
4081                  s = name + 2;
4082         }
4083
4084         if (is_myname_or_ipaddr(s)) {
4085                  return WERR_CAN_NOT_COMPLETE;
4086         }
4087
4088         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4089 }
4090
4091 /********************************************************************
4092  * api_spoolss_enumprinters
4093  *
4094  * called from api_spoolss_enumprinters (see this to understand)
4095  ********************************************************************/
4096
4097 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4098                                        union spoolss_PrinterInfo **info,
4099                                        uint32_t *count)
4100 {
4101         DEBUG(4,("enum_all_printers_info_2\n"));
4102
4103         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4104 }
4105
4106 /********************************************************************
4107  * handle enumeration of printers at level 1
4108  ********************************************************************/
4109
4110 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4111                                   uint32_t flags,
4112                                   const char *name,
4113                                   union spoolss_PrinterInfo **info,
4114                                   uint32_t *count)
4115 {
4116         /* Not all the flags are equals */
4117
4118         if (flags & PRINTER_ENUM_LOCAL) {
4119                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4120         }
4121
4122         if (flags & PRINTER_ENUM_NAME) {
4123                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4124         }
4125
4126         if (flags & PRINTER_ENUM_NETWORK) {
4127                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4128         }
4129
4130         return WERR_OK; /* NT4sp5 does that */
4131 }
4132
4133 /********************************************************************
4134  * handle enumeration of printers at level 2
4135  ********************************************************************/
4136
4137 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4138                                   uint32_t flags,
4139                                   const char *servername,
4140                                   union spoolss_PrinterInfo **info,
4141                                   uint32_t *count)
4142 {
4143         if (flags & PRINTER_ENUM_LOCAL) {
4144                 return enum_all_printers_info_2(mem_ctx, info, count);
4145         }
4146
4147         if (flags & PRINTER_ENUM_NAME) {
4148                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4149                         return WERR_INVALID_NAME;
4150                 }
4151
4152                 return enum_all_printers_info_2(mem_ctx, info, count);
4153         }
4154
4155         if (flags & PRINTER_ENUM_REMOTE) {
4156                 return WERR_UNKNOWN_LEVEL;
4157         }
4158
4159         return WERR_OK;
4160 }
4161
4162 /********************************************************************
4163  * handle enumeration of printers at level 4
4164  ********************************************************************/
4165
4166 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4167                                   uint32_t flags,
4168                                   const char *servername,
4169                                   union spoolss_PrinterInfo **info,
4170                                   uint32_t *count)
4171 {
4172         DEBUG(4,("enum_all_printers_info_4\n"));
4173
4174         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4175 }
4176
4177
4178 /********************************************************************
4179  * handle enumeration of printers at level 5
4180  ********************************************************************/
4181
4182 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4183                                   uint32_t flags,
4184                                   const char *servername,
4185                                   union spoolss_PrinterInfo **info,
4186                                   uint32_t *count)
4187 {
4188         DEBUG(4,("enum_all_printers_info_5\n"));
4189
4190         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4191 }
4192
4193 /****************************************************************
4194  _spoolss_EnumPrinters
4195 ****************************************************************/
4196
4197 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4198                              struct spoolss_EnumPrinters *r)
4199 {
4200         const char *name = NULL;
4201         WERROR result;
4202
4203         /* that's an [in out] buffer */
4204
4205         if (!r->in.buffer && (r->in.offered != 0)) {
4206                 return WERR_INVALID_PARAM;
4207         }
4208
4209         DEBUG(4,("_spoolss_EnumPrinters\n"));
4210
4211         *r->out.needed = 0;
4212         *r->out.count = 0;
4213         *r->out.info = NULL;
4214
4215         /*
4216          * Level 1:
4217          *          flags==PRINTER_ENUM_NAME
4218          *           if name=="" then enumerates all printers
4219          *           if name!="" then enumerate the printer
4220          *          flags==PRINTER_ENUM_REMOTE
4221          *          name is NULL, enumerate printers
4222          * Level 2: name!="" enumerates printers, name can't be NULL
4223          * Level 3: doesn't exist
4224          * Level 4: does a local registry lookup
4225          * Level 5: same as Level 2
4226          */
4227
4228         if (r->in.server) {
4229                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4230                 W_ERROR_HAVE_NO_MEMORY(name);
4231         }
4232
4233         switch (r->in.level) {
4234         case 0:
4235                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4236                                              r->out.info, r->out.count);
4237                 break;
4238         case 1:
4239                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4240                                              r->out.info, r->out.count);
4241                 break;
4242         case 2:
4243                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4244                                              r->out.info, r->out.count);
4245                 break;
4246         case 4:
4247                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4248                                              r->out.info, r->out.count);
4249                 break;
4250         case 5:
4251                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4252                                              r->out.info, r->out.count);
4253                 break;
4254         default:
4255                 return WERR_UNKNOWN_LEVEL;
4256         }
4257
4258         if (!W_ERROR_IS_OK(result)) {
4259                 return result;
4260         }
4261
4262         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4263                                                      spoolss_EnumPrinters, 
4264                                                      *r->out.info, r->in.level,
4265                                                      *r->out.count);
4266         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4267         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4268
4269         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4270 }
4271
4272 /****************************************************************
4273  _spoolss_GetPrinter
4274 ****************************************************************/
4275
4276 WERROR _spoolss_GetPrinter(pipes_struct *p,
4277                            struct spoolss_GetPrinter *r)
4278 {
4279         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4280         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4281         WERROR result = WERR_OK;
4282
4283         int snum;
4284
4285         /* that's an [in out] buffer */
4286
4287         if (!r->in.buffer && (r->in.offered != 0)) {
4288                 return WERR_INVALID_PARAM;
4289         }
4290
4291         *r->out.needed = 0;
4292
4293         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4294                 return WERR_BADFID;
4295         }
4296
4297         result = get_a_printer(Printer, &ntprinter, 2,
4298                                lp_const_servicename(snum));
4299         if (!W_ERROR_IS_OK(result)) {
4300                 return result;
4301         }
4302
4303         switch (r->in.level) {
4304         case 0:
4305                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4306                                                  &r->out.info->info0, snum);
4307                 break;
4308         case 1:
4309                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4310                                                  PRINTER_ENUM_ICON8,
4311                                                  &r->out.info->info1, snum);
4312                 break;
4313         case 2:
4314                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4315                                                  &r->out.info->info2, snum);
4316                 break;
4317         case 3:
4318                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4319                                                  &r->out.info->info3, snum);
4320                 break;
4321         case 4:
4322                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4323                                                  &r->out.info->info4, snum);
4324                 break;
4325         case 5:
4326                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4327                                                  &r->out.info->info5, snum);
4328                 break;
4329         case 6:
4330                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4331                                                  &r->out.info->info6, snum);
4332                 break;
4333         case 7:
4334                 result = construct_printer_info7(p->mem_ctx, Printer,
4335                                                  &r->out.info->info7, snum);
4336                 break;
4337         case 8:
4338                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4339                                                  &r->out.info->info8, snum);
4340                 break;
4341         default:
4342                 result = WERR_UNKNOWN_LEVEL;
4343                 break;
4344         }
4345
4346         free_a_printer(&ntprinter, 2);
4347
4348         if (!W_ERROR_IS_OK(result)) {
4349                 TALLOC_FREE(r->out.info);
4350                 return result;
4351         }
4352
4353         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4354                                                r->out.info, r->in.level);
4355         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4356
4357         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4358 }
4359
4360 /********************************************************************
4361  ********************************************************************/
4362
4363 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4364                                                   const char **string_array,
4365                                                   const char *cservername)
4366 {
4367         int i, num_strings = 0;
4368         const char **array = NULL;
4369
4370         if (!string_array) {
4371                 return NULL;
4372         }
4373
4374         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4375
4376                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4377                                                   cservername, string_array[i]);
4378                 if (!str) {
4379                         TALLOC_FREE(array);
4380                         return NULL;
4381                 }
4382
4383
4384                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4385                         TALLOC_FREE(array);
4386                         return NULL;
4387                 }
4388         }
4389
4390         if (i > 0) {
4391                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4392                              &array, &num_strings);
4393         }
4394
4395         return array;
4396 }
4397
4398 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4399         do { \
4400                 if (in && strlen(in)) { \
4401                         out = talloc_strdup(mem_ctx, in); \
4402                         W_ERROR_HAVE_NO_MEMORY(out); \
4403                 } else { \
4404                         out = NULL; \
4405                 } \
4406         } while (0);
4407
4408 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4409         do { \
4410                 if (in && strlen(in)) { \
4411                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4412                 } else { \
4413                         out = talloc_strdup(mem_ctx, ""); \
4414                 } \
4415                 W_ERROR_HAVE_NO_MEMORY(out); \
4416         } while (0);
4417
4418 /********************************************************************
4419  * fill a spoolss_DriverInfo1 struct
4420  ********************************************************************/
4421
4422 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4423                                         struct spoolss_DriverInfo1 *r,
4424                                         const struct spoolss_DriverInfo8 *driver,
4425                                         const char *servername)
4426 {
4427         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4428         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4429
4430         return WERR_OK;
4431 }
4432
4433 /********************************************************************
4434  * fill a spoolss_DriverInfo2 struct
4435  ********************************************************************/
4436
4437 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4438                                         struct spoolss_DriverInfo2 *r,
4439                                         const struct spoolss_DriverInfo8 *driver,
4440                                         const char *servername)
4441
4442 {
4443         const char *cservername = canon_servername(servername);
4444
4445         r->version              = driver->version;
4446
4447         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4448         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4449         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4450         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4451
4452         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4453                                driver->driver_path,
4454                                r->driver_path);
4455
4456         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4457                                driver->data_file,
4458                                r->data_file);
4459
4460         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4461                                driver->config_file,
4462                                r->config_file);
4463
4464         return WERR_OK;
4465 }
4466
4467 /********************************************************************
4468  * fill a spoolss_DriverInfo3 struct
4469  ********************************************************************/
4470
4471 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4472                                         struct spoolss_DriverInfo3 *r,
4473                                         const struct spoolss_DriverInfo8 *driver,
4474                                         const char *servername)
4475 {
4476         const char *cservername = canon_servername(servername);
4477
4478         r->version              = driver->version;
4479
4480         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4481         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4482         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4483         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4484
4485         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4486                                driver->driver_path,
4487                                r->driver_path);
4488
4489         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4490                                driver->data_file,
4491                                r->data_file);
4492
4493         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4494                                driver->config_file,
4495                                r->config_file);
4496
4497         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4498                                driver->help_file,
4499                                r->help_file);
4500
4501         FILL_DRIVER_STRING(mem_ctx,
4502                            driver->monitor_name,
4503                            r->monitor_name);
4504
4505         FILL_DRIVER_STRING(mem_ctx,
4506                            driver->default_datatype,
4507                            r->default_datatype);
4508
4509         r->dependent_files = string_array_from_driver_info(mem_ctx,
4510                                                            driver->dependent_files,
4511                                                            cservername);
4512         return WERR_OK;
4513 }
4514
4515 /********************************************************************
4516  * fill a spoolss_DriverInfo4 struct
4517  ********************************************************************/
4518
4519 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4520                                         struct spoolss_DriverInfo4 *r,
4521                                         const struct spoolss_DriverInfo8 *driver,
4522                                         const char *servername)
4523 {
4524         const char *cservername = canon_servername(servername);
4525
4526         r->version              = driver->version;
4527
4528         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4529         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4530         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4531         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4532
4533         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4534                                driver->driver_path,
4535                                r->driver_path);
4536
4537         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4538                                driver->data_file,
4539                                r->data_file);
4540
4541         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4542                                driver->config_file,
4543                                r->config_file);
4544
4545         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4546                                driver->help_file,
4547                                r->help_file);
4548
4549         r->dependent_files = string_array_from_driver_info(mem_ctx,
4550                                                            driver->dependent_files,
4551                                                            cservername);
4552
4553         FILL_DRIVER_STRING(mem_ctx,
4554                            driver->monitor_name,
4555                            r->monitor_name);
4556
4557         FILL_DRIVER_STRING(mem_ctx,
4558                            driver->default_datatype,
4559                            r->default_datatype);
4560
4561         r->previous_names = string_array_from_driver_info(mem_ctx,
4562                                                           driver->previous_names,
4563                                                           cservername);
4564
4565         return WERR_OK;
4566 }
4567
4568 /********************************************************************
4569  * fill a spoolss_DriverInfo5 struct
4570  ********************************************************************/
4571
4572 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4573                                         struct spoolss_DriverInfo5 *r,
4574                                         const struct spoolss_DriverInfo8 *driver,
4575                                         const char *servername)
4576 {
4577         const char *cservername = canon_servername(servername);
4578
4579         r->version              = driver->version;
4580
4581         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4582         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4583         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4584         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4585
4586         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4587                                driver->driver_path,
4588                                r->driver_path);
4589
4590         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4591                                driver->data_file,
4592                                r->data_file);
4593
4594         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4595                                driver->config_file,
4596                                r->config_file);
4597
4598         r->driver_attributes    = 0;
4599         r->config_version       = 0;
4600         r->driver_version       = 0;
4601
4602         return WERR_OK;
4603 }
4604 /********************************************************************
4605  * fill a spoolss_DriverInfo6 struct
4606  ********************************************************************/
4607
4608 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4609                                         struct spoolss_DriverInfo6 *r,
4610                                         const struct spoolss_DriverInfo8 *driver,
4611                                         const char *servername)
4612 {
4613         const char *cservername = canon_servername(servername);
4614
4615         r->version              = driver->version;
4616
4617         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4618         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4619         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4620         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4621
4622         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4623                                driver->driver_path,
4624                                r->driver_path);
4625
4626         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4627                                driver->data_file,
4628                                r->data_file);
4629
4630         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4631                                driver->config_file,
4632                                r->config_file);
4633
4634         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4635                                driver->help_file,
4636                                r->help_file);
4637
4638         FILL_DRIVER_STRING(mem_ctx,
4639                            driver->monitor_name,
4640                            r->monitor_name);
4641
4642         FILL_DRIVER_STRING(mem_ctx,
4643                            driver->default_datatype,
4644                            r->default_datatype);
4645
4646         r->dependent_files = string_array_from_driver_info(mem_ctx,
4647                                                            driver->dependent_files,
4648                                                            cservername);
4649         r->previous_names = string_array_from_driver_info(mem_ctx,
4650                                                           driver->previous_names,
4651                                                           cservername);
4652
4653         r->driver_date          = driver->driver_date;
4654         r->driver_version       = driver->driver_version;
4655
4656         FILL_DRIVER_STRING(mem_ctx,
4657                            driver->manufacturer_name,
4658                            r->manufacturer_name);
4659         FILL_DRIVER_STRING(mem_ctx,
4660                            driver->manufacturer_url,
4661                            r->manufacturer_url);
4662         FILL_DRIVER_STRING(mem_ctx,
4663                            driver->hardware_id,
4664                            r->hardware_id);
4665         FILL_DRIVER_STRING(mem_ctx,
4666                            driver->provider,
4667                            r->provider);
4668
4669         return WERR_OK;
4670 }
4671
4672 /********************************************************************
4673  * fill a spoolss_DriverInfo8 struct
4674  ********************************************************************/
4675
4676 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4677                                         struct spoolss_DriverInfo8 *r,
4678                                         const struct spoolss_DriverInfo8 *driver,
4679                                         const char *servername)
4680 {
4681         const char *cservername = canon_servername(servername);
4682
4683         r->version              = driver->version;
4684
4685         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4686         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4687         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4688         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4689
4690         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4691                                driver->driver_path,
4692                                r->driver_path);
4693
4694         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4695                                driver->data_file,
4696                                r->data_file);
4697
4698         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4699                                driver->config_file,
4700                                r->config_file);
4701
4702         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4703                                driver->help_file,
4704                                r->help_file);
4705
4706         FILL_DRIVER_STRING(mem_ctx,
4707                            driver->monitor_name,
4708                            r->monitor_name);
4709
4710         FILL_DRIVER_STRING(mem_ctx,
4711                            driver->default_datatype,
4712                            r->default_datatype);
4713
4714         r->dependent_files = string_array_from_driver_info(mem_ctx,
4715                                                            driver->dependent_files,
4716                                                            cservername);
4717         r->previous_names = string_array_from_driver_info(mem_ctx,
4718                                                           driver->previous_names,
4719                                                           cservername);
4720
4721         r->driver_date          = driver->driver_date;
4722         r->driver_version       = driver->driver_version;
4723
4724         FILL_DRIVER_STRING(mem_ctx,
4725                            driver->manufacturer_name,
4726                            r->manufacturer_name);
4727         FILL_DRIVER_STRING(mem_ctx,
4728                            driver->manufacturer_url,
4729                            r->manufacturer_url);
4730         FILL_DRIVER_STRING(mem_ctx,
4731                            driver->hardware_id,
4732                            r->hardware_id);
4733         FILL_DRIVER_STRING(mem_ctx,
4734                            driver->provider,
4735                            r->provider);
4736
4737         FILL_DRIVER_STRING(mem_ctx,
4738                            driver->print_processor,
4739                            r->print_processor);
4740         FILL_DRIVER_STRING(mem_ctx,
4741                            driver->vendor_setup,
4742                            r->vendor_setup);
4743
4744         r->color_profiles = string_array_from_driver_info(mem_ctx,
4745                                                           driver->color_profiles,
4746                                                           cservername);
4747
4748         FILL_DRIVER_STRING(mem_ctx,
4749                            driver->inf_path,
4750                            r->inf_path);
4751
4752         r->printer_driver_attributes    = driver->printer_driver_attributes;
4753
4754         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4755                                                                     driver->core_driver_dependencies,
4756                                                                     cservername);
4757
4758         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4759         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4760
4761         return WERR_OK;
4762 }
4763
4764 #if 0 /* disabled until marshalling issues are resolved - gd */
4765 /********************************************************************
4766  ********************************************************************/
4767
4768 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4769                                           struct spoolss_DriverFileInfo *r,
4770                                           const char *cservername,
4771                                           const char *file_name,
4772                                           enum spoolss_DriverFileType file_type,
4773                                           uint32_t file_version)
4774 {
4775         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4776                                           cservername, file_name);
4777         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4778         r->file_type    = file_type;
4779         r->file_version = file_version;
4780
4781         return WERR_OK;
4782 }
4783
4784 /********************************************************************
4785  ********************************************************************/
4786
4787 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4788                                                  const struct spoolss_DriverInfo8 *driver,
4789                                                  const char *cservername,
4790                                                  struct spoolss_DriverFileInfo **info_p,
4791                                                  uint32_t *count_p)
4792 {
4793         struct spoolss_DriverFileInfo *info = NULL;
4794         uint32_t count = 0;
4795         WERROR result;
4796         uint32_t i;
4797
4798         *info_p = NULL;
4799         *count_p = 0;
4800
4801         if (strlen(driver->driver_path)) {
4802                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4803                                             struct spoolss_DriverFileInfo,
4804                                             count + 1);
4805                 W_ERROR_HAVE_NO_MEMORY(info);
4806                 result = fill_spoolss_DriverFileInfo(info,
4807                                                      &info[count],
4808                                                      cservername,
4809                                                      driver->driver_path,
4810                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4811                                                      0);
4812                 W_ERROR_NOT_OK_RETURN(result);
4813                 count++;
4814         }
4815
4816         if (strlen(driver->config_file)) {
4817                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4818                                             struct spoolss_DriverFileInfo,
4819                                             count + 1);
4820                 W_ERROR_HAVE_NO_MEMORY(info);
4821                 result = fill_spoolss_DriverFileInfo(info,
4822                                                      &info[count],
4823                                                      cservername,
4824                                                      driver->config_file,
4825                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4826                                                      0);
4827                 W_ERROR_NOT_OK_RETURN(result);
4828                 count++;
4829         }
4830
4831         if (strlen(driver->data_file)) {
4832                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4833                                             struct spoolss_DriverFileInfo,
4834                                             count + 1);
4835                 W_ERROR_HAVE_NO_MEMORY(info);
4836                 result = fill_spoolss_DriverFileInfo(info,
4837                                                      &info[count],
4838                                                      cservername,
4839                                                      driver->data_file,
4840                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4841                                                      0);
4842                 W_ERROR_NOT_OK_RETURN(result);
4843                 count++;
4844         }
4845
4846         if (strlen(driver->help_file)) {
4847                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4848                                             struct spoolss_DriverFileInfo,
4849                                             count + 1);
4850                 W_ERROR_HAVE_NO_MEMORY(info);
4851                 result = fill_spoolss_DriverFileInfo(info,
4852                                                      &info[count],
4853                                                      cservername,
4854                                                      driver->help_file,
4855                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4856                                                      0);
4857                 W_ERROR_NOT_OK_RETURN(result);
4858                 count++;
4859         }
4860
4861         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4862                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4863                                             struct spoolss_DriverFileInfo,
4864                                             count + 1);
4865                 W_ERROR_HAVE_NO_MEMORY(info);
4866                 result = fill_spoolss_DriverFileInfo(info,
4867                                                      &info[count],
4868                                                      cservername,
4869                                                      driver->dependent_files[i],
4870                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4871                                                      0);
4872                 W_ERROR_NOT_OK_RETURN(result);
4873                 count++;
4874         }
4875
4876         *info_p = info;
4877         *count_p = count;
4878
4879         return WERR_OK;
4880 }
4881
4882 /********************************************************************
4883  * fill a spoolss_DriverInfo101 struct
4884  ********************************************************************/
4885
4886 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4887                                           struct spoolss_DriverInfo101 *r,
4888                                           const struct spoolss_DriverInfo8 *driver,
4889                                           const char *servername)
4890 {
4891         const char *cservername = canon_servername(servername);
4892         WERROR result;
4893
4894         r->version              = driver->version;
4895
4896         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4897         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4898         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4899         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4900
4901         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4902                                                     cservername,
4903                                                     &r->file_info,
4904                                                     &r->file_count);
4905         if (!W_ERROR_IS_OK(result)) {
4906                 return result;
4907         }
4908
4909         FILL_DRIVER_STRING(mem_ctx,
4910                            driver->monitor_name,
4911                            r->monitor_name);
4912
4913         FILL_DRIVER_STRING(mem_ctx,
4914                            driver->default_datatype,
4915                            r->default_datatype);
4916
4917         r->previous_names = string_array_from_driver_info(mem_ctx,
4918                                                           driver->previous_names,
4919                                                           cservername);
4920         r->driver_date          = driver->driver_date;
4921         r->driver_version       = driver->driver_version;
4922
4923         FILL_DRIVER_STRING(mem_ctx,
4924                            driver->manufacturer_name,
4925                            r->manufacturer_name);
4926         FILL_DRIVER_STRING(mem_ctx,
4927                            driver->manufacturer_url,
4928                            r->manufacturer_url);
4929         FILL_DRIVER_STRING(mem_ctx,
4930                            driver->hardware_id,
4931                            r->hardware_id);
4932         FILL_DRIVER_STRING(mem_ctx,
4933                            driver->provider,
4934                            r->provider);
4935
4936         return WERR_OK;
4937 }
4938 #endif
4939 /********************************************************************
4940  ********************************************************************/
4941
4942 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4943                                                   uint32_t level,
4944                                                   union spoolss_DriverInfo *r,
4945                                                   int snum,
4946                                                   const char *servername,
4947                                                   const char *architecture,
4948                                                   uint32_t version)
4949 {
4950         NT_PRINTER_INFO_LEVEL *printer = NULL;
4951         struct spoolss_DriverInfo8 *driver;
4952         WERROR result;
4953
4954         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4955
4956         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4957                 win_errstr(result)));
4958
4959         if (!W_ERROR_IS_OK(result)) {
4960                 return WERR_INVALID_PRINTER_NAME;
4961         }
4962
4963         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4964                                       architecture, version);
4965
4966         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4967                 win_errstr(result)));
4968
4969         if (!W_ERROR_IS_OK(result)) {
4970                 /*
4971                  * Is this a W2k client ?
4972                  */
4973
4974                 if (version < 3) {
4975                         free_a_printer(&printer, 2);
4976                         return WERR_UNKNOWN_PRINTER_DRIVER;
4977                 }
4978
4979                 /* Yes - try again with a WinNT driver. */
4980                 version = 2;
4981                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4982                                               architecture, version);
4983                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4984                         win_errstr(result)));
4985                 if (!W_ERROR_IS_OK(result)) {
4986                         free_a_printer(&printer, 2);
4987                         return WERR_UNKNOWN_PRINTER_DRIVER;
4988                 }
4989         }
4990
4991         switch (level) {
4992         case 1:
4993                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4994                 break;
4995         case 2:
4996                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4997                 break;
4998         case 3:
4999                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5000                 break;
5001         case 4:
5002                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5003                 break;
5004         case 5:
5005                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5006                 break;
5007         case 6:
5008                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5009                 break;
5010         case 8:
5011                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5012                 break;
5013 #if 0 /* disabled until marshalling issues are resolved - gd */
5014         case 101:
5015                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5016                 break;
5017 #endif
5018         default:
5019                 result = WERR_UNKNOWN_LEVEL;
5020                 break;
5021         }
5022
5023         free_a_printer(&printer, 2);
5024         free_a_printer_driver(driver);
5025
5026         return result;
5027 }
5028
5029 /****************************************************************
5030  _spoolss_GetPrinterDriver2
5031 ****************************************************************/
5032
5033 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5034                                   struct spoolss_GetPrinterDriver2 *r)
5035 {
5036         Printer_entry *printer;
5037         WERROR result;
5038
5039         const char *servername;
5040         int snum;
5041
5042         /* that's an [in out] buffer */
5043
5044         if (!r->in.buffer && (r->in.offered != 0)) {
5045                 return WERR_INVALID_PARAM;
5046         }
5047
5048         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5049
5050         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5051                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5052                 return WERR_INVALID_PRINTER_NAME;
5053         }
5054
5055         *r->out.needed = 0;
5056         *r->out.server_major_version = 0;
5057         *r->out.server_minor_version = 0;
5058
5059         servername = get_server_name(printer);
5060
5061         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5062                 return WERR_BADFID;
5063         }
5064
5065         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5066                                                      r->out.info, snum,
5067                                                      servername,
5068                                                      r->in.architecture,
5069                                                      r->in.client_major_version);
5070         if (!W_ERROR_IS_OK(result)) {
5071                 TALLOC_FREE(r->out.info);
5072                 return result;
5073         }
5074
5075         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5076                                                r->out.info, r->in.level);
5077         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5078
5079         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5080 }
5081
5082
5083 /****************************************************************
5084  _spoolss_StartPagePrinter
5085 ****************************************************************/
5086
5087 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5088                                  struct spoolss_StartPagePrinter *r)
5089 {
5090         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5091
5092         if (!Printer) {
5093                 DEBUG(3,("_spoolss_StartPagePrinter: "
5094                         "Error in startpageprinter printer handle\n"));
5095                 return WERR_BADFID;
5096         }
5097
5098         Printer->page_started = true;
5099         return WERR_OK;
5100 }
5101
5102 /****************************************************************
5103  _spoolss_EndPagePrinter
5104 ****************************************************************/
5105
5106 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5107                                struct spoolss_EndPagePrinter *r)
5108 {
5109         int snum;
5110
5111         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5112
5113         if (!Printer) {
5114                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5115                         OUR_HANDLE(r->in.handle)));
5116                 return WERR_BADFID;
5117         }
5118
5119         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5120                 return WERR_BADFID;
5121
5122         Printer->page_started = false;
5123         print_job_endpage(snum, Printer->jobid);
5124
5125         return WERR_OK;
5126 }
5127
5128 /****************************************************************
5129  _spoolss_StartDocPrinter
5130 ****************************************************************/
5131
5132 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5133                                 struct spoolss_StartDocPrinter *r)
5134 {
5135         struct spoolss_DocumentInfo1 *info_1;
5136         int snum;
5137         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5138
5139         if (!Printer) {
5140                 DEBUG(2,("_spoolss_StartDocPrinter: "
5141                         "Invalid handle (%s:%u:%u)\n",
5142                         OUR_HANDLE(r->in.handle)));
5143                 return WERR_BADFID;
5144         }
5145
5146         if (r->in.level != 1) {
5147                 return WERR_UNKNOWN_LEVEL;
5148         }
5149
5150         info_1 = r->in.info.info1;
5151
5152         /*
5153          * a nice thing with NT is it doesn't listen to what you tell it.
5154          * when asked to send _only_ RAW datas, it tries to send datas
5155          * in EMF format.
5156          *
5157          * So I add checks like in NT Server ...
5158          */
5159
5160         if (info_1->datatype) {
5161                 if (strcmp(info_1->datatype, "RAW") != 0) {
5162                         *r->out.job_id = 0;
5163                         return WERR_INVALID_DATATYPE;
5164                 }
5165         }
5166
5167         /* get the share number of the printer */
5168         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5169                 return WERR_BADFID;
5170         }
5171
5172         Printer->jobid = print_job_start(p->server_info, snum,
5173                                          info_1->document_name,
5174                                          Printer->nt_devmode);
5175
5176         /* An error occured in print_job_start() so return an appropriate
5177            NT error code. */
5178
5179         if (Printer->jobid == -1) {
5180                 return map_werror_from_unix(errno);
5181         }
5182
5183         Printer->document_started = true;
5184         *r->out.job_id = Printer->jobid;
5185
5186         return WERR_OK;
5187 }
5188
5189 /****************************************************************
5190  _spoolss_EndDocPrinter
5191 ****************************************************************/
5192
5193 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5194                               struct spoolss_EndDocPrinter *r)
5195 {
5196         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5197         int snum;
5198
5199         if (!Printer) {
5200                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5201                         OUR_HANDLE(r->in.handle)));
5202                 return WERR_BADFID;
5203         }
5204
5205         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5206                 return WERR_BADFID;
5207         }
5208
5209         Printer->document_started = false;
5210         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5211         /* error codes unhandled so far ... */
5212
5213         return WERR_OK;
5214 }
5215
5216 /****************************************************************
5217  _spoolss_WritePrinter
5218 ****************************************************************/
5219
5220 WERROR _spoolss_WritePrinter(pipes_struct *p,
5221                              struct spoolss_WritePrinter *r)
5222 {
5223         ssize_t buffer_written;
5224         int snum;
5225         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5226
5227         if (!Printer) {
5228                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5229                         OUR_HANDLE(r->in.handle)));
5230                 *r->out.num_written = r->in._data_size;
5231                 return WERR_BADFID;
5232         }
5233
5234         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5235                 return WERR_BADFID;
5236
5237         buffer_written = print_job_write(snum, Printer->jobid,
5238                                                    (const char *)r->in.data.data,
5239                                                    (SMB_OFF_T)-1,
5240                                                    (size_t)r->in._data_size);
5241         if (buffer_written == (ssize_t)-1) {
5242                 *r->out.num_written = 0;
5243                 if (errno == ENOSPC)
5244                         return WERR_NO_SPOOL_SPACE;
5245                 else
5246                         return WERR_ACCESS_DENIED;
5247         }
5248
5249         *r->out.num_written = r->in._data_size;
5250
5251         return WERR_OK;
5252 }
5253
5254 /********************************************************************
5255  * api_spoolss_getprinter
5256  * called from the spoolss dispatcher
5257  *
5258  ********************************************************************/
5259
5260 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5261                               pipes_struct *p)
5262 {
5263         int snum;
5264         WERROR errcode = WERR_BADFUNC;
5265         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5266
5267         if (!Printer) {
5268                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5269                         OUR_HANDLE(handle)));
5270                 return WERR_BADFID;
5271         }
5272
5273         if (!get_printer_snum(p, handle, &snum, NULL))
5274                 return WERR_BADFID;
5275
5276         switch (command) {
5277         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5278                 errcode = print_queue_pause(p->server_info, snum);
5279                 break;
5280         case SPOOLSS_PRINTER_CONTROL_RESUME:
5281         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5282                 errcode = print_queue_resume(p->server_info, snum);
5283                 break;
5284         case SPOOLSS_PRINTER_CONTROL_PURGE:
5285                 errcode = print_queue_purge(p->server_info, snum);
5286                 break;
5287         default:
5288                 return WERR_UNKNOWN_LEVEL;
5289         }
5290
5291         return errcode;
5292 }
5293
5294
5295 /****************************************************************
5296  _spoolss_AbortPrinter
5297  * From MSDN: "Deletes printer's spool file if printer is configured
5298  * for spooling"
5299 ****************************************************************/
5300
5301 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5302                              struct spoolss_AbortPrinter *r)
5303 {
5304         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5305         int             snum;
5306         WERROR          errcode = WERR_OK;
5307
5308         if (!Printer) {
5309                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5310                         OUR_HANDLE(r->in.handle)));
5311                 return WERR_BADFID;
5312         }
5313
5314         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5315                 return WERR_BADFID;
5316
5317         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5318
5319         return errcode;
5320 }
5321
5322 /********************************************************************
5323  * called by spoolss_api_setprinter
5324  * when updating a printer description
5325  ********************************************************************/
5326
5327 static WERROR update_printer_sec(struct policy_handle *handle,
5328                                  pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5329 {
5330         struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5331         WERROR result;
5332         int snum;
5333
5334         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5335
5336         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5337                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5338                          OUR_HANDLE(handle)));
5339
5340                 result = WERR_BADFID;
5341                 goto done;
5342         }
5343
5344         if (!secdesc_ctr) {
5345                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5346                 result = WERR_INVALID_PARAM;
5347                 goto done;
5348         }
5349
5350         /* Check the user has permissions to change the security
5351            descriptor.  By experimentation with two NT machines, the user
5352            requires Full Access to the printer to change security
5353            information. */
5354
5355         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5356                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5357                 result = WERR_ACCESS_DENIED;
5358                 goto done;
5359         }
5360
5361         /* NT seems to like setting the security descriptor even though
5362            nothing may have actually changed. */
5363
5364         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5365                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5366                 result = WERR_BADFID;
5367                 goto done;
5368         }
5369
5370         if (DEBUGLEVEL >= 10) {
5371                 struct security_acl *the_acl;
5372                 int i;
5373
5374                 the_acl = old_secdesc_ctr->sd->dacl;
5375                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5376                            lp_printername(snum), the_acl->num_aces));
5377
5378                 for (i = 0; i < the_acl->num_aces; i++) {
5379                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5380                                            &the_acl->aces[i].trustee),
5381                                   the_acl->aces[i].access_mask));
5382                 }
5383
5384                 the_acl = secdesc_ctr->sd->dacl;
5385
5386                 if (the_acl) {
5387                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5388                                    lp_printername(snum), the_acl->num_aces));
5389
5390                         for (i = 0; i < the_acl->num_aces; i++) {
5391                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5392                                                    &the_acl->aces[i].trustee),
5393                                            the_acl->aces[i].access_mask));
5394                         }
5395                 } else {
5396                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5397                 }
5398         }
5399
5400         new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5401         if (!new_secdesc_ctr) {
5402                 result = WERR_NOMEM;
5403                 goto done;
5404         }
5405
5406         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5407                 result = WERR_OK;
5408                 goto done;
5409         }
5410
5411         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5412
5413  done:
5414
5415         return result;
5416 }
5417
5418 /********************************************************************
5419  Canonicalize printer info from a client
5420
5421  ATTN: It does not matter what we set the servername to hear
5422  since we do the necessary work in get_a_printer() to set it to
5423  the correct value based on what the client sent in the
5424  _spoolss_open_printer_ex().
5425  ********************************************************************/
5426
5427 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5428 {
5429         fstring printername;
5430         const char *p;
5431
5432         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5433                 "portname=%s drivername=%s comment=%s location=%s\n",
5434                 info->servername, info->printername, info->sharename,
5435                 info->portname, info->drivername, info->comment, info->location));
5436
5437         /* we force some elements to "correct" values */
5438         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5439         fstrcpy(info->sharename, lp_servicename(snum));
5440
5441         /* check to see if we allow printername != sharename */
5442
5443         if ( lp_force_printername(snum) ) {
5444                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5445                         global_myname(), info->sharename );
5446         } else {
5447
5448                 /* make sure printername is in \\server\printername format */
5449
5450                 fstrcpy( printername, info->printername );
5451                 p = printername;
5452                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5453                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5454                                 p++;
5455                 }
5456
5457                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5458                          global_myname(), p );
5459         }
5460
5461         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5462         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5463
5464
5465
5466         return true;
5467 }
5468
5469 /****************************************************************************
5470 ****************************************************************************/
5471
5472 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5473 {
5474         char *cmd = lp_addport_cmd();
5475         char *command = NULL;
5476         int ret;
5477         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5478         bool is_print_op = false;
5479
5480         if ( !*cmd ) {
5481                 return WERR_ACCESS_DENIED;
5482         }
5483
5484         command = talloc_asprintf(ctx,
5485                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5486         if (!command) {
5487                 return WERR_NOMEM;
5488         }
5489
5490         if ( token )
5491                 is_print_op = user_has_privileges( token, &se_printop );
5492
5493         DEBUG(10,("Running [%s]\n", command));
5494
5495         /********* BEGIN SePrintOperatorPrivilege **********/
5496
5497         if ( is_print_op )
5498                 become_root();
5499
5500         ret = smbrun(command, NULL);
5501
5502         if ( is_print_op )
5503                 unbecome_root();
5504
5505         /********* END SePrintOperatorPrivilege **********/
5506
5507         DEBUGADD(10,("returned [%d]\n", ret));
5508
5509         TALLOC_FREE(command);
5510
5511         if ( ret != 0 ) {
5512                 return WERR_ACCESS_DENIED;
5513         }
5514
5515         return WERR_OK;
5516 }
5517
5518 /****************************************************************************
5519 ****************************************************************************/
5520
5521 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5522 {
5523         char *cmd = lp_addprinter_cmd();
5524         char **qlines;
5525         char *command = NULL;
5526         int numlines;
5527         int ret;
5528         int fd;
5529         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5530         bool is_print_op = false;
5531         char *remote_machine = talloc_strdup(ctx, "%m");
5532
5533         if (!remote_machine) {
5534                 return false;
5535         }
5536         remote_machine = talloc_sub_basic(ctx,
5537                                 current_user_info.smb_name,
5538                                 current_user_info.domain,
5539                                 remote_machine);
5540         if (!remote_machine) {
5541                 return false;
5542         }
5543
5544         command = talloc_asprintf(ctx,
5545                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5546                         cmd, printer->info_2->printername, printer->info_2->sharename,
5547                         printer->info_2->portname, printer->info_2->drivername,
5548                         printer->info_2->location, printer->info_2->comment, remote_machine);
5549         if (!command) {
5550                 return false;
5551         }
5552
5553         if ( token )
5554                 is_print_op = user_has_privileges( token, &se_printop );
5555
5556         DEBUG(10,("Running [%s]\n", command));
5557
5558         /********* BEGIN SePrintOperatorPrivilege **********/
5559
5560         if ( is_print_op )
5561                 become_root();
5562
5563         if ( (ret = smbrun(command, &fd)) == 0 ) {
5564                 /* Tell everyone we updated smb.conf. */
5565                 message_send_all(smbd_messaging_context(),
5566                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5567         }
5568
5569         if ( is_print_op )
5570                 unbecome_root();
5571
5572         /********* END SePrintOperatorPrivilege **********/
5573
5574         DEBUGADD(10,("returned [%d]\n", ret));
5575
5576         TALLOC_FREE(command);
5577         TALLOC_FREE(remote_machine);
5578
5579         if ( ret != 0 ) {
5580                 if (fd != -1)
5581                         close(fd);
5582                 return false;
5583         }
5584
5585         /* reload our services immediately */
5586         become_root();
5587         reload_services(false);
5588         unbecome_root();
5589
5590         numlines = 0;
5591         /* Get lines and convert them back to dos-codepage */
5592         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5593         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5594         close(fd);
5595
5596         /* Set the portname to what the script says the portname should be. */
5597         /* but don't require anything to be return from the script exit a good error code */
5598
5599         if (numlines) {
5600                 /* Set the portname to what the script says the portname should be. */
5601                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5602                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5603         }
5604
5605         TALLOC_FREE(qlines);
5606         return true;
5607 }
5608
5609
5610 /********************************************************************
5611  * Called by spoolss_api_setprinter
5612  * when updating a printer description.
5613  ********************************************************************/
5614
5615 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5616                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5617                              struct spoolss_DeviceMode *devmode)
5618 {
5619         int snum;
5620         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5621         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5622         WERROR result;
5623         DATA_BLOB buffer;
5624         fstring asc_buffer;
5625
5626         DEBUG(8,("update_printer\n"));
5627
5628         result = WERR_OK;
5629
5630         if (!Printer) {
5631                 result = WERR_BADFID;
5632                 goto done;
5633         }
5634
5635         if (!get_printer_snum(p, handle, &snum, NULL)) {
5636                 result = WERR_BADFID;
5637                 goto done;
5638         }
5639
5640         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5641             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5642                 result = WERR_BADFID;
5643                 goto done;
5644         }
5645
5646         DEBUGADD(8,("Converting info_2 struct\n"));
5647
5648         /*
5649          * convert_printer_info converts the incoming
5650          * info from the client and overwrites the info
5651          * just read from the tdb in the pointer 'printer'.
5652          */
5653
5654         if (!convert_printer_info(info_ctr, printer)) {
5655                 result =  WERR_NOMEM;
5656                 goto done;
5657         }
5658
5659         if (devmode) {
5660                 /* we have a valid devmode
5661                    convert it and link it*/
5662
5663                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5664                 if (!convert_devicemode(printer->info_2->printername, devmode,
5665                                         &printer->info_2->devmode)) {
5666                         result =  WERR_NOMEM;
5667                         goto done;
5668                 }
5669         }
5670
5671         /* Do sanity check on the requested changes for Samba */
5672
5673         if (!check_printer_ok(printer->info_2, snum)) {
5674                 result = WERR_INVALID_PARAM;
5675                 goto done;
5676         }
5677
5678         /* FIXME!!! If the driver has changed we really should verify that
5679            it is installed before doing much else   --jerry */
5680
5681         /* Check calling user has permission to update printer description */
5682
5683         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5684                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5685                 result = WERR_ACCESS_DENIED;
5686                 goto done;
5687         }
5688
5689         /* Call addprinter hook */
5690         /* Check changes to see if this is really needed */
5691
5692         if ( *lp_addprinter_cmd()
5693                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5694                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5695                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5696                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5697         {
5698                 /* add_printer_hook() will call reload_services() */
5699
5700                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5701                                        printer) ) {
5702                         result = WERR_ACCESS_DENIED;
5703                         goto done;
5704                 }
5705         }
5706
5707         /*
5708          * When a *new* driver is bound to a printer, the drivername is used to
5709          * lookup previously saved driver initialization info, which is then
5710          * bound to the printer, simulating what happens in the Windows arch.
5711          */
5712         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5713         {
5714                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5715                         printer->info_2->drivername));
5716
5717                 notify_printer_driver(snum, printer->info_2->drivername);
5718         }
5719
5720         /*
5721          * flag which changes actually occured.  This is a small subset of
5722          * all the possible changes.  We also have to update things in the
5723          * DsSpooler key.
5724          */
5725
5726         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5727                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5728                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5729                         REG_SZ, buffer.data, buffer.length);
5730
5731                 notify_printer_comment(snum, printer->info_2->comment);
5732         }
5733
5734         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5735                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5736                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5737                         REG_SZ, buffer.data, buffer.length);
5738
5739                 notify_printer_sharename(snum, printer->info_2->sharename);
5740         }
5741
5742         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5743                 char *pname;
5744
5745                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5746                         pname++;
5747                 else
5748                         pname = printer->info_2->printername;
5749
5750
5751                 push_reg_sz(talloc_tos(), &buffer, pname);
5752                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5753                         REG_SZ, buffer.data, buffer.length);
5754
5755                 notify_printer_printername( snum, pname );
5756         }
5757
5758         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5759                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5760                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5761                         REG_SZ, buffer.data, buffer.length);
5762
5763                 notify_printer_port(snum, printer->info_2->portname);
5764         }
5765
5766         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5767                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5768                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5769                         REG_SZ, buffer.data, buffer.length);
5770
5771                 notify_printer_location(snum, printer->info_2->location);
5772         }
5773
5774         /* here we need to update some more DsSpooler keys */
5775         /* uNCName, serverName, shortServerName */
5776
5777         push_reg_sz(talloc_tos(), &buffer, global_myname());
5778         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5779                 REG_SZ, buffer.data, buffer.length);
5780         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5781                 REG_SZ, buffer.data, buffer.length);
5782
5783         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5784                  global_myname(), printer->info_2->sharename );
5785         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5786         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5787                 REG_SZ, buffer.data, buffer.length);
5788
5789         /* Update printer info */
5790         result = mod_a_printer(printer, 2);
5791
5792 done:
5793         free_a_printer(&printer, 2);
5794         free_a_printer(&old_printer, 2);
5795
5796
5797         return result;
5798 }
5799
5800 /****************************************************************************
5801 ****************************************************************************/
5802 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5803                                            struct policy_handle *handle,
5804                                            struct spoolss_SetPrinterInfo7 *info7)
5805 {
5806 #ifdef HAVE_ADS
5807         int snum;
5808         Printer_entry *Printer;
5809
5810         if ( lp_security() != SEC_ADS ) {
5811                 return WERR_UNKNOWN_LEVEL;
5812         }
5813
5814         Printer = find_printer_index_by_hnd(p, handle);
5815
5816         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5817
5818         if (!Printer)
5819                 return WERR_BADFID;
5820
5821         if (!get_printer_snum(p, handle, &snum, NULL))
5822                 return WERR_BADFID;
5823
5824         nt_printer_publish(Printer, snum, info7->action);
5825
5826         return WERR_OK;
5827 #else
5828         return WERR_UNKNOWN_LEVEL;
5829 #endif
5830 }
5831
5832 /********************************************************************
5833  ********************************************************************/
5834
5835 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5836                                      struct spoolss_DeviceMode *devmode)
5837 {
5838         int snum;
5839         NT_PRINTER_INFO_LEVEL *printer = NULL;
5840         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5841         WERROR result;
5842
5843         DEBUG(8,("update_printer_devmode\n"));
5844
5845         result = WERR_OK;
5846
5847         if (!Printer) {
5848                 result = WERR_BADFID;
5849                 goto done;
5850         }
5851
5852         if (!get_printer_snum(p, handle, &snum, NULL)) {
5853                 result = WERR_BADFID;
5854                 goto done;
5855         }
5856
5857         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5858                 result = WERR_BADFID;
5859                 goto done;
5860         }
5861
5862         if (devmode) {
5863                 /* we have a valid devmode
5864                    convert it and link it*/
5865
5866                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5867                 if (!convert_devicemode(printer->info_2->printername, devmode,
5868                                         &printer->info_2->devmode)) {
5869                         result =  WERR_NOMEM;
5870                         goto done;
5871                 }
5872         }
5873
5874         /* Check calling user has permission to update printer description */
5875
5876         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5877                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5878                 result = WERR_ACCESS_DENIED;
5879                 goto done;
5880         }
5881
5882
5883         /* Update printer info */
5884         result = mod_a_printer(printer, 2);
5885
5886 done:
5887         free_a_printer(&printer, 2);
5888
5889         return result;
5890 }
5891
5892
5893 /****************************************************************
5894  _spoolss_SetPrinter
5895 ****************************************************************/
5896
5897 WERROR _spoolss_SetPrinter(pipes_struct *p,
5898                            struct spoolss_SetPrinter *r)
5899 {
5900         WERROR result;
5901
5902         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5903
5904         if (!Printer) {
5905                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5906                         OUR_HANDLE(r->in.handle)));
5907                 return WERR_BADFID;
5908         }
5909
5910         /* check the level */
5911         switch (r->in.info_ctr->level) {
5912                 case 0:
5913                         return control_printer(r->in.handle, r->in.command, p);
5914                 case 2:
5915                         result = update_printer(p, r->in.handle,
5916                                                 r->in.info_ctr,
5917                                                 r->in.devmode_ctr->devmode);
5918                         if (!W_ERROR_IS_OK(result))
5919                                 return result;
5920                         if (r->in.secdesc_ctr->sd)
5921                                 result = update_printer_sec(r->in.handle, p,
5922                                                             r->in.secdesc_ctr);
5923                         return result;
5924                 case 3:
5925                         return update_printer_sec(r->in.handle, p,
5926                                                   r->in.secdesc_ctr);
5927                 case 7:
5928                         return publish_or_unpublish_printer(p, r->in.handle,
5929                                                             r->in.info_ctr->info.info7);
5930                 case 8:
5931                         return update_printer_devmode(p, r->in.handle,
5932                                                       r->in.devmode_ctr->devmode);
5933                 default:
5934                         return WERR_UNKNOWN_LEVEL;
5935         }
5936 }
5937
5938 /****************************************************************
5939  _spoolss_FindClosePrinterNotify
5940 ****************************************************************/
5941
5942 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5943                                        struct spoolss_FindClosePrinterNotify *r)
5944 {
5945         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5946
5947         if (!Printer) {
5948                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5949                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5950                 return WERR_BADFID;
5951         }
5952
5953         if (Printer->notify.client_connected == true) {
5954                 int snum = -1;
5955
5956                 if ( Printer->printer_type == SPLHND_SERVER)
5957                         snum = -1;
5958                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5959                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5960                         return WERR_BADFID;
5961
5962                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5963         }
5964
5965         Printer->notify.flags=0;
5966         Printer->notify.options=0;
5967         Printer->notify.localmachine[0]='\0';
5968         Printer->notify.printerlocal=0;
5969         TALLOC_FREE(Printer->notify.option);
5970         Printer->notify.client_connected = false;
5971
5972         return WERR_OK;
5973 }
5974
5975 /****************************************************************
5976  _spoolss_AddJob
5977 ****************************************************************/
5978
5979 WERROR _spoolss_AddJob(pipes_struct *p,
5980                        struct spoolss_AddJob *r)
5981 {
5982         if (!r->in.buffer && (r->in.offered != 0)) {
5983                 return WERR_INVALID_PARAM;
5984         }
5985
5986         /* this is what a NT server returns for AddJob. AddJob must fail on
5987          * non-local printers */
5988
5989         if (r->in.level != 1) {
5990                 return WERR_UNKNOWN_LEVEL;
5991         }
5992
5993         return WERR_INVALID_PARAM;
5994 }
5995
5996 /****************************************************************************
5997 fill_job_info1
5998 ****************************************************************************/
5999
6000 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6001                              struct spoolss_JobInfo1 *r,
6002                              const print_queue_struct *queue,
6003                              int position, int snum,
6004                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6005 {
6006         struct tm *t;
6007
6008         t = gmtime(&queue->time);
6009
6010         r->job_id               = queue->job;
6011
6012         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6013         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6014         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6015         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6016         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6017         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6018         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6019         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6020         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6021         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6022         r->text_status          = talloc_strdup(mem_ctx, "");
6023         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6024
6025         r->status               = nt_printj_status(queue->status);
6026         r->priority             = queue->priority;
6027         r->position             = position;
6028         r->total_pages          = queue->page_count;
6029         r->pages_printed        = 0; /* ??? */
6030
6031         init_systemtime(&r->submitted, t);
6032
6033         return WERR_OK;
6034 }
6035
6036 /****************************************************************************
6037 fill_job_info2
6038 ****************************************************************************/
6039
6040 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6041                              struct spoolss_JobInfo2 *r,
6042                              const print_queue_struct *queue,
6043                              int position, int snum,
6044                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6045                              struct spoolss_DeviceMode *devmode)
6046 {
6047         struct tm *t;
6048
6049         t = gmtime(&queue->time);
6050
6051         r->job_id               = queue->job;
6052
6053         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6054         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6055         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6056         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6057         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6058         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6059         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6060         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6061         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6062         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6063         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6064         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6065         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6066         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6067         r->parameters           = talloc_strdup(mem_ctx, "");
6068         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6069         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6070         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6071
6072         r->devmode              = devmode;
6073
6074         r->text_status          = talloc_strdup(mem_ctx, "");
6075         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6076
6077         r->secdesc              = NULL;
6078
6079         r->status               = nt_printj_status(queue->status);
6080         r->priority             = queue->priority;
6081         r->position             = position;
6082         r->start_time           = 0;
6083         r->until_time           = 0;
6084         r->total_pages          = queue->page_count;
6085         r->size                 = queue->size;
6086         init_systemtime(&r->submitted, t);
6087         r->time                 = 0;
6088         r->pages_printed        = 0; /* ??? */
6089
6090         return WERR_OK;
6091 }
6092
6093 /****************************************************************************
6094 fill_job_info3
6095 ****************************************************************************/
6096
6097 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6098                              struct spoolss_JobInfo3 *r,
6099                              const print_queue_struct *queue,
6100                              const print_queue_struct *next_queue,
6101                              int position, int snum,
6102                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6103 {
6104         r->job_id               = queue->job;
6105         r->next_job_id          = 0;
6106         if (next_queue) {
6107                 r->next_job_id  = next_queue->job;
6108         }
6109         r->reserved             = 0;
6110
6111         return WERR_OK;
6112 }
6113
6114 /****************************************************************************
6115  Enumjobs at level 1.
6116 ****************************************************************************/
6117
6118 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6119                               const print_queue_struct *queue,
6120                               uint32_t num_queues, int snum,
6121                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6122                               union spoolss_JobInfo **info_p,
6123                               uint32_t *count)
6124 {
6125         union spoolss_JobInfo *info;
6126         int i;
6127         WERROR result = WERR_OK;
6128
6129         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6130         W_ERROR_HAVE_NO_MEMORY(info);
6131
6132         *count = num_queues;
6133
6134         for (i=0; i<*count; i++) {
6135                 result = fill_job_info1(info,
6136                                         &info[i].info1,
6137                                         &queue[i],
6138                                         i,
6139                                         snum,
6140                                         ntprinter);
6141                 if (!W_ERROR_IS_OK(result)) {
6142                         goto out;
6143                 }
6144         }
6145
6146  out:
6147         if (!W_ERROR_IS_OK(result)) {
6148                 TALLOC_FREE(info);
6149                 *count = 0;
6150                 return result;
6151         }
6152
6153         *info_p = info;
6154
6155         return WERR_OK;
6156 }
6157
6158 /****************************************************************************
6159  Enumjobs at level 2.
6160 ****************************************************************************/
6161
6162 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6163                               const print_queue_struct *queue,
6164                               uint32_t num_queues, int snum,
6165                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6166                               union spoolss_JobInfo **info_p,
6167                               uint32_t *count)
6168 {
6169         union spoolss_JobInfo *info;
6170         int i;
6171         WERROR result = WERR_OK;
6172
6173         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6174         W_ERROR_HAVE_NO_MEMORY(info);
6175
6176         *count = num_queues;
6177
6178         for (i=0; i<*count; i++) {
6179
6180                 struct spoolss_DeviceMode *devmode;
6181
6182                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6183                 if (!devmode) {
6184                         result = WERR_NOMEM;
6185                         goto out;
6186                 }
6187
6188                 result = fill_job_info2(info,
6189                                         &info[i].info2,
6190                                         &queue[i],
6191                                         i,
6192                                         snum,
6193                                         ntprinter,
6194                                         devmode);
6195                 if (!W_ERROR_IS_OK(result)) {
6196                         goto out;
6197                 }
6198         }
6199
6200  out:
6201         if (!W_ERROR_IS_OK(result)) {
6202                 TALLOC_FREE(info);
6203                 *count = 0;
6204                 return result;
6205         }
6206
6207         *info_p = info;
6208
6209         return WERR_OK;
6210 }
6211
6212 /****************************************************************************
6213  Enumjobs at level 3.
6214 ****************************************************************************/
6215
6216 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6217                               const print_queue_struct *queue,
6218                               uint32_t num_queues, int snum,
6219                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6220                               union spoolss_JobInfo **info_p,
6221                               uint32_t *count)
6222 {
6223         union spoolss_JobInfo *info;
6224         int i;
6225         WERROR result = WERR_OK;
6226
6227         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6228         W_ERROR_HAVE_NO_MEMORY(info);
6229
6230         *count = num_queues;
6231
6232         for (i=0; i<*count; i++) {
6233                 const print_queue_struct *next_queue = NULL;
6234
6235                 if (i+1 < *count) {
6236                         next_queue = &queue[i+1];
6237                 }
6238
6239                 result = fill_job_info3(info,
6240                                         &info[i].info3,
6241                                         &queue[i],
6242                                         next_queue,
6243                                         i,
6244                                         snum,
6245                                         ntprinter);
6246                 if (!W_ERROR_IS_OK(result)) {
6247                         goto out;
6248                 }
6249         }
6250
6251  out:
6252         if (!W_ERROR_IS_OK(result)) {
6253                 TALLOC_FREE(info);
6254                 *count = 0;
6255                 return result;
6256         }
6257
6258         *info_p = info;
6259
6260         return WERR_OK;
6261 }
6262
6263 /****************************************************************
6264  _spoolss_EnumJobs
6265 ****************************************************************/
6266
6267 WERROR _spoolss_EnumJobs(pipes_struct *p,
6268                          struct spoolss_EnumJobs *r)
6269 {
6270         WERROR result;
6271         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6272         int snum;
6273         print_status_struct prt_status;
6274         print_queue_struct *queue = NULL;
6275         uint32_t count;
6276
6277         /* that's an [in out] buffer */
6278
6279         if (!r->in.buffer && (r->in.offered != 0)) {
6280                 return WERR_INVALID_PARAM;
6281         }
6282
6283         DEBUG(4,("_spoolss_EnumJobs\n"));
6284
6285         *r->out.needed = 0;
6286         *r->out.count = 0;
6287         *r->out.info = NULL;
6288
6289         /* lookup the printer snum and tdb entry */
6290
6291         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6292                 return WERR_BADFID;
6293         }
6294
6295         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6296         if (!W_ERROR_IS_OK(result)) {
6297                 return result;
6298         }
6299
6300         count = print_queue_status(snum, &queue, &prt_status);
6301         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6302                 count, prt_status.status, prt_status.message));
6303
6304         if (count == 0) {
6305                 SAFE_FREE(queue);
6306                 free_a_printer(&ntprinter, 2);
6307                 return WERR_OK;
6308         }
6309
6310         switch (r->in.level) {
6311         case 1:
6312                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6313                                          ntprinter, r->out.info, r->out.count);
6314                 break;
6315         case 2:
6316                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6317                                          ntprinter, r->out.info, r->out.count);
6318                 break;
6319         case 3:
6320                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6321                                          ntprinter, r->out.info, r->out.count);
6322                 break;
6323         default:
6324                 result = WERR_UNKNOWN_LEVEL;
6325                 break;
6326         }
6327
6328         SAFE_FREE(queue);
6329         free_a_printer(&ntprinter, 2);
6330
6331         if (!W_ERROR_IS_OK(result)) {
6332                 return result;
6333         }
6334
6335         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6336                                                      spoolss_EnumJobs, 
6337                                                      *r->out.info, r->in.level,
6338                                                      *r->out.count);
6339         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6340         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6341
6342         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6343 }
6344
6345 /****************************************************************
6346  _spoolss_ScheduleJob
6347 ****************************************************************/
6348
6349 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6350                             struct spoolss_ScheduleJob *r)
6351 {
6352         return WERR_OK;
6353 }
6354
6355 /****************************************************************
6356 ****************************************************************/
6357
6358 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6359                                const char *printer_name,
6360                                uint32_t job_id,
6361                                struct spoolss_SetJobInfo1 *r)
6362 {
6363         char *old_doc_name;
6364
6365         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6366                 return WERR_BADFID;
6367         }
6368
6369         if (strequal(old_doc_name, r->document_name)) {
6370                 return WERR_OK;
6371         }
6372
6373         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6374                 return WERR_BADFID;
6375         }
6376
6377         return WERR_OK;
6378 }
6379
6380 /****************************************************************
6381  _spoolss_SetJob
6382 ****************************************************************/
6383
6384 WERROR _spoolss_SetJob(pipes_struct *p,
6385                        struct spoolss_SetJob *r)
6386 {
6387         int snum;
6388         WERROR errcode = WERR_BADFUNC;
6389
6390         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6391                 return WERR_BADFID;
6392         }
6393
6394         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6395                 return WERR_INVALID_PRINTER_NAME;
6396         }
6397
6398         switch (r->in.command) {
6399         case SPOOLSS_JOB_CONTROL_CANCEL:
6400         case SPOOLSS_JOB_CONTROL_DELETE:
6401                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6402                         errcode = WERR_OK;
6403                 }
6404                 break;
6405         case SPOOLSS_JOB_CONTROL_PAUSE:
6406                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6407                         errcode = WERR_OK;
6408                 }
6409                 break;
6410         case SPOOLSS_JOB_CONTROL_RESTART:
6411         case SPOOLSS_JOB_CONTROL_RESUME:
6412                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6413                         errcode = WERR_OK;
6414                 }
6415                 break;
6416         case 0:
6417                 errcode = WERR_OK;
6418                 break;
6419         default:
6420                 return WERR_UNKNOWN_LEVEL;
6421         }
6422
6423         if (!W_ERROR_IS_OK(errcode)) {
6424                 return errcode;
6425         }
6426
6427         if (r->in.ctr == NULL) {
6428                 return errcode;
6429         }
6430
6431         switch (r->in.ctr->level) {
6432         case 1:
6433                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6434                                            r->in.job_id,
6435                                            r->in.ctr->info.info1);
6436                 break;
6437         case 2:
6438         case 3:
6439         case 4:
6440         default:
6441                 return WERR_UNKNOWN_LEVEL;
6442         }
6443
6444         return errcode;
6445 }
6446
6447 /****************************************************************************
6448  Enumerates all printer drivers by level and architecture.
6449 ****************************************************************************/
6450
6451 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6452                                                        const char *servername,
6453                                                        const char *architecture,
6454                                                        uint32_t level,
6455                                                        union spoolss_DriverInfo **info_p,
6456                                                        uint32_t *count_p)
6457 {
6458         int i;
6459         int ndrivers;
6460         uint32_t version;
6461         fstring *list = NULL;
6462         struct spoolss_DriverInfo8 *driver;
6463         union spoolss_DriverInfo *info = NULL;
6464         uint32_t count = 0;
6465         WERROR result = WERR_OK;
6466
6467         *count_p = 0;
6468         *info_p = NULL;
6469
6470         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6471                 list = NULL;
6472                 ndrivers = get_ntdrivers(&list, architecture, version);
6473                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6474                         ndrivers, architecture, version));
6475
6476                 if (ndrivers == -1) {
6477                         result = WERR_NOMEM;
6478                         goto out;
6479                 }
6480
6481                 if (ndrivers != 0) {
6482                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6483                                                     union spoolss_DriverInfo,
6484                                                     count + ndrivers);
6485                         if (!info) {
6486                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6487                                         "failed to enlarge driver info buffer!\n"));
6488                                 result = WERR_NOMEM;
6489                                 goto out;
6490                         }
6491                 }
6492
6493                 for (i=0; i<ndrivers; i++) {
6494                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6495                         ZERO_STRUCT(driver);
6496                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6497                                                       architecture, version);
6498                         if (!W_ERROR_IS_OK(result)) {
6499                                 goto out;
6500                         }
6501
6502                         switch (level) {
6503                         case 1:
6504                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6505                                                                    driver, servername);
6506                                 break;
6507                         case 2:
6508                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6509                                                                    driver, servername);
6510                                 break;
6511                         case 3:
6512                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6513                                                                    driver, servername);
6514                                 break;
6515                         case 4:
6516                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6517                                                                    driver, servername);
6518                                 break;
6519                         case 5:
6520                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6521                                                                    driver, servername);
6522                                 break;
6523                         case 6:
6524                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6525                                                                    driver, servername);
6526                                 break;
6527                         case 8:
6528                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6529                                                                    driver, servername);
6530                                 break;
6531                         default:
6532                                 result = WERR_UNKNOWN_LEVEL;
6533                                 break;
6534                         }
6535
6536                         free_a_printer_driver(driver);
6537
6538                         if (!W_ERROR_IS_OK(result)) {
6539                                 goto out;
6540                         }
6541                 }
6542
6543                 count += ndrivers;
6544                 SAFE_FREE(list);
6545         }
6546
6547  out:
6548         SAFE_FREE(list);
6549
6550         if (!W_ERROR_IS_OK(result)) {
6551                 TALLOC_FREE(info);
6552                 return result;
6553         }
6554
6555         *info_p = info;
6556         *count_p = count;
6557
6558         return WERR_OK;
6559 }
6560
6561 /****************************************************************************
6562  Enumerates all printer drivers by level.
6563 ****************************************************************************/
6564
6565 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6566                                        const char *servername,
6567                                        const char *architecture,
6568                                        uint32_t level,
6569                                        union spoolss_DriverInfo **info_p,
6570                                        uint32_t *count_p)
6571 {
6572         uint32_t a,i;
6573         WERROR result = WERR_OK;
6574
6575         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6576
6577                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6578
6579                         union spoolss_DriverInfo *info = NULL;
6580                         uint32_t count = 0;
6581
6582                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6583                                                                           servername,
6584                                                                           archi_table[a].long_archi,
6585                                                                           level,
6586                                                                           &info,
6587                                                                           &count);
6588                         if (!W_ERROR_IS_OK(result)) {
6589                                 continue;
6590                         }
6591
6592                         for (i=0; i < count; i++) {
6593                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6594                                              info[i], info_p, count_p);
6595                         }
6596                 }
6597
6598                 return result;
6599         }
6600
6601         return enumprinterdrivers_level_by_architecture(mem_ctx,
6602                                                         servername,
6603                                                         architecture,
6604                                                         level,
6605                                                         info_p,
6606                                                         count_p);
6607 }
6608
6609 /****************************************************************
6610  _spoolss_EnumPrinterDrivers
6611 ****************************************************************/
6612
6613 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6614                                    struct spoolss_EnumPrinterDrivers *r)
6615 {
6616         const char *cservername;
6617         WERROR result;
6618
6619         /* that's an [in out] buffer */
6620
6621         if (!r->in.buffer && (r->in.offered != 0)) {
6622                 return WERR_INVALID_PARAM;
6623         }
6624
6625         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6626
6627         *r->out.needed = 0;
6628         *r->out.count = 0;
6629         *r->out.info = NULL;
6630
6631         cservername = canon_servername(r->in.server);
6632
6633         if (!is_myname_or_ipaddr(cservername)) {
6634                 return WERR_UNKNOWN_PRINTER_DRIVER;
6635         }
6636
6637         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6638                                           r->in.environment,
6639                                           r->in.level,
6640                                           r->out.info,
6641                                           r->out.count);
6642         if (!W_ERROR_IS_OK(result)) {
6643                 return result;
6644         }
6645
6646         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6647                                                      spoolss_EnumPrinterDrivers, 
6648                                                      *r->out.info, r->in.level,
6649                                                      *r->out.count);
6650         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6651         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6652
6653         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6654 }
6655
6656 /****************************************************************************
6657 ****************************************************************************/
6658
6659 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6660                                struct spoolss_FormInfo1 *r,
6661                                const nt_forms_struct *form)
6662 {
6663         r->form_name    = talloc_strdup(mem_ctx, form->name);
6664         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6665
6666         r->flags        = form->flag;
6667         r->size.width   = form->width;
6668         r->size.height  = form->length;
6669         r->area.left    = form->left;
6670         r->area.top     = form->top;
6671         r->area.right   = form->right;
6672         r->area.bottom  = form->bottom;
6673
6674         return WERR_OK;
6675 }
6676
6677 /****************************************************************
6678  spoolss_enumforms_level1
6679 ****************************************************************/
6680
6681 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6682                                        const nt_forms_struct *builtin_forms,
6683                                        uint32_t num_builtin_forms,
6684                                        const nt_forms_struct *user_forms,
6685                                        uint32_t num_user_forms,
6686                                        union spoolss_FormInfo **info_p,
6687                                        uint32_t *count)
6688 {
6689         union spoolss_FormInfo *info;
6690         WERROR result = WERR_OK;
6691         int i;
6692
6693         *count = num_builtin_forms + num_user_forms;
6694
6695         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6696         W_ERROR_HAVE_NO_MEMORY(info);
6697
6698         /* construct the list of form structures */
6699         for (i=0; i<num_builtin_forms; i++) {
6700                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6701                 result = fill_form_info_1(info, &info[i].info1,
6702                                           &builtin_forms[i]);
6703                 if (!W_ERROR_IS_OK(result)) {
6704                         goto out;
6705                 }
6706         }
6707
6708         for (i=0; i<num_user_forms; i++) {
6709                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6710                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6711                                           &user_forms[i]);
6712                 if (!W_ERROR_IS_OK(result)) {
6713                         goto out;
6714                 }
6715         }
6716
6717  out:
6718         if (!W_ERROR_IS_OK(result)) {
6719                 TALLOC_FREE(info);
6720                 *count = 0;
6721                 return result;
6722         }
6723
6724         *info_p = info;
6725
6726         return WERR_OK;
6727 }
6728
6729 /****************************************************************
6730  _spoolss_EnumForms
6731 ****************************************************************/
6732
6733 WERROR _spoolss_EnumForms(pipes_struct *p,
6734                           struct spoolss_EnumForms *r)
6735 {
6736         WERROR result;
6737         nt_forms_struct *user_forms = NULL;
6738         nt_forms_struct *builtin_forms = NULL;
6739         uint32_t num_user_forms;
6740         uint32_t num_builtin_forms;
6741
6742         *r->out.count = 0;
6743         *r->out.needed = 0;
6744         *r->out.info = NULL;
6745
6746         /* that's an [in out] buffer */
6747
6748         if (!r->in.buffer && (r->in.offered != 0) ) {
6749                 return WERR_INVALID_PARAM;
6750         }
6751
6752         DEBUG(4,("_spoolss_EnumForms\n"));
6753         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6754         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6755
6756         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6757         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6758         num_user_forms = get_ntforms(&user_forms);
6759         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6760
6761         if (num_user_forms + num_builtin_forms == 0) {
6762                 SAFE_FREE(builtin_forms);
6763                 SAFE_FREE(user_forms);
6764                 return WERR_NO_MORE_ITEMS;
6765         }
6766
6767         switch (r->in.level) {
6768         case 1:
6769                 result = spoolss_enumforms_level1(p->mem_ctx,
6770                                                   builtin_forms,
6771                                                   num_builtin_forms,
6772                                                   user_forms,
6773                                                   num_user_forms,
6774                                                   r->out.info,
6775                                                   r->out.count);
6776                 break;
6777         default:
6778                 result = WERR_UNKNOWN_LEVEL;
6779                 break;
6780         }
6781
6782         SAFE_FREE(user_forms);
6783         SAFE_FREE(builtin_forms);
6784
6785         if (!W_ERROR_IS_OK(result)) {
6786                 return result;
6787         }
6788
6789         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6790                                                      spoolss_EnumForms, 
6791                                                      *r->out.info, r->in.level,
6792                                                      *r->out.count);
6793         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6794         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6795
6796         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6797 }
6798
6799 /****************************************************************
6800 ****************************************************************/
6801
6802 static WERROR find_form_byname(const char *name,
6803                                nt_forms_struct *form)
6804 {
6805         nt_forms_struct *list = NULL;
6806         int num_forms = 0, i = 0;
6807
6808         if (get_a_builtin_ntform_by_string(name, form)) {
6809                 return WERR_OK;
6810         }
6811
6812         num_forms = get_ntforms(&list);
6813         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6814
6815         if (num_forms == 0) {
6816                 return WERR_BADFID;
6817         }
6818
6819         /* Check if the requested name is in the list of form structures */
6820         for (i = 0; i < num_forms; i++) {
6821
6822                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6823
6824                 if (strequal(name, list[i].name)) {
6825                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6826                         *form = list[i];
6827                         SAFE_FREE(list);
6828                         return WERR_OK;
6829                 }
6830         }
6831
6832         SAFE_FREE(list);
6833
6834         return WERR_BADFID;
6835 }
6836
6837 /****************************************************************
6838  _spoolss_GetForm
6839 ****************************************************************/
6840
6841 WERROR _spoolss_GetForm(pipes_struct *p,
6842                         struct spoolss_GetForm *r)
6843 {
6844         WERROR result;
6845         nt_forms_struct form;
6846
6847         /* that's an [in out] buffer */
6848
6849         if (!r->in.buffer && (r->in.offered != 0)) {
6850                 return WERR_INVALID_PARAM;
6851         }
6852
6853         DEBUG(4,("_spoolss_GetForm\n"));
6854         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6855         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6856
6857         result = find_form_byname(r->in.form_name, &form);
6858         if (!W_ERROR_IS_OK(result)) {
6859                 TALLOC_FREE(r->out.info);
6860                 return result;
6861         }
6862
6863         switch (r->in.level) {
6864         case 1:
6865                 result = fill_form_info_1(p->mem_ctx,
6866                                           &r->out.info->info1,
6867                                           &form);
6868                 break;
6869
6870         default:
6871                 result = WERR_UNKNOWN_LEVEL;
6872                 break;
6873         }
6874
6875         if (!W_ERROR_IS_OK(result)) {
6876                 TALLOC_FREE(r->out.info);
6877                 return result;
6878         }
6879
6880         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6881                                                r->out.info, r->in.level);
6882         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6883
6884         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6885 }
6886
6887 /****************************************************************************
6888 ****************************************************************************/
6889
6890 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6891                           struct spoolss_PortInfo1 *r,
6892                           const char *name)
6893 {
6894         r->port_name = talloc_strdup(mem_ctx, name);
6895         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6896
6897         return WERR_OK;
6898 }
6899
6900 /****************************************************************************
6901  TODO: This probably needs distinguish between TCP/IP and Local ports
6902  somehow.
6903 ****************************************************************************/
6904
6905 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6906                           struct spoolss_PortInfo2 *r,
6907                           const char *name)
6908 {
6909         r->port_name = talloc_strdup(mem_ctx, name);
6910         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6911
6912         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6913         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6914
6915         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6916         W_ERROR_HAVE_NO_MEMORY(r->description);
6917
6918         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6919         r->reserved = 0;
6920
6921         return WERR_OK;
6922 }
6923
6924
6925 /****************************************************************************
6926  wrapper around the enumer ports command
6927 ****************************************************************************/
6928
6929 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6930 {
6931         char *cmd = lp_enumports_cmd();
6932         char **qlines = NULL;
6933         char *command = NULL;
6934         int numlines;
6935         int ret;
6936         int fd;
6937
6938         *count = 0;
6939         *lines = NULL;
6940
6941         /* if no hook then just fill in the default port */
6942
6943         if ( !*cmd ) {
6944                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6945                         return WERR_NOMEM;
6946                 }
6947                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6948                         TALLOC_FREE(qlines);
6949                         return WERR_NOMEM;
6950                 }
6951                 qlines[1] = NULL;
6952                 numlines = 1;
6953         }
6954         else {
6955                 /* we have a valid enumport command */
6956
6957                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6958                 if (!command) {
6959                         return WERR_NOMEM;
6960                 }
6961
6962                 DEBUG(10,("Running [%s]\n", command));
6963                 ret = smbrun(command, &fd);
6964                 DEBUG(10,("Returned [%d]\n", ret));
6965                 TALLOC_FREE(command);
6966                 if (ret != 0) {
6967                         if (fd != -1) {
6968                                 close(fd);
6969                         }
6970                         return WERR_ACCESS_DENIED;
6971                 }
6972
6973                 numlines = 0;
6974                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6975                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6976                 close(fd);
6977         }
6978
6979         *count = numlines;
6980         *lines = qlines;
6981
6982         return WERR_OK;
6983 }
6984
6985 /****************************************************************************
6986  enumports level 1.
6987 ****************************************************************************/
6988
6989 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6990                                 union spoolss_PortInfo **info_p,
6991                                 uint32_t *count)
6992 {
6993         union spoolss_PortInfo *info = NULL;
6994         int i=0;
6995         WERROR result = WERR_OK;
6996         char **qlines = NULL;
6997         int numlines = 0;
6998
6999         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7000         if (!W_ERROR_IS_OK(result)) {
7001                 goto out;
7002         }
7003
7004         if (numlines) {
7005                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7006                 if (!info) {
7007                         DEBUG(10,("Returning WERR_NOMEM\n"));
7008                         result = WERR_NOMEM;
7009                         goto out;
7010                 }
7011
7012                 for (i=0; i<numlines; i++) {
7013                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7014                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7015                         if (!W_ERROR_IS_OK(result)) {
7016                                 goto out;
7017                         }
7018                 }
7019         }
7020         TALLOC_FREE(qlines);
7021
7022 out:
7023         if (!W_ERROR_IS_OK(result)) {
7024                 TALLOC_FREE(info);
7025                 TALLOC_FREE(qlines);
7026                 *count = 0;
7027                 *info_p = NULL;
7028                 return result;
7029         }
7030
7031         *info_p = info;
7032         *count = numlines;
7033
7034         return WERR_OK;
7035 }
7036
7037 /****************************************************************************
7038  enumports level 2.
7039 ****************************************************************************/
7040
7041 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7042                                 union spoolss_PortInfo **info_p,
7043                                 uint32_t *count)
7044 {
7045         union spoolss_PortInfo *info = NULL;
7046         int i=0;
7047         WERROR result = WERR_OK;
7048         char **qlines = NULL;
7049         int numlines = 0;
7050
7051         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7052         if (!W_ERROR_IS_OK(result)) {
7053                 goto out;
7054         }
7055
7056         if (numlines) {
7057                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7058                 if (!info) {
7059                         DEBUG(10,("Returning WERR_NOMEM\n"));
7060                         result = WERR_NOMEM;
7061                         goto out;
7062                 }
7063
7064                 for (i=0; i<numlines; i++) {
7065                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7066                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7067                         if (!W_ERROR_IS_OK(result)) {
7068                                 goto out;
7069                         }
7070                 }
7071         }
7072         TALLOC_FREE(qlines);
7073
7074 out:
7075         if (!W_ERROR_IS_OK(result)) {
7076                 TALLOC_FREE(info);
7077                 TALLOC_FREE(qlines);
7078                 *count = 0;
7079                 *info_p = NULL;
7080                 return result;
7081         }
7082
7083         *info_p = info;
7084         *count = numlines;
7085
7086         return WERR_OK;
7087 }
7088
7089 /****************************************************************
7090  _spoolss_EnumPorts
7091 ****************************************************************/
7092
7093 WERROR _spoolss_EnumPorts(pipes_struct *p,
7094                           struct spoolss_EnumPorts *r)
7095 {
7096         WERROR result;
7097
7098         /* that's an [in out] buffer */
7099
7100         if (!r->in.buffer && (r->in.offered != 0)) {
7101                 return WERR_INVALID_PARAM;
7102         }
7103
7104         DEBUG(4,("_spoolss_EnumPorts\n"));
7105
7106         *r->out.count = 0;
7107         *r->out.needed = 0;
7108         *r->out.info = NULL;
7109
7110         switch (r->in.level) {
7111         case 1:
7112                 result = enumports_level_1(p->mem_ctx, r->out.info,
7113                                            r->out.count);
7114                 break;
7115         case 2:
7116                 result = enumports_level_2(p->mem_ctx, r->out.info,
7117                                            r->out.count);
7118                 break;
7119         default:
7120                 return WERR_UNKNOWN_LEVEL;
7121         }
7122
7123         if (!W_ERROR_IS_OK(result)) {
7124                 return result;
7125         }
7126
7127         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7128                                                      spoolss_EnumPorts, 
7129                                                      *r->out.info, r->in.level,
7130                                                      *r->out.count);
7131         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7132         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7133
7134         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7135 }
7136
7137 /****************************************************************************
7138 ****************************************************************************/
7139
7140 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7141                                            const char *server,
7142                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7143                                            struct spoolss_DeviceMode *devmode,
7144                                            struct security_descriptor *sec_desc,
7145                                            struct spoolss_UserLevelCtr *user_ctr,
7146                                            struct policy_handle *handle)
7147 {
7148         NT_PRINTER_INFO_LEVEL *printer = NULL;
7149         fstring name;
7150         int     snum;
7151         WERROR err = WERR_OK;
7152
7153         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7154                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7155                 return WERR_NOMEM;
7156         }
7157
7158         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7159         if (!convert_printer_info(info_ctr, printer)) {
7160                 free_a_printer(&printer, 2);
7161                 return WERR_NOMEM;
7162         }
7163
7164         /* samba does not have a concept of local, non-shared printers yet, so
7165          * make sure we always setup sharename - gd */
7166         if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7167                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7168                         "no sharename has been set, setting printername %s as sharename\n",
7169                         printer->info_2->printername));
7170                 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7171         }
7172
7173         /* check to see if the printer already exists */
7174
7175         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7176                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7177                         printer->info_2->sharename));
7178                 free_a_printer(&printer, 2);
7179                 return WERR_PRINTER_ALREADY_EXISTS;
7180         }
7181
7182         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7183                 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7184                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7185                                 printer->info_2->printername));
7186                         free_a_printer(&printer, 2);
7187                         return WERR_PRINTER_ALREADY_EXISTS;
7188                 }
7189         }
7190
7191         /* validate printer info struct */
7192         if (!info_ctr->info.info2->printername ||
7193             strlen(info_ctr->info.info2->printername) == 0) {
7194                 free_a_printer(&printer,2);
7195                 return WERR_INVALID_PRINTER_NAME;
7196         }
7197         if (!info_ctr->info.info2->portname ||
7198             strlen(info_ctr->info.info2->portname) == 0) {
7199                 free_a_printer(&printer,2);
7200                 return WERR_UNKNOWN_PORT;
7201         }
7202         if (!info_ctr->info.info2->drivername ||
7203             strlen(info_ctr->info.info2->drivername) == 0) {
7204                 free_a_printer(&printer,2);
7205                 return WERR_UNKNOWN_PRINTER_DRIVER;
7206         }
7207         if (!info_ctr->info.info2->printprocessor ||
7208             strlen(info_ctr->info.info2->printprocessor) == 0) {
7209                 free_a_printer(&printer,2);
7210                 return WERR_UNKNOWN_PRINTPROCESSOR;
7211         }
7212
7213         /* FIXME!!!  smbd should check to see if the driver is installed before
7214            trying to add a printer like this  --jerry */
7215
7216         if (*lp_addprinter_cmd() ) {
7217                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7218                                        printer) ) {
7219                         free_a_printer(&printer,2);
7220                         return WERR_ACCESS_DENIED;
7221                 }
7222         } else {
7223                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7224                         "smb.conf parameter \"addprinter command\" is defined. This"
7225                         "parameter must exist for this call to succeed\n",
7226                         printer->info_2->sharename ));
7227         }
7228
7229         /* use our primary netbios name since get_a_printer() will convert
7230            it to what the client expects on a case by case basis */
7231
7232         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7233              printer->info_2->sharename);
7234
7235
7236         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7237                 free_a_printer(&printer,2);
7238                 return WERR_ACCESS_DENIED;
7239         }
7240
7241         /* you must be a printer admin to add a new printer */
7242         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7243                 free_a_printer(&printer,2);
7244                 return WERR_ACCESS_DENIED;
7245         }
7246
7247         /*
7248          * Do sanity check on the requested changes for Samba.
7249          */
7250
7251         if (!check_printer_ok(printer->info_2, snum)) {
7252                 free_a_printer(&printer,2);
7253                 return WERR_INVALID_PARAM;
7254         }
7255
7256         /*
7257          * When a printer is created, the drivername bound to the printer is used
7258          * to lookup previously saved driver initialization info, which is then
7259          * bound to the new printer, simulating what happens in the Windows arch.
7260          */
7261
7262         if (devmode)
7263         {
7264                 /* A valid devmode was included, convert and link it
7265                 */
7266                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7267
7268                 if (!convert_devicemode(printer->info_2->printername, devmode,
7269                                         &printer->info_2->devmode)) {
7270                         return  WERR_NOMEM;
7271                 }
7272         }
7273
7274         /* write the ASCII on disk */
7275         err = mod_a_printer(printer, 2);
7276         if (!W_ERROR_IS_OK(err)) {
7277                 free_a_printer(&printer,2);
7278                 return err;
7279         }
7280
7281         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7282                 /* Handle open failed - remove addition. */
7283                 del_a_printer(printer->info_2->sharename);
7284                 free_a_printer(&printer,2);
7285                 ZERO_STRUCTP(handle);
7286                 return WERR_ACCESS_DENIED;
7287         }
7288
7289         update_c_setprinter(false);
7290         free_a_printer(&printer,2);
7291
7292         return WERR_OK;
7293 }
7294
7295 /****************************************************************
7296  _spoolss_AddPrinterEx
7297 ****************************************************************/
7298
7299 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7300                              struct spoolss_AddPrinterEx *r)
7301 {
7302         switch (r->in.info_ctr->level) {
7303         case 1:
7304                 /* we don't handle yet */
7305                 /* but I know what to do ... */
7306                 return WERR_UNKNOWN_LEVEL;
7307         case 2:
7308                 return spoolss_addprinterex_level_2(p, r->in.server,
7309                                                     r->in.info_ctr,
7310                                                     r->in.devmode_ctr->devmode,
7311                                                     r->in.secdesc_ctr->sd,
7312                                                     r->in.userlevel_ctr,
7313                                                     r->out.handle);
7314         default:
7315                 return WERR_UNKNOWN_LEVEL;
7316         }
7317 }
7318
7319 /****************************************************************
7320  _spoolss_AddPrinter
7321 ****************************************************************/
7322
7323 WERROR _spoolss_AddPrinter(pipes_struct *p,
7324                            struct spoolss_AddPrinter *r)
7325 {
7326         struct spoolss_AddPrinterEx a;
7327         struct spoolss_UserLevelCtr userlevel_ctr;
7328
7329         ZERO_STRUCT(userlevel_ctr);
7330
7331         userlevel_ctr.level = 1;
7332
7333         a.in.server             = r->in.server;
7334         a.in.info_ctr           = r->in.info_ctr;
7335         a.in.devmode_ctr        = r->in.devmode_ctr;
7336         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7337         a.in.userlevel_ctr      = &userlevel_ctr;
7338         a.out.handle            = r->out.handle;
7339
7340         return _spoolss_AddPrinterEx(p, &a);
7341 }
7342
7343 /****************************************************************
7344  _spoolss_AddPrinterDriverEx
7345 ****************************************************************/
7346
7347 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7348                                    struct spoolss_AddPrinterDriverEx *r)
7349 {
7350         WERROR err = WERR_OK;
7351         char *driver_name = NULL;
7352         uint32_t version;
7353         const char *fn;
7354
7355         switch (p->hdr_req.opnum) {
7356                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7357                         fn = "_spoolss_AddPrinterDriver";
7358                         break;
7359                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7360                         fn = "_spoolss_AddPrinterDriverEx";
7361                         break;
7362                 default:
7363                         return WERR_INVALID_PARAM;
7364         }
7365
7366         /*
7367          * we only support the semantics of AddPrinterDriver()
7368          * i.e. only copy files that are newer than existing ones
7369          */
7370
7371         if (r->in.flags == 0) {
7372                 return WERR_INVALID_PARAM;
7373         }
7374
7375         if (r->in.flags != APD_COPY_NEW_FILES) {
7376                 return WERR_ACCESS_DENIED;
7377         }
7378
7379         /* FIXME */
7380         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7381                 /* Clever hack from Martin Zielinski <mz@seh.de>
7382                  * to allow downgrade from level 8 (Vista).
7383                  */
7384                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7385                         r->in.info_ctr->level));
7386                 return WERR_UNKNOWN_LEVEL;
7387         }
7388
7389         DEBUG(5,("Cleaning driver's information\n"));
7390         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7391         if (!W_ERROR_IS_OK(err))
7392                 goto done;
7393
7394         DEBUG(5,("Moving driver to final destination\n"));
7395         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7396                                                               &err)) ) {
7397                 goto done;
7398         }
7399
7400         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7401                 err = WERR_ACCESS_DENIED;
7402                 goto done;
7403         }
7404
7405         /*
7406          * I think this is where he DrvUpgradePrinter() hook would be
7407          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7408          * server.  Right now, we just need to send ourselves a message
7409          * to update each printer bound to this driver.   --jerry
7410          */
7411
7412         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7413                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7414                         fn, driver_name));
7415         }
7416
7417 done:
7418         return err;
7419 }
7420
7421 /****************************************************************
7422  _spoolss_AddPrinterDriver
7423 ****************************************************************/
7424
7425 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7426                                  struct spoolss_AddPrinterDriver *r)
7427 {
7428         struct spoolss_AddPrinterDriverEx a;
7429
7430         switch (r->in.info_ctr->level) {
7431         case 2:
7432         case 3:
7433         case 4:
7434         case 5:
7435                 break;
7436         default:
7437                 return WERR_UNKNOWN_LEVEL;
7438         }
7439
7440         a.in.servername         = r->in.servername;
7441         a.in.info_ctr           = r->in.info_ctr;
7442         a.in.flags              = APD_COPY_NEW_FILES;
7443
7444         return _spoolss_AddPrinterDriverEx(p, &a);
7445 }
7446
7447 /****************************************************************************
7448 ****************************************************************************/
7449
7450 struct _spoolss_paths {
7451         int type;
7452         const char *share;
7453         const char *dir;
7454 };
7455
7456 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7457
7458 static const struct _spoolss_paths spoolss_paths[]= {
7459         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7460         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7461 };
7462
7463 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7464                                           const char *servername,
7465                                           const char *environment,
7466                                           int component,
7467                                           char **path)
7468 {
7469         const char *pservername = NULL;
7470         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7471         const char *short_archi;
7472
7473         *path = NULL;
7474
7475         /* environment may be empty */
7476         if (environment && strlen(environment)) {
7477                 long_archi = environment;
7478         }
7479
7480         /* servername may be empty */
7481         if (servername && strlen(servername)) {
7482                 pservername = canon_servername(servername);
7483
7484                 if (!is_myname_or_ipaddr(pservername)) {
7485                         return WERR_INVALID_PARAM;
7486                 }
7487         }
7488
7489         if (!(short_archi = get_short_archi(long_archi))) {
7490                 return WERR_INVALID_ENVIRONMENT;
7491         }
7492
7493         switch (component) {
7494         case SPOOLSS_PRTPROCS_PATH:
7495         case SPOOLSS_DRIVER_PATH:
7496                 if (pservername) {
7497                         *path = talloc_asprintf(mem_ctx,
7498                                         "\\\\%s\\%s\\%s",
7499                                         pservername,
7500                                         spoolss_paths[component].share,
7501                                         short_archi);
7502                 } else {
7503                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7504                                         SPOOLSS_DEFAULT_SERVER_PATH,
7505                                         spoolss_paths[component].dir,
7506                                         short_archi);
7507                 }
7508                 break;
7509         default:
7510                 return WERR_INVALID_PARAM;
7511         }
7512
7513         if (!*path) {
7514                 return WERR_NOMEM;
7515         }
7516
7517         return WERR_OK;
7518 }
7519
7520 /****************************************************************************
7521 ****************************************************************************/
7522
7523 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7524                                           const char *servername,
7525                                           const char *environment,
7526                                           struct spoolss_DriverDirectoryInfo1 *r)
7527 {
7528         WERROR werr;
7529         char *path = NULL;
7530
7531         werr = compose_spoolss_server_path(mem_ctx,
7532                                            servername,
7533                                            environment,
7534                                            SPOOLSS_DRIVER_PATH,
7535                                            &path);
7536         if (!W_ERROR_IS_OK(werr)) {
7537                 return werr;
7538         }
7539
7540         DEBUG(4,("printer driver directory: [%s]\n", path));
7541
7542         r->directory_name = path;
7543
7544         return WERR_OK;
7545 }
7546
7547 /****************************************************************
7548  _spoolss_GetPrinterDriverDirectory
7549 ****************************************************************/
7550
7551 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7552                                           struct spoolss_GetPrinterDriverDirectory *r)
7553 {
7554         WERROR werror;
7555
7556         /* that's an [in out] buffer */
7557
7558         if (!r->in.buffer && (r->in.offered != 0)) {
7559                 return WERR_INVALID_PARAM;
7560         }
7561
7562         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7563                 r->in.level));
7564
7565         *r->out.needed = 0;
7566
7567         /* r->in.level is ignored */
7568
7569         werror = getprinterdriverdir_level_1(p->mem_ctx,
7570                                              r->in.server,
7571                                              r->in.environment,
7572                                              &r->out.info->info1);
7573         if (!W_ERROR_IS_OK(werror)) {
7574                 TALLOC_FREE(r->out.info);
7575                 return werror;
7576         }
7577
7578         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7579                                                r->out.info, r->in.level);
7580         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7581
7582         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7583 }
7584
7585 /****************************************************************
7586  _spoolss_EnumPrinterData
7587 ****************************************************************/
7588
7589 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7590                                 struct spoolss_EnumPrinterData *r)
7591 {
7592         WERROR result;
7593         struct spoolss_EnumPrinterDataEx r2;
7594         uint32_t count;
7595         struct spoolss_PrinterEnumValues *info, *val = NULL;
7596         uint32_t needed;
7597
7598         r2.in.handle    = r->in.handle;
7599         r2.in.key_name  = "PrinterDriverData";
7600         r2.in.offered   = 0;
7601         r2.out.count    = &count;
7602         r2.out.info     = &info;
7603         r2.out.needed   = &needed;
7604
7605         result = _spoolss_EnumPrinterDataEx(p, &r2);
7606         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7607                 r2.in.offered = needed;
7608                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7609         }
7610         if (!W_ERROR_IS_OK(result)) {
7611                 return result;
7612         }
7613
7614         /*
7615          * The NT machine wants to know the biggest size of value and data
7616          *
7617          * cf: MSDN EnumPrinterData remark section
7618          */
7619
7620         if (!r->in.value_offered && !r->in.data_offered) {
7621                 uint32_t biggest_valuesize = 0;
7622                 uint32_t biggest_datasize = 0;
7623                 int i, name_length;
7624
7625                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7626
7627                 for (i=0; i<count; i++) {
7628
7629                         name_length = strlen(info[i].value_name);
7630                         if (strlen(info[i].value_name) > biggest_valuesize) {
7631                                 biggest_valuesize = name_length;
7632                         }
7633
7634                         if (info[i].data_length > biggest_datasize) {
7635                                 biggest_datasize = info[i].data_length;
7636                         }
7637
7638                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7639                                 biggest_datasize));
7640                 }
7641
7642                 /* the value is an UNICODE string but real_value_size is the length
7643                    in bytes including the trailing 0 */
7644
7645                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7646                 *r->out.data_needed  = biggest_datasize;
7647
7648                 DEBUG(6,("final values: [%d], [%d]\n",
7649                         *r->out.value_needed, *r->out.data_needed));
7650
7651                 return WERR_OK;
7652         }
7653
7654         if (r->in.enum_index < count) {
7655                 val = &info[r->in.enum_index];
7656         }
7657
7658         if (val == NULL) {
7659                 /* out_value should default to "" or else NT4 has
7660                    problems unmarshalling the response */
7661
7662                 if (r->in.value_offered) {
7663                         *r->out.value_needed = 1;
7664                         r->out.value_name = talloc_strdup(r, "");
7665                         if (!r->out.value_name) {
7666                                 return WERR_NOMEM;
7667                         }
7668                 } else {
7669                         r->out.value_name = NULL;
7670                         *r->out.value_needed = 0;
7671                 }
7672
7673                 /* the data is counted in bytes */
7674
7675                 *r->out.data_needed = r->in.data_offered;
7676
7677                 result = WERR_NO_MORE_ITEMS;
7678         } else {
7679                 /*
7680                  * the value is:
7681                  * - counted in bytes in the request
7682                  * - counted in UNICODE chars in the max reply
7683                  * - counted in bytes in the real size
7684                  *
7685                  * take a pause *before* coding not *during* coding
7686                  */
7687
7688                 /* name */
7689                 if (r->in.value_offered) {
7690                         r->out.value_name = talloc_strdup(r, val->value_name);
7691                         if (!r->out.value_name) {
7692                                 return WERR_NOMEM;
7693                         }
7694                         *r->out.value_needed = val->value_name_len;
7695                 } else {
7696                         r->out.value_name = NULL;
7697                         *r->out.value_needed = 0;
7698                 }
7699
7700                 /* type */
7701
7702                 *r->out.type = val->type;
7703
7704                 /* data - counted in bytes */
7705
7706                 /*
7707                  * See the section "Dynamically Typed Query Parameters"
7708                  * in MS-RPRN.
7709                  */
7710
7711                 if (r->out.data && val->data && val->data->data &&
7712                                 val->data_length && r->in.data_offered) {
7713                         memcpy(r->out.data, val->data->data,
7714                                 MIN(val->data_length,r->in.data_offered));
7715                 }
7716
7717                 *r->out.data_needed = val->data_length;
7718
7719                 result = WERR_OK;
7720         }
7721
7722         return result;
7723 }
7724
7725 /****************************************************************
7726  _spoolss_SetPrinterData
7727 ****************************************************************/
7728
7729 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7730                                struct spoolss_SetPrinterData *r)
7731 {
7732         struct spoolss_SetPrinterDataEx r2;
7733
7734         r2.in.handle            = r->in.handle;
7735         r2.in.key_name          = "PrinterDriverData";
7736         r2.in.value_name        = r->in.value_name;
7737         r2.in.type              = r->in.type;
7738         r2.in.data              = r->in.data;
7739         r2.in.offered           = r->in.offered;
7740
7741         return _spoolss_SetPrinterDataEx(p, &r2);
7742 }
7743
7744 /****************************************************************
7745  _spoolss_ResetPrinter
7746 ****************************************************************/
7747
7748 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7749                              struct spoolss_ResetPrinter *r)
7750 {
7751         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7752         int             snum;
7753
7754         DEBUG(5,("_spoolss_ResetPrinter\n"));
7755
7756         /*
7757          * All we do is to check to see if the handle and queue is valid.
7758          * This call really doesn't mean anything to us because we only
7759          * support RAW printing.   --jerry
7760          */
7761
7762         if (!Printer) {
7763                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7764                         OUR_HANDLE(r->in.handle)));
7765                 return WERR_BADFID;
7766         }
7767
7768         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7769                 return WERR_BADFID;
7770
7771
7772         /* blindly return success */
7773         return WERR_OK;
7774 }
7775
7776 /****************************************************************
7777  _spoolss_DeletePrinterData
7778 ****************************************************************/
7779
7780 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7781                                   struct spoolss_DeletePrinterData *r)
7782 {
7783         struct spoolss_DeletePrinterDataEx r2;
7784
7785         r2.in.handle            = r->in.handle;
7786         r2.in.key_name          = "PrinterDriverData";
7787         r2.in.value_name        = r->in.value_name;
7788
7789         return _spoolss_DeletePrinterDataEx(p, &r2);
7790 }
7791
7792 /****************************************************************
7793  _spoolss_AddForm
7794 ****************************************************************/
7795
7796 WERROR _spoolss_AddForm(pipes_struct *p,
7797                         struct spoolss_AddForm *r)
7798 {
7799         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7800         nt_forms_struct tmpForm;
7801         int snum = -1;
7802         WERROR status = WERR_OK;
7803         NT_PRINTER_INFO_LEVEL *printer = NULL;
7804         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7805
7806         int count=0;
7807         nt_forms_struct *list=NULL;
7808         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7809         int i;
7810
7811         DEBUG(5,("_spoolss_AddForm\n"));
7812
7813         if (!Printer) {
7814                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7815                         OUR_HANDLE(r->in.handle)));
7816                 return WERR_BADFID;
7817         }
7818
7819
7820         /* forms can be added on printer or on the print server handle */
7821
7822         if ( Printer->printer_type == SPLHND_PRINTER )
7823         {
7824                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7825                         return WERR_BADFID;
7826
7827                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7828                 if (!W_ERROR_IS_OK(status))
7829                         goto done;
7830         }
7831
7832         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7833            and not a printer admin, then fail */
7834
7835         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7836              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7837              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7838                                           p->server_info->info3->base.domain.string,
7839                                           NULL,
7840                                           p->server_info->ptok,
7841                                           lp_printer_admin(snum))) {
7842                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7843                 status = WERR_ACCESS_DENIED;
7844                 goto done;
7845         }
7846
7847         switch (form->flags) {
7848         case SPOOLSS_FORM_USER:
7849         case SPOOLSS_FORM_BUILTIN:
7850         case SPOOLSS_FORM_PRINTER:
7851                 break;
7852         default:
7853                 status = WERR_INVALID_PARAM;
7854                 goto done;
7855         }
7856
7857         /* can't add if builtin */
7858
7859         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7860                 status = WERR_FILE_EXISTS;
7861                 goto done;
7862         }
7863
7864         count = get_ntforms(&list);
7865
7866         for (i=0; i < count; i++) {
7867                 if (strequal(form->form_name, list[i].name)) {
7868                         status = WERR_FILE_EXISTS;
7869                         goto done;
7870                 }
7871         }
7872
7873         if(!add_a_form(&list, form, &count)) {
7874                 status =  WERR_NOMEM;
7875                 goto done;
7876         }
7877
7878         become_root();
7879         write_ntforms(&list, count);
7880         unbecome_root();
7881
7882         /*
7883          * ChangeID must always be set if this is a printer
7884          */
7885
7886         if ( Printer->printer_type == SPLHND_PRINTER )
7887                 status = mod_a_printer(printer, 2);
7888
7889 done:
7890         if ( printer )
7891                 free_a_printer(&printer, 2);
7892         SAFE_FREE(list);
7893
7894         return status;
7895 }
7896
7897 /****************************************************************
7898  _spoolss_DeleteForm
7899 ****************************************************************/
7900
7901 WERROR _spoolss_DeleteForm(pipes_struct *p,
7902                            struct spoolss_DeleteForm *r)
7903 {
7904         const char *form_name = r->in.form_name;
7905         nt_forms_struct tmpForm;
7906         int count=0;
7907         nt_forms_struct *list=NULL;
7908         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7909         int snum = -1;
7910         WERROR status = WERR_OK;
7911         NT_PRINTER_INFO_LEVEL *printer = NULL;
7912         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7913         bool ret = false;
7914
7915         DEBUG(5,("_spoolss_DeleteForm\n"));
7916
7917         if (!Printer) {
7918                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7919                         OUR_HANDLE(r->in.handle)));
7920                 return WERR_BADFID;
7921         }
7922
7923         /* forms can be deleted on printer of on the print server handle */
7924
7925         if ( Printer->printer_type == SPLHND_PRINTER )
7926         {
7927                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7928                         return WERR_BADFID;
7929
7930                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7931                 if (!W_ERROR_IS_OK(status))
7932                         goto done;
7933         }
7934
7935         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7936              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7937              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7938                                           p->server_info->info3->base.domain.string,
7939                                           NULL,
7940                                           p->server_info->ptok,
7941                                           lp_printer_admin(snum))) {
7942                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7943                 return WERR_ACCESS_DENIED;
7944         }
7945
7946
7947         /* can't delete if builtin */
7948
7949         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7950                 status = WERR_INVALID_PARAM;
7951                 goto done;
7952         }
7953
7954         count = get_ntforms(&list);
7955
7956         become_root();
7957         ret = delete_a_form(&list, form_name, &count, &status);
7958         unbecome_root();
7959         if (ret == false) {
7960                 goto done;
7961         }
7962
7963         /*
7964          * ChangeID must always be set if this is a printer
7965          */
7966
7967         if ( Printer->printer_type == SPLHND_PRINTER )
7968                 status = mod_a_printer(printer, 2);
7969
7970 done:
7971         if ( printer )
7972                 free_a_printer(&printer, 2);
7973         SAFE_FREE(list);
7974
7975         return status;
7976 }
7977
7978 /****************************************************************
7979  _spoolss_SetForm
7980 ****************************************************************/
7981
7982 WERROR _spoolss_SetForm(pipes_struct *p,
7983                         struct spoolss_SetForm *r)
7984 {
7985         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7986         nt_forms_struct tmpForm;
7987         int snum = -1;
7988         WERROR status = WERR_OK;
7989         NT_PRINTER_INFO_LEVEL *printer = NULL;
7990         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7991
7992         int count=0;
7993         nt_forms_struct *list=NULL;
7994         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7995
7996         DEBUG(5,("_spoolss_SetForm\n"));
7997
7998         if (!Printer) {
7999                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8000                         OUR_HANDLE(r->in.handle)));
8001                 return WERR_BADFID;
8002         }
8003
8004         /* forms can be modified on printer of on the print server handle */
8005
8006         if ( Printer->printer_type == SPLHND_PRINTER )
8007         {
8008                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8009                         return WERR_BADFID;
8010
8011                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8012                 if (!W_ERROR_IS_OK(status))
8013                         goto done;
8014         }
8015
8016         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8017            and not a printer admin, then fail */
8018
8019         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8020              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8021              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8022                                           p->server_info->info3->base.domain.string,
8023                                           NULL,
8024                                           p->server_info->ptok,
8025                                           lp_printer_admin(snum))) {
8026                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8027                 status = WERR_ACCESS_DENIED;
8028                 goto done;
8029         }
8030
8031         /* can't set if builtin */
8032         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8033                 status = WERR_INVALID_PARAM;
8034                 goto done;
8035         }
8036
8037         count = get_ntforms(&list);
8038         update_a_form(&list, form, count);
8039         become_root();
8040         write_ntforms(&list, count);
8041         unbecome_root();
8042
8043         /*
8044          * ChangeID must always be set if this is a printer
8045          */
8046
8047         if ( Printer->printer_type == SPLHND_PRINTER )
8048                 status = mod_a_printer(printer, 2);
8049
8050
8051 done:
8052         if ( printer )
8053                 free_a_printer(&printer, 2);
8054         SAFE_FREE(list);
8055
8056         return status;
8057 }
8058
8059 /****************************************************************************
8060  fill_print_processor1
8061 ****************************************************************************/
8062
8063 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8064                                     struct spoolss_PrintProcessorInfo1 *r,
8065                                     const char *print_processor_name)
8066 {
8067         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8068         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8069
8070         return WERR_OK;
8071 }
8072
8073 /****************************************************************************
8074  enumprintprocessors level 1.
8075 ****************************************************************************/
8076
8077 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8078                                           union spoolss_PrintProcessorInfo **info_p,
8079                                           uint32_t *count)
8080 {
8081         union spoolss_PrintProcessorInfo *info;
8082         WERROR result;
8083
8084         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8085         W_ERROR_HAVE_NO_MEMORY(info);
8086
8087         *count = 1;
8088
8089         result = fill_print_processor1(info, &info[0].info1, "winprint");
8090         if (!W_ERROR_IS_OK(result)) {
8091                 goto out;
8092         }
8093
8094  out:
8095         if (!W_ERROR_IS_OK(result)) {
8096                 TALLOC_FREE(info);
8097                 *count = 0;
8098                 return result;
8099         }
8100
8101         *info_p = info;
8102
8103         return WERR_OK;
8104 }
8105
8106 /****************************************************************
8107  _spoolss_EnumPrintProcessors
8108 ****************************************************************/
8109
8110 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8111                                     struct spoolss_EnumPrintProcessors *r)
8112 {
8113         WERROR result;
8114
8115         /* that's an [in out] buffer */
8116
8117         if (!r->in.buffer && (r->in.offered != 0)) {
8118                 return WERR_INVALID_PARAM;
8119         }
8120
8121         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8122
8123         /*
8124          * Enumerate the print processors ...
8125          *
8126          * Just reply with "winprint", to keep NT happy
8127          * and I can use my nice printer checker.
8128          */
8129
8130         *r->out.count = 0;
8131         *r->out.needed = 0;
8132         *r->out.info = NULL;
8133
8134         switch (r->in.level) {
8135         case 1:
8136                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8137                                                      r->out.count);
8138                 break;
8139         default:
8140                 return WERR_UNKNOWN_LEVEL;
8141         }
8142
8143         if (!W_ERROR_IS_OK(result)) {
8144                 return result;
8145         }
8146
8147         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8148                                                      spoolss_EnumPrintProcessors,
8149                                                      *r->out.info, r->in.level,
8150                                                      *r->out.count);
8151         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8152         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8153
8154         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8155 }
8156
8157 /****************************************************************************
8158  fill_printprocdatatype1
8159 ****************************************************************************/
8160
8161 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8162                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8163                                       const char *name_array)
8164 {
8165         r->name_array = talloc_strdup(mem_ctx, name_array);
8166         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8167
8168         return WERR_OK;
8169 }
8170
8171 /****************************************************************************
8172  enumprintprocdatatypes level 1.
8173 ****************************************************************************/
8174
8175 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8176                                              union spoolss_PrintProcDataTypesInfo **info_p,
8177                                              uint32_t *count)
8178 {
8179         WERROR result;
8180         union spoolss_PrintProcDataTypesInfo *info;
8181
8182         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8183         W_ERROR_HAVE_NO_MEMORY(info);
8184
8185         *count = 1;
8186
8187         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8188         if (!W_ERROR_IS_OK(result)) {
8189                 goto out;
8190         }
8191
8192  out:
8193         if (!W_ERROR_IS_OK(result)) {
8194                 TALLOC_FREE(info);
8195                 *count = 0;
8196                 return result;
8197         }
8198
8199         *info_p = info;
8200
8201         return WERR_OK;
8202 }
8203
8204 /****************************************************************
8205  _spoolss_EnumPrintProcDataTypes
8206 ****************************************************************/
8207
8208 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8209                                        struct spoolss_EnumPrintProcDataTypes *r)
8210 {
8211         WERROR result;
8212
8213         /* that's an [in out] buffer */
8214
8215         if (!r->in.buffer && (r->in.offered != 0)) {
8216                 return WERR_INVALID_PARAM;
8217         }
8218
8219         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8220
8221         *r->out.count = 0;
8222         *r->out.needed = 0;
8223         *r->out.info = NULL;
8224
8225         switch (r->in.level) {
8226         case 1:
8227                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8228                                                         r->out.count);
8229                 break;
8230         default:
8231                 return WERR_UNKNOWN_LEVEL;
8232         }
8233
8234         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8235                                                      spoolss_EnumPrintProcDataTypes, 
8236                                                      *r->out.info, r->in.level,
8237                                                      *r->out.count);
8238         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8239         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8240
8241         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8242 }
8243
8244 /****************************************************************************
8245  fill_monitor_1
8246 ****************************************************************************/
8247
8248 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8249                              struct spoolss_MonitorInfo1 *r,
8250                              const char *monitor_name)
8251 {
8252         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8253         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8254
8255         return WERR_OK;
8256 }
8257
8258 /****************************************************************************
8259  fill_monitor_2
8260 ****************************************************************************/
8261
8262 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8263                              struct spoolss_MonitorInfo2 *r,
8264                              const char *monitor_name,
8265                              const char *environment,
8266                              const char *dll_name)
8267 {
8268         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8269         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8270         r->environment                  = talloc_strdup(mem_ctx, environment);
8271         W_ERROR_HAVE_NO_MEMORY(r->environment);
8272         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8273         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8274
8275         return WERR_OK;
8276 }
8277
8278 /****************************************************************************
8279  enumprintmonitors level 1.
8280 ****************************************************************************/
8281
8282 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8283                                         union spoolss_MonitorInfo **info_p,
8284                                         uint32_t *count)
8285 {
8286         union spoolss_MonitorInfo *info;
8287         WERROR result = WERR_OK;
8288
8289         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8290         W_ERROR_HAVE_NO_MEMORY(info);
8291
8292         *count = 2;
8293
8294         result = fill_monitor_1(info, &info[0].info1,
8295                                 SPL_LOCAL_PORT);
8296         if (!W_ERROR_IS_OK(result)) {
8297                 goto out;
8298         }
8299
8300         result = fill_monitor_1(info, &info[1].info1,
8301                                 SPL_TCPIP_PORT);
8302         if (!W_ERROR_IS_OK(result)) {
8303                 goto out;
8304         }
8305
8306 out:
8307         if (!W_ERROR_IS_OK(result)) {
8308                 TALLOC_FREE(info);
8309                 *count = 0;
8310                 return result;
8311         }
8312
8313         *info_p = info;
8314
8315         return WERR_OK;
8316 }
8317
8318 /****************************************************************************
8319  enumprintmonitors level 2.
8320 ****************************************************************************/
8321
8322 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8323                                         union spoolss_MonitorInfo **info_p,
8324                                         uint32_t *count)
8325 {
8326         union spoolss_MonitorInfo *info;
8327         WERROR result = WERR_OK;
8328
8329         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8330         W_ERROR_HAVE_NO_MEMORY(info);
8331
8332         *count = 2;
8333
8334         result = fill_monitor_2(info, &info[0].info2,
8335                                 SPL_LOCAL_PORT,
8336                                 "Windows NT X86", /* FIXME */
8337                                 "localmon.dll");
8338         if (!W_ERROR_IS_OK(result)) {
8339                 goto out;
8340         }
8341
8342         result = fill_monitor_2(info, &info[1].info2,
8343                                 SPL_TCPIP_PORT,
8344                                 "Windows NT X86", /* FIXME */
8345                                 "tcpmon.dll");
8346         if (!W_ERROR_IS_OK(result)) {
8347                 goto out;
8348         }
8349
8350 out:
8351         if (!W_ERROR_IS_OK(result)) {
8352                 TALLOC_FREE(info);
8353                 *count = 0;
8354                 return result;
8355         }
8356
8357         *info_p = info;
8358
8359         return WERR_OK;
8360 }
8361
8362 /****************************************************************
8363  _spoolss_EnumMonitors
8364 ****************************************************************/
8365
8366 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8367                              struct spoolss_EnumMonitors *r)
8368 {
8369         WERROR result;
8370
8371         /* that's an [in out] buffer */
8372
8373         if (!r->in.buffer && (r->in.offered != 0)) {
8374                 return WERR_INVALID_PARAM;
8375         }
8376
8377         DEBUG(5,("_spoolss_EnumMonitors\n"));
8378
8379         /*
8380          * Enumerate the print monitors ...
8381          *
8382          * Just reply with "Local Port", to keep NT happy
8383          * and I can use my nice printer checker.
8384          */
8385
8386         *r->out.count = 0;
8387         *r->out.needed = 0;
8388         *r->out.info = NULL;
8389
8390         switch (r->in.level) {
8391         case 1:
8392                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8393                                                    r->out.count);
8394                 break;
8395         case 2:
8396                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8397                                                    r->out.count);
8398                 break;
8399         default:
8400                 return WERR_UNKNOWN_LEVEL;
8401         }
8402
8403         if (!W_ERROR_IS_OK(result)) {
8404                 return result;
8405         }
8406
8407         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8408                                                      spoolss_EnumMonitors, 
8409                                                      *r->out.info, r->in.level,
8410                                                      *r->out.count);
8411         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8412         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8413
8414         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8415 }
8416
8417 /****************************************************************************
8418 ****************************************************************************/
8419
8420 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8421                              const print_queue_struct *queue,
8422                              int count, int snum,
8423                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8424                              uint32_t jobid,
8425                              struct spoolss_JobInfo1 *r)
8426 {
8427         int i = 0;
8428         bool found = false;
8429
8430         for (i=0; i<count; i++) {
8431                 if (queue[i].job == (int)jobid) {
8432                         found = true;
8433                         break;
8434                 }
8435         }
8436
8437         if (found == false) {
8438                 /* NT treats not found as bad param... yet another bad choice */
8439                 return WERR_INVALID_PARAM;
8440         }
8441
8442         return fill_job_info1(mem_ctx,
8443                               r,
8444                               &queue[i],
8445                               i,
8446                               snum,
8447                               ntprinter);
8448 }
8449
8450 /****************************************************************************
8451 ****************************************************************************/
8452
8453 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8454                              const print_queue_struct *queue,
8455                              int count, int snum,
8456                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8457                              uint32_t jobid,
8458                              struct spoolss_JobInfo2 *r)
8459 {
8460         int i = 0;
8461         bool found = false;
8462         struct spoolss_DeviceMode *devmode;
8463         NT_DEVICEMODE *nt_devmode;
8464         WERROR result;
8465
8466         for (i=0; i<count; i++) {
8467                 if (queue[i].job == (int)jobid) {
8468                         found = true;
8469                         break;
8470                 }
8471         }
8472
8473         if (found == false) {
8474                 /* NT treats not found as bad param... yet another bad
8475                    choice */
8476                 return WERR_INVALID_PARAM;
8477         }
8478
8479         /*
8480          * if the print job does not have a DEVMODE associated with it,
8481          * just use the one for the printer. A NULL devicemode is not
8482          *  a failure condition
8483          */
8484
8485         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8486         if (nt_devmode) {
8487                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8488                 W_ERROR_HAVE_NO_MEMORY(devmode);
8489                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8490                 if (!W_ERROR_IS_OK(result)) {
8491                         return result;
8492                 }
8493         } else {
8494                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8495                 W_ERROR_HAVE_NO_MEMORY(devmode);
8496         }
8497
8498         return fill_job_info2(mem_ctx,
8499                               r,
8500                               &queue[i],
8501                               i,
8502                               snum,
8503                               ntprinter,
8504                               devmode);
8505 }
8506
8507 /****************************************************************
8508  _spoolss_GetJob
8509 ****************************************************************/
8510
8511 WERROR _spoolss_GetJob(pipes_struct *p,
8512                        struct spoolss_GetJob *r)
8513 {
8514         WERROR result = WERR_OK;
8515         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8516         int snum;
8517         int count;
8518         print_queue_struct      *queue = NULL;
8519         print_status_struct prt_status;
8520
8521         /* that's an [in out] buffer */
8522
8523         if (!r->in.buffer && (r->in.offered != 0)) {
8524                 return WERR_INVALID_PARAM;
8525         }
8526
8527         DEBUG(5,("_spoolss_GetJob\n"));
8528
8529         *r->out.needed = 0;
8530
8531         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8532                 return WERR_BADFID;
8533         }
8534
8535         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8536         if (!W_ERROR_IS_OK(result)) {
8537                 return result;
8538         }
8539
8540         count = print_queue_status(snum, &queue, &prt_status);
8541
8542         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8543                      count, prt_status.status, prt_status.message));
8544
8545         switch (r->in.level) {
8546         case 1:
8547                 result = getjob_level_1(p->mem_ctx,
8548                                         queue, count, snum, ntprinter,
8549                                         r->in.job_id, &r->out.info->info1);
8550                 break;
8551         case 2:
8552                 result = getjob_level_2(p->mem_ctx,
8553                                         queue, count, snum, ntprinter,
8554                                         r->in.job_id, &r->out.info->info2);
8555                 break;
8556         default:
8557                 result = WERR_UNKNOWN_LEVEL;
8558                 break;
8559         }
8560
8561         SAFE_FREE(queue);
8562         free_a_printer(&ntprinter, 2);
8563
8564         if (!W_ERROR_IS_OK(result)) {
8565                 TALLOC_FREE(r->out.info);
8566                 return result;
8567         }
8568
8569         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8570                                                                                    r->in.level);
8571         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8572
8573         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8574 }
8575
8576 /****************************************************************
8577  _spoolss_GetPrinterDataEx
8578 ****************************************************************/
8579
8580 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8581                                  struct spoolss_GetPrinterDataEx *r)
8582 {
8583
8584         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8585         struct regval_blob              *val = NULL;
8586         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8587         int                     snum = 0;
8588         WERROR result = WERR_OK;
8589         DATA_BLOB blob;
8590
8591         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8592
8593         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8594                 r->in.key_name, r->in.value_name));
8595
8596         /* in case of problem, return some default values */
8597
8598         *r->out.needed  = 0;
8599         *r->out.type    = REG_NONE;
8600
8601         if (!Printer) {
8602                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8603                         OUR_HANDLE(r->in.handle)));
8604                 result = WERR_BADFID;
8605                 goto done;
8606         }
8607
8608         /* Is the handle to a printer or to the server? */
8609
8610         if (Printer->printer_type == SPLHND_SERVER) {
8611
8612                 union spoolss_PrinterData data;
8613
8614                 result = getprinterdata_printer_server(p->mem_ctx,
8615                                                        r->in.value_name,
8616                                                        r->out.type,
8617                                                        &data);
8618                 if (!W_ERROR_IS_OK(result)) {
8619                         goto done;
8620                 }
8621
8622                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8623                                                   *r->out.type, &data);
8624                 if (!W_ERROR_IS_OK(result)) {
8625                         goto done;
8626                 }
8627
8628                 *r->out.needed = blob.length;
8629
8630                 if (r->in.offered >= *r->out.needed) {
8631                         memcpy(r->out.data, blob.data, blob.length);
8632                 }
8633
8634                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8635         }
8636
8637         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8638                 result = WERR_BADFID;
8639                 goto done;
8640         }
8641
8642         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8643         if (!W_ERROR_IS_OK(result)) {
8644                 goto done;
8645         }
8646
8647         /* check to see if the keyname is valid */
8648         if (!strlen(r->in.key_name)) {
8649                 result = WERR_INVALID_PARAM;
8650                 goto done;
8651         }
8652
8653         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8654
8655         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8656             strequal(r->in.value_name, "ChangeId")) {
8657                 *r->out.type = REG_DWORD;
8658                 *r->out.needed = 4;
8659                 if (r->in.offered >= *r->out.needed) {
8660                         SIVAL(r->out.data, 0, printer->info_2->changeid);
8661                         result = WERR_OK;
8662                 }
8663                 goto done;
8664         }
8665
8666         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8667                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8668                         "Invalid keyname [%s]\n", r->in.key_name ));
8669                 result = WERR_BADFILE;
8670                 goto done;
8671         }
8672
8673         val = get_printer_data(printer->info_2,
8674                                r->in.key_name, r->in.value_name);
8675         if (!val) {
8676                 result = WERR_BADFILE;
8677                 goto done;
8678         }
8679
8680         *r->out.needed = regval_size(val);
8681         *r->out.type = regval_type(val);
8682
8683         if (r->in.offered >= *r->out.needed) {
8684                 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8685         }
8686  done:
8687         if (printer) {
8688                 free_a_printer(&printer, 2);
8689         }
8690
8691         if (!W_ERROR_IS_OK(result)) {
8692                 return result;
8693         }
8694
8695         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8696         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8697
8698         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8699 }
8700
8701 /****************************************************************
8702  _spoolss_SetPrinterDataEx
8703 ****************************************************************/
8704
8705 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8706                                  struct spoolss_SetPrinterDataEx *r)
8707 {
8708         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8709         int                     snum = 0;
8710         WERROR                  result = WERR_OK;
8711         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8712         char                    *oid_string;
8713
8714         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8715
8716         /* From MSDN documentation of SetPrinterDataEx: pass request to
8717            SetPrinterData if key is "PrinterDriverData" */
8718
8719         if (!Printer) {
8720                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8721                         OUR_HANDLE(r->in.handle)));
8722                 return WERR_BADFID;
8723         }
8724
8725         if (Printer->printer_type == SPLHND_SERVER) {
8726                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8727                         "Not implemented for server handles yet\n"));
8728                 return WERR_INVALID_PARAM;
8729         }
8730
8731         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8732                 return WERR_BADFID;
8733         }
8734
8735         /*
8736          * Access check : NT returns "access denied" if you make a
8737          * SetPrinterData call without the necessary privildge.
8738          * we were originally returning OK if nothing changed
8739          * which made Win2k issue **a lot** of SetPrinterData
8740          * when connecting to a printer  --jerry
8741          */
8742
8743         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8744                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8745                         "change denied by handle access permissions\n"));
8746                 return WERR_ACCESS_DENIED;
8747         }
8748
8749         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8750         if (!W_ERROR_IS_OK(result)) {
8751                 return result;
8752         }
8753
8754         /* check for OID in valuename */
8755
8756         oid_string = strchr(r->in.value_name, ',');
8757         if (oid_string) {
8758                 *oid_string = '\0';
8759                 oid_string++;
8760         }
8761
8762         /* save the registry data */
8763
8764         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8765                                     r->in.type, r->in.data, r->in.offered);
8766
8767         if (W_ERROR_IS_OK(result)) {
8768                 /* save the OID if one was specified */
8769                 if (oid_string) {
8770                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8771                                 r->in.key_name, SPOOL_OID_KEY);
8772                         if (!str) {
8773                                 result = WERR_NOMEM;
8774                                 goto done;
8775                         }
8776
8777                         /*
8778                          * I'm not checking the status here on purpose.  Don't know
8779                          * if this is right, but I'm returning the status from the
8780                          * previous set_printer_dataex() call.  I have no idea if
8781                          * this is right.    --jerry
8782                          */
8783
8784                         set_printer_dataex(printer, str, r->in.value_name,
8785                                            REG_SZ, (uint8_t *)oid_string,
8786                                            strlen(oid_string)+1);
8787                 }
8788
8789                 result = mod_a_printer(printer, 2);
8790         }
8791
8792  done:
8793         free_a_printer(&printer, 2);
8794
8795         return result;
8796 }
8797
8798 /****************************************************************
8799  _spoolss_DeletePrinterDataEx
8800 ****************************************************************/
8801
8802 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8803                                     struct spoolss_DeletePrinterDataEx *r)
8804 {
8805         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8806         int             snum=0;
8807         WERROR          status = WERR_OK;
8808         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8809
8810         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8811
8812         if (!Printer) {
8813                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8814                         "Invalid handle (%s:%u:%u).\n",
8815                         OUR_HANDLE(r->in.handle)));
8816                 return WERR_BADFID;
8817         }
8818
8819         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8820                 return WERR_BADFID;
8821
8822         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8823                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8824                         "printer properties change denied by handle\n"));
8825                 return WERR_ACCESS_DENIED;
8826         }
8827
8828         if (!r->in.value_name || !r->in.key_name) {
8829                 return WERR_NOMEM;
8830         }
8831
8832         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8833         if (!W_ERROR_IS_OK(status))
8834                 return status;
8835
8836         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8837
8838         if ( W_ERROR_IS_OK(status) )
8839                 mod_a_printer( printer, 2 );
8840
8841         free_a_printer(&printer, 2);
8842
8843         return status;
8844 }
8845
8846 /****************************************************************
8847  _spoolss_EnumPrinterKey
8848 ****************************************************************/
8849
8850 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8851                                struct spoolss_EnumPrinterKey *r)
8852 {
8853         fstring         *keynames = NULL;
8854         int             num_keys;
8855         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8856         NT_PRINTER_DATA *data;
8857         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8858         int             snum = 0;
8859         WERROR          result = WERR_BADFILE;
8860         int i;
8861         const char **array = NULL;
8862         DATA_BLOB blob;
8863
8864         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8865
8866         if (!Printer) {
8867                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8868                         OUR_HANDLE(r->in.handle)));
8869                 return WERR_BADFID;
8870         }
8871
8872         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8873                 return WERR_BADFID;
8874         }
8875
8876         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8877         if (!W_ERROR_IS_OK(result)) {
8878                 return result;
8879         }
8880
8881         /* get the list of subkey names */
8882
8883         data = printer->info_2->data;
8884
8885         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8886         if (num_keys == -1) {
8887                 result = WERR_BADFILE;
8888                 goto done;
8889         }
8890
8891         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8892         if (!array) {
8893                 result = WERR_NOMEM;
8894                 goto done;
8895         }
8896
8897         if (!num_keys) {
8898                 array[0] = talloc_strdup(array, "");
8899                 if (!array[0]) {
8900                         result = WERR_NOMEM;
8901                         goto done;
8902                 }
8903         }
8904
8905         for (i=0; i < num_keys; i++) {
8906
8907                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8908                         keynames[i]));
8909
8910                 array[i] = talloc_strdup(array, keynames[i]);
8911                 if (!array[i]) {
8912                         result = WERR_NOMEM;
8913                         goto done;
8914                 }
8915         }
8916
8917         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8918                 result = WERR_NOMEM;
8919                 goto done;
8920         }
8921
8922         *r->out._ndr_size = r->in.offered / 2;
8923         *r->out.needed = blob.length;
8924
8925         if (r->in.offered < *r->out.needed) {
8926                 result = WERR_MORE_DATA;
8927         } else {
8928                 result = WERR_OK;
8929                 r->out.key_buffer->string_array = array;
8930         }
8931
8932  done:
8933         if (!W_ERROR_IS_OK(result)) {
8934                 TALLOC_FREE(array);
8935                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8936                         *r->out.needed = 0;
8937                 }
8938         }
8939
8940         free_a_printer(&printer, 2);
8941         SAFE_FREE(keynames);
8942
8943         return result;
8944 }
8945
8946 /****************************************************************
8947  _spoolss_DeletePrinterKey
8948 ****************************************************************/
8949
8950 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8951                                  struct spoolss_DeletePrinterKey *r)
8952 {
8953         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8954         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8955         int                     snum=0;
8956         WERROR                  status;
8957
8958         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8959
8960         if (!Printer) {
8961                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8962                         OUR_HANDLE(r->in.handle)));
8963                 return WERR_BADFID;
8964         }
8965
8966         /* if keyname == NULL, return error */
8967
8968         if ( !r->in.key_name )
8969                 return WERR_INVALID_PARAM;
8970
8971         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8972                 return WERR_BADFID;
8973
8974         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8975                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8976                         "printer properties change denied by handle\n"));
8977                 return WERR_ACCESS_DENIED;
8978         }
8979
8980         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8981         if (!W_ERROR_IS_OK(status))
8982                 return status;
8983
8984         /* delete the key and all subneys */
8985
8986         status = delete_all_printer_data( printer->info_2, r->in.key_name );
8987
8988         if ( W_ERROR_IS_OK(status) )
8989                 status = mod_a_printer(printer, 2);
8990
8991         free_a_printer( &printer, 2 );
8992
8993         return status;
8994 }
8995
8996 /****************************************************************
8997 ****************************************************************/
8998
8999 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9000                                                    struct regval_blob *v,
9001                                                    struct spoolss_PrinterEnumValues *r)
9002 {
9003         r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9004         W_ERROR_HAVE_NO_MEMORY(r->data);
9005
9006         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9007         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9008
9009         r->value_name_len = strlen_m_term(regval_name(v)) * 2;
9010
9011         r->type         = regval_type(v);
9012         r->data_length  = regval_size(v);
9013
9014         if (r->data_length) {
9015                 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9016         }
9017
9018         return WERR_OK;
9019 }
9020
9021 /****************************************************************
9022  _spoolss_EnumPrinterDataEx
9023 ****************************************************************/
9024
9025 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9026                                   struct spoolss_EnumPrinterDataEx *r)
9027 {
9028         uint32_t        count = 0;
9029         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9030         struct spoolss_PrinterEnumValues *info = NULL;
9031         NT_PRINTER_DATA         *p_data;
9032         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9033         int             snum;
9034         WERROR          result;
9035         int             key_index;
9036         int             i;
9037
9038         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9039
9040         *r->out.count = 0;
9041         *r->out.needed = 0;
9042         *r->out.info = NULL;
9043
9044         if (!Printer) {
9045                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9046                         OUR_HANDLE(r->in.handle)));
9047                 return WERR_BADFID;
9048         }
9049
9050         /*
9051          * first check for a keyname of NULL or "".  Win2k seems to send
9052          * this a lot and we should send back WERR_INVALID_PARAM
9053          * no need to spend time looking up the printer in this case.
9054          * --jerry
9055          */
9056
9057         if (!strlen(r->in.key_name)) {
9058                 result = WERR_INVALID_PARAM;
9059                 goto done;
9060         }
9061
9062         /* get the printer off of disk */
9063
9064         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9065                 return WERR_BADFID;
9066         }
9067
9068         ZERO_STRUCT(printer);
9069         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9070         if (!W_ERROR_IS_OK(result)) {
9071                 return result;
9072         }
9073
9074         /* now look for a match on the key name */
9075
9076         p_data = printer->info_2->data;
9077
9078         key_index = lookup_printerkey(p_data, r->in.key_name);
9079         if (key_index == -1) {
9080                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9081                         r->in.key_name));
9082                 result = WERR_INVALID_PARAM;
9083                 goto done;
9084         }
9085
9086         /* allocate the memory for the array of pointers -- if necessary */
9087
9088         count = regval_ctr_numvals(p_data->keys[key_index].values);
9089         if (!count) {
9090                 result = WERR_OK; /* ??? */
9091                 goto done;
9092         }
9093
9094         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9095                                  struct spoolss_PrinterEnumValues,
9096                                  count);
9097         if (!info) {
9098                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9099                 result = WERR_NOMEM;
9100                 goto done;
9101         }
9102
9103         /*
9104          * loop through all params and build the array to pass
9105          * back to the  client
9106          */
9107
9108         for (i=0; i < count; i++) {
9109
9110                 struct regval_blob      *val;
9111
9112                 /* lookup the registry value */
9113
9114                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9115
9116                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9117
9118                 /* copy the data */
9119
9120                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9121                 if (!W_ERROR_IS_OK(result)) {
9122                         goto done;
9123                 }
9124         }
9125
9126 #if 0 /* FIXME - gd */
9127         /* housekeeping information in the reply */
9128
9129         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9130          * the hand marshalled container size is a multiple
9131          * of 4 bytes for RPC alignment.
9132          */
9133
9134         if (needed % 4) {
9135                 needed += 4-(needed % 4);
9136         }
9137 #endif
9138         *r->out.count   = count;
9139         *r->out.info    = info;
9140
9141  done:
9142
9143         if (printer) {
9144                 free_a_printer(&printer, 2);
9145         }
9146
9147         if (!W_ERROR_IS_OK(result)) {
9148                 return result;
9149         }
9150
9151         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9152                                                spoolss_EnumPrinterDataEx, 
9153                                                *r->out.info,
9154                                                *r->out.count);
9155         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9156         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9157
9158         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9159 }
9160
9161 /****************************************************************************
9162 ****************************************************************************/
9163
9164 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9165                                                  const char *servername,
9166                                                  const char *environment,
9167                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9168 {
9169         WERROR werr;
9170         char *path = NULL;
9171
9172         werr = compose_spoolss_server_path(mem_ctx,
9173                                            servername,
9174                                            environment,
9175                                            SPOOLSS_PRTPROCS_PATH,
9176                                            &path);
9177         if (!W_ERROR_IS_OK(werr)) {
9178                 return werr;
9179         }
9180
9181         DEBUG(4,("print processor directory: [%s]\n", path));
9182
9183         r->directory_name = path;
9184
9185         return WERR_OK;
9186 }
9187
9188 /****************************************************************
9189  _spoolss_GetPrintProcessorDirectory
9190 ****************************************************************/
9191
9192 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9193                                            struct spoolss_GetPrintProcessorDirectory *r)
9194 {
9195         WERROR result;
9196
9197         /* that's an [in out] buffer */
9198
9199         if (!r->in.buffer && (r->in.offered != 0)) {
9200                 return WERR_INVALID_PARAM;
9201         }
9202
9203         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9204                 r->in.level));
9205
9206         *r->out.needed = 0;
9207
9208         /* r->in.level is ignored */
9209
9210         /* We always should reply with a local print processor directory so that
9211          * users are not forced to have a [prnproc$] share on the Samba spoolss
9212          * server - Guenther */
9213
9214         result = getprintprocessordirectory_level_1(p->mem_ctx,
9215                                                     NULL, /* r->in.server */
9216                                                     r->in.environment,
9217                                                     &r->out.info->info1);
9218         if (!W_ERROR_IS_OK(result)) {
9219                 TALLOC_FREE(r->out.info);
9220                 return result;
9221         }
9222
9223         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9224                                                                                    r->out.info, r->in.level);
9225         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9226
9227         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9228 }
9229
9230 /*******************************************************************
9231  ********************************************************************/
9232
9233 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9234                                const char *dllname)
9235 {
9236         enum ndr_err_code ndr_err;
9237         struct spoolss_MonitorUi ui;
9238
9239         ui.dll_name = dllname;
9240
9241         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9242                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9243         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9244                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9245         }
9246         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9247 }
9248
9249 /*******************************************************************
9250  Streams the monitor UI DLL name in UNICODE
9251 *******************************************************************/
9252
9253 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9254                                NT_USER_TOKEN *token, DATA_BLOB *in,
9255                                DATA_BLOB *out, uint32_t *needed)
9256 {
9257         const char *dllname = "tcpmonui.dll";
9258
9259         *needed = (strlen(dllname)+1) * 2;
9260
9261         if (out->length < *needed) {
9262                 return WERR_INSUFFICIENT_BUFFER;
9263         }
9264
9265         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9266                 return WERR_NOMEM;
9267         }
9268
9269         return WERR_OK;
9270 }
9271
9272 /*******************************************************************
9273  ********************************************************************/
9274
9275 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9276                              struct spoolss_PortData1 *port1,
9277                              const DATA_BLOB *buf)
9278 {
9279         enum ndr_err_code ndr_err;
9280         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9281                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9282         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9283                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9284         }
9285         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9286 }
9287
9288 /*******************************************************************
9289  ********************************************************************/
9290
9291 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9292                              struct spoolss_PortData2 *port2,
9293                              const DATA_BLOB *buf)
9294 {
9295         enum ndr_err_code ndr_err;
9296         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9297                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9298         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9299                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9300         }
9301         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9302 }
9303
9304 /*******************************************************************
9305  Create a new TCP/IP port
9306 *******************************************************************/
9307
9308 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9309                              NT_USER_TOKEN *token, DATA_BLOB *in,
9310                              DATA_BLOB *out, uint32_t *needed)
9311 {
9312         struct spoolss_PortData1 port1;
9313         struct spoolss_PortData2 port2;
9314         char *device_uri = NULL;
9315         uint32_t version;
9316
9317         const char *portname;
9318         const char *hostaddress;
9319         const char *queue;
9320         uint32_t port_number;
9321         uint32_t protocol;
9322
9323         /* peek for spoolss_PortData version */
9324
9325         if (!in || (in->length < (128 + 4))) {
9326                 return WERR_GENERAL_FAILURE;
9327         }
9328
9329         version = IVAL(in->data, 128);
9330
9331         switch (version) {
9332                 case 1:
9333                         ZERO_STRUCT(port1);
9334
9335                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9336                                 return WERR_NOMEM;
9337                         }
9338
9339                         portname        = port1.portname;
9340                         hostaddress     = port1.hostaddress;
9341                         queue           = port1.queue;
9342                         protocol        = port1.protocol;
9343                         port_number     = port1.port_number;
9344
9345                         break;
9346                 case 2:
9347                         ZERO_STRUCT(port2);
9348
9349                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9350                                 return WERR_NOMEM;
9351                         }
9352
9353                         portname        = port2.portname;
9354                         hostaddress     = port2.hostaddress;
9355                         queue           = port2.queue;
9356                         protocol        = port2.protocol;
9357                         port_number     = port2.port_number;
9358
9359                         break;
9360                 default:
9361                         DEBUG(1,("xcvtcp_addport: "
9362                                 "unknown version of port_data: %d\n", version));
9363                         return WERR_UNKNOWN_PORT;
9364         }
9365
9366         /* create the device URI and call the add_port_hook() */
9367
9368         switch (protocol) {
9369         case PROTOCOL_RAWTCP_TYPE:
9370                 device_uri = talloc_asprintf(mem_ctx,
9371                                 "socket://%s:%d/", hostaddress,
9372                                 port_number);
9373                 break;
9374
9375         case PROTOCOL_LPR_TYPE:
9376                 device_uri = talloc_asprintf(mem_ctx,
9377                         "lpr://%s/%s", hostaddress, queue );
9378                 break;
9379
9380         default:
9381                 return WERR_UNKNOWN_PORT;
9382         }
9383
9384         if (!device_uri) {
9385                 return WERR_NOMEM;
9386         }
9387
9388         return add_port_hook(mem_ctx, token, portname, device_uri);
9389 }
9390
9391 /*******************************************************************
9392 *******************************************************************/
9393
9394 struct xcv_api_table xcvtcp_cmds[] = {
9395         { "MonitorUI",  xcvtcp_monitorui },
9396         { "AddPort",    xcvtcp_addport},
9397         { NULL,         NULL }
9398 };
9399
9400 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9401                                      NT_USER_TOKEN *token, const char *command,
9402                                      DATA_BLOB *inbuf,
9403                                      DATA_BLOB *outbuf,
9404                                      uint32_t *needed )
9405 {
9406         int i;
9407
9408         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9409
9410         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9411                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9412                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9413         }
9414
9415         return WERR_BADFUNC;
9416 }
9417
9418 /*******************************************************************
9419 *******************************************************************/
9420 #if 0   /* don't support management using the "Local Port" monitor */
9421
9422 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9423                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9424                                  DATA_BLOB *out, uint32_t *needed)
9425 {
9426         const char *dllname = "localui.dll";
9427
9428         *needed = (strlen(dllname)+1) * 2;
9429
9430         if (out->length < *needed) {
9431                 return WERR_INSUFFICIENT_BUFFER;
9432         }
9433
9434         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9435                 return WERR_NOMEM;
9436         }
9437
9438         return WERR_OK;
9439 }
9440
9441 /*******************************************************************
9442 *******************************************************************/
9443
9444 struct xcv_api_table xcvlocal_cmds[] = {
9445         { "MonitorUI",  xcvlocal_monitorui },
9446         { NULL,         NULL }
9447 };
9448 #else
9449 struct xcv_api_table xcvlocal_cmds[] = {
9450         { NULL,         NULL }
9451 };
9452 #endif
9453
9454
9455
9456 /*******************************************************************
9457 *******************************************************************/
9458
9459 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9460                                        NT_USER_TOKEN *token, const char *command,
9461                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9462                                        uint32_t *needed)
9463 {
9464         int i;
9465
9466         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9467
9468         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9469                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9470                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9471         }
9472         return WERR_BADFUNC;
9473 }
9474
9475 /****************************************************************
9476  _spoolss_XcvData
9477 ****************************************************************/
9478
9479 WERROR _spoolss_XcvData(pipes_struct *p,
9480                         struct spoolss_XcvData *r)
9481 {
9482         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9483         DATA_BLOB out_data = data_blob_null;
9484         WERROR werror;
9485
9486         if (!Printer) {
9487                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9488                         OUR_HANDLE(r->in.handle)));
9489                 return WERR_BADFID;
9490         }
9491
9492         /* Has to be a handle to the TCP/IP port monitor */
9493
9494         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9495                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9496                 return WERR_BADFID;
9497         }
9498
9499         /* requires administrative access to the server */
9500
9501         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9502                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9503                 return WERR_ACCESS_DENIED;
9504         }
9505
9506         /* Allocate the outgoing buffer */
9507
9508         if (r->in.out_data_size) {
9509                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9510                 if (out_data.data == NULL) {
9511                         return WERR_NOMEM;
9512                 }
9513         }
9514
9515         switch ( Printer->printer_type ) {
9516         case SPLHND_PORTMON_TCP:
9517                 werror = process_xcvtcp_command(p->mem_ctx,
9518                                                 p->server_info->ptok,
9519                                                 r->in.function_name,
9520                                                 &r->in.in_data, &out_data,
9521                                                 r->out.needed);
9522                 break;
9523         case SPLHND_PORTMON_LOCAL:
9524                 werror = process_xcvlocal_command(p->mem_ctx,
9525                                                   p->server_info->ptok,
9526                                                   r->in.function_name,
9527                                                   &r->in.in_data, &out_data,
9528                                                   r->out.needed);
9529                 break;
9530         default:
9531                 werror = WERR_INVALID_PRINT_MONITOR;
9532         }
9533
9534         if (!W_ERROR_IS_OK(werror)) {
9535                 return werror;
9536         }
9537
9538         *r->out.status_code = 0;
9539
9540         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9541                 memcpy(r->out.out_data, out_data.data,
9542                         MIN(r->in.out_data_size, out_data.length));
9543         }
9544
9545         return WERR_OK;
9546 }
9547
9548 /****************************************************************
9549  _spoolss_AddPrintProcessor
9550 ****************************************************************/
9551
9552 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9553                                   struct spoolss_AddPrintProcessor *r)
9554 {
9555         /* for now, just indicate success and ignore the add.  We'll
9556            automatically set the winprint processor for printer
9557            entries later.  Used to debug the LexMark Optra S 1855 PCL
9558            driver --jerry */
9559
9560         return WERR_OK;
9561 }
9562
9563 /****************************************************************
9564  _spoolss_AddPort
9565 ****************************************************************/
9566
9567 WERROR _spoolss_AddPort(pipes_struct *p,
9568                         struct spoolss_AddPort *r)
9569 {
9570         /* do what w2k3 does */
9571
9572         return WERR_NOT_SUPPORTED;
9573 }
9574
9575 /****************************************************************
9576  _spoolss_GetPrinterDriver
9577 ****************************************************************/
9578
9579 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9580                                  struct spoolss_GetPrinterDriver *r)
9581 {
9582         p->rng_fault_state = true;
9583         return WERR_NOT_SUPPORTED;
9584 }
9585
9586 /****************************************************************
9587  _spoolss_ReadPrinter
9588 ****************************************************************/
9589
9590 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9591                             struct spoolss_ReadPrinter *r)
9592 {
9593         p->rng_fault_state = true;
9594         return WERR_NOT_SUPPORTED;
9595 }
9596
9597 /****************************************************************
9598  _spoolss_WaitForPrinterChange
9599 ****************************************************************/
9600
9601 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9602                                      struct spoolss_WaitForPrinterChange *r)
9603 {
9604         p->rng_fault_state = true;
9605         return WERR_NOT_SUPPORTED;
9606 }
9607
9608 /****************************************************************
9609  _spoolss_ConfigurePort
9610 ****************************************************************/
9611
9612 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9613                               struct spoolss_ConfigurePort *r)
9614 {
9615         p->rng_fault_state = true;
9616         return WERR_NOT_SUPPORTED;
9617 }
9618
9619 /****************************************************************
9620  _spoolss_DeletePort
9621 ****************************************************************/
9622
9623 WERROR _spoolss_DeletePort(pipes_struct *p,
9624                            struct spoolss_DeletePort *r)
9625 {
9626         p->rng_fault_state = true;
9627         return WERR_NOT_SUPPORTED;
9628 }
9629
9630 /****************************************************************
9631  _spoolss_CreatePrinterIC
9632 ****************************************************************/
9633
9634 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9635                                 struct spoolss_CreatePrinterIC *r)
9636 {
9637         p->rng_fault_state = true;
9638         return WERR_NOT_SUPPORTED;
9639 }
9640
9641 /****************************************************************
9642  _spoolss_PlayGDIScriptOnPrinterIC
9643 ****************************************************************/
9644
9645 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9646                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9647 {
9648         p->rng_fault_state = true;
9649         return WERR_NOT_SUPPORTED;
9650 }
9651
9652 /****************************************************************
9653  _spoolss_DeletePrinterIC
9654 ****************************************************************/
9655
9656 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9657                                 struct spoolss_DeletePrinterIC *r)
9658 {
9659         p->rng_fault_state = true;
9660         return WERR_NOT_SUPPORTED;
9661 }
9662
9663 /****************************************************************
9664  _spoolss_AddPrinterConnection
9665 ****************************************************************/
9666
9667 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9668                                      struct spoolss_AddPrinterConnection *r)
9669 {
9670         p->rng_fault_state = true;
9671         return WERR_NOT_SUPPORTED;
9672 }
9673
9674 /****************************************************************
9675  _spoolss_DeletePrinterConnection
9676 ****************************************************************/
9677
9678 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9679                                         struct spoolss_DeletePrinterConnection *r)
9680 {
9681         p->rng_fault_state = true;
9682         return WERR_NOT_SUPPORTED;
9683 }
9684
9685 /****************************************************************
9686  _spoolss_PrinterMessageBox
9687 ****************************************************************/
9688
9689 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9690                                   struct spoolss_PrinterMessageBox *r)
9691 {
9692         p->rng_fault_state = true;
9693         return WERR_NOT_SUPPORTED;
9694 }
9695
9696 /****************************************************************
9697  _spoolss_AddMonitor
9698 ****************************************************************/
9699
9700 WERROR _spoolss_AddMonitor(pipes_struct *p,
9701                            struct spoolss_AddMonitor *r)
9702 {
9703         p->rng_fault_state = true;
9704         return WERR_NOT_SUPPORTED;
9705 }
9706
9707 /****************************************************************
9708  _spoolss_DeleteMonitor
9709 ****************************************************************/
9710
9711 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9712                               struct spoolss_DeleteMonitor *r)
9713 {
9714         p->rng_fault_state = true;
9715         return WERR_NOT_SUPPORTED;
9716 }
9717
9718 /****************************************************************
9719  _spoolss_DeletePrintProcessor
9720 ****************************************************************/
9721
9722 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9723                                      struct spoolss_DeletePrintProcessor *r)
9724 {
9725         p->rng_fault_state = true;
9726         return WERR_NOT_SUPPORTED;
9727 }
9728
9729 /****************************************************************
9730  _spoolss_AddPrintProvidor
9731 ****************************************************************/
9732
9733 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9734                                  struct spoolss_AddPrintProvidor *r)
9735 {
9736         p->rng_fault_state = true;
9737         return WERR_NOT_SUPPORTED;
9738 }
9739
9740 /****************************************************************
9741  _spoolss_DeletePrintProvidor
9742 ****************************************************************/
9743
9744 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9745                                     struct spoolss_DeletePrintProvidor *r)
9746 {
9747         p->rng_fault_state = true;
9748         return WERR_NOT_SUPPORTED;
9749 }
9750
9751 /****************************************************************
9752  _spoolss_FindFirstPrinterChangeNotification
9753 ****************************************************************/
9754
9755 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9756                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9757 {
9758         p->rng_fault_state = true;
9759         return WERR_NOT_SUPPORTED;
9760 }
9761
9762 /****************************************************************
9763  _spoolss_FindNextPrinterChangeNotification
9764 ****************************************************************/
9765
9766 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9767                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9768 {
9769         p->rng_fault_state = true;
9770         return WERR_NOT_SUPPORTED;
9771 }
9772
9773 /****************************************************************
9774  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9775 ****************************************************************/
9776
9777 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9778                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9779 {
9780         p->rng_fault_state = true;
9781         return WERR_NOT_SUPPORTED;
9782 }
9783
9784 /****************************************************************
9785  _spoolss_ReplyOpenPrinter
9786 ****************************************************************/
9787
9788 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9789                                  struct spoolss_ReplyOpenPrinter *r)
9790 {
9791         p->rng_fault_state = true;
9792         return WERR_NOT_SUPPORTED;
9793 }
9794
9795 /****************************************************************
9796  _spoolss_RouterReplyPrinter
9797 ****************************************************************/
9798
9799 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9800                                    struct spoolss_RouterReplyPrinter *r)
9801 {
9802         p->rng_fault_state = true;
9803         return WERR_NOT_SUPPORTED;
9804 }
9805
9806 /****************************************************************
9807  _spoolss_ReplyClosePrinter
9808 ****************************************************************/
9809
9810 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9811                                   struct spoolss_ReplyClosePrinter *r)
9812 {
9813         p->rng_fault_state = true;
9814         return WERR_NOT_SUPPORTED;
9815 }
9816
9817 /****************************************************************
9818  _spoolss_AddPortEx
9819 ****************************************************************/
9820
9821 WERROR _spoolss_AddPortEx(pipes_struct *p,
9822                           struct spoolss_AddPortEx *r)
9823 {
9824         p->rng_fault_state = true;
9825         return WERR_NOT_SUPPORTED;
9826 }
9827
9828 /****************************************************************
9829  _spoolss_RouterFindFirstPrinterChangeNotification
9830 ****************************************************************/
9831
9832 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9833                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9834 {
9835         p->rng_fault_state = true;
9836         return WERR_NOT_SUPPORTED;
9837 }
9838
9839 /****************************************************************
9840  _spoolss_SpoolerInit
9841 ****************************************************************/
9842
9843 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9844                             struct spoolss_SpoolerInit *r)
9845 {
9846         p->rng_fault_state = true;
9847         return WERR_NOT_SUPPORTED;
9848 }
9849
9850 /****************************************************************
9851  _spoolss_ResetPrinterEx
9852 ****************************************************************/
9853
9854 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9855                                struct spoolss_ResetPrinterEx *r)
9856 {
9857         p->rng_fault_state = true;
9858         return WERR_NOT_SUPPORTED;
9859 }
9860
9861 /****************************************************************
9862  _spoolss_RouterReplyPrinterEx
9863 ****************************************************************/
9864
9865 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9866                                      struct spoolss_RouterReplyPrinterEx *r)
9867 {
9868         p->rng_fault_state = true;
9869         return WERR_NOT_SUPPORTED;
9870 }
9871
9872 /****************************************************************
9873  _spoolss_44
9874 ****************************************************************/
9875
9876 WERROR _spoolss_44(pipes_struct *p,
9877                    struct spoolss_44 *r)
9878 {
9879         p->rng_fault_state = true;
9880         return WERR_NOT_SUPPORTED;
9881 }
9882
9883 /****************************************************************
9884  _spoolss_47
9885 ****************************************************************/
9886
9887 WERROR _spoolss_47(pipes_struct *p,
9888                    struct spoolss_47 *r)
9889 {
9890         p->rng_fault_state = true;
9891         return WERR_NOT_SUPPORTED;
9892 }
9893
9894 /****************************************************************
9895  _spoolss_4a
9896 ****************************************************************/
9897
9898 WERROR _spoolss_4a(pipes_struct *p,
9899                    struct spoolss_4a *r)
9900 {
9901         p->rng_fault_state = true;
9902         return WERR_NOT_SUPPORTED;
9903 }
9904
9905 /****************************************************************
9906  _spoolss_4b
9907 ****************************************************************/
9908
9909 WERROR _spoolss_4b(pipes_struct *p,
9910                    struct spoolss_4b *r)
9911 {
9912         p->rng_fault_state = true;
9913         return WERR_NOT_SUPPORTED;
9914 }
9915
9916 /****************************************************************
9917  _spoolss_4c
9918 ****************************************************************/
9919
9920 WERROR _spoolss_4c(pipes_struct *p,
9921                    struct spoolss_4c *r)
9922 {
9923         p->rng_fault_state = true;
9924         return WERR_NOT_SUPPORTED;
9925 }
9926
9927 /****************************************************************
9928  _spoolss_53
9929 ****************************************************************/
9930
9931 WERROR _spoolss_53(pipes_struct *p,
9932                    struct spoolss_53 *r)
9933 {
9934         p->rng_fault_state = true;
9935         return WERR_NOT_SUPPORTED;
9936 }
9937
9938 /****************************************************************
9939  _spoolss_55
9940 ****************************************************************/
9941
9942 WERROR _spoolss_55(pipes_struct *p,
9943                    struct spoolss_55 *r)
9944 {
9945         p->rng_fault_state = true;
9946         return WERR_NOT_SUPPORTED;
9947 }
9948
9949 /****************************************************************
9950  _spoolss_56
9951 ****************************************************************/
9952
9953 WERROR _spoolss_56(pipes_struct *p,
9954                    struct spoolss_56 *r)
9955 {
9956         p->rng_fault_state = true;
9957         return WERR_NOT_SUPPORTED;
9958 }
9959
9960 /****************************************************************
9961  _spoolss_57
9962 ****************************************************************/
9963
9964 WERROR _spoolss_57(pipes_struct *p,
9965                    struct spoolss_57 *r)
9966 {
9967         p->rng_fault_state = true;
9968         return WERR_NOT_SUPPORTED;
9969 }
9970
9971 /****************************************************************
9972  _spoolss_5a
9973 ****************************************************************/
9974
9975 WERROR _spoolss_5a(pipes_struct *p,
9976                    struct spoolss_5a *r)
9977 {
9978         p->rng_fault_state = true;
9979         return WERR_NOT_SUPPORTED;
9980 }
9981
9982 /****************************************************************
9983  _spoolss_5b
9984 ****************************************************************/
9985
9986 WERROR _spoolss_5b(pipes_struct *p,
9987                    struct spoolss_5b *r)
9988 {
9989         p->rng_fault_state = true;
9990         return WERR_NOT_SUPPORTED;
9991 }
9992
9993 /****************************************************************
9994  _spoolss_5c
9995 ****************************************************************/
9996
9997 WERROR _spoolss_5c(pipes_struct *p,
9998                    struct spoolss_5c *r)
9999 {
10000         p->rng_fault_state = true;
10001         return WERR_NOT_SUPPORTED;
10002 }
10003
10004 /****************************************************************
10005  _spoolss_5d
10006 ****************************************************************/
10007
10008 WERROR _spoolss_5d(pipes_struct *p,
10009                    struct spoolss_5d *r)
10010 {
10011         p->rng_fault_state = true;
10012         return WERR_NOT_SUPPORTED;
10013 }
10014
10015 /****************************************************************
10016  _spoolss_5e
10017 ****************************************************************/
10018
10019 WERROR _spoolss_5e(pipes_struct *p,
10020                    struct spoolss_5e *r)
10021 {
10022         p->rng_fault_state = true;
10023         return WERR_NOT_SUPPORTED;
10024 }
10025
10026 /****************************************************************
10027  _spoolss_5f
10028 ****************************************************************/
10029
10030 WERROR _spoolss_5f(pipes_struct *p,
10031                    struct spoolss_5f *r)
10032 {
10033         p->rng_fault_state = true;
10034         return WERR_NOT_SUPPORTED;
10035 }
10036
10037 /****************************************************************
10038  _spoolss_60
10039 ****************************************************************/
10040
10041 WERROR _spoolss_60(pipes_struct *p,
10042                    struct spoolss_60 *r)
10043 {
10044         p->rng_fault_state = true;
10045         return WERR_NOT_SUPPORTED;
10046 }
10047
10048 /****************************************************************
10049  _spoolss_61
10050 ****************************************************************/
10051
10052 WERROR _spoolss_61(pipes_struct *p,
10053                    struct spoolss_61 *r)
10054 {
10055         p->rng_fault_state = true;
10056         return WERR_NOT_SUPPORTED;
10057 }
10058
10059 /****************************************************************
10060  _spoolss_62
10061 ****************************************************************/
10062
10063 WERROR _spoolss_62(pipes_struct *p,
10064                    struct spoolss_62 *r)
10065 {
10066         p->rng_fault_state = true;
10067         return WERR_NOT_SUPPORTED;
10068 }
10069
10070 /****************************************************************
10071  _spoolss_63
10072 ****************************************************************/
10073
10074 WERROR _spoolss_63(pipes_struct *p,
10075                    struct spoolss_63 *r)
10076 {
10077         p->rng_fault_state = true;
10078         return WERR_NOT_SUPPORTED;
10079 }
10080
10081 /****************************************************************
10082  _spoolss_64
10083 ****************************************************************/
10084
10085 WERROR _spoolss_64(pipes_struct *p,
10086                    struct spoolss_64 *r)
10087 {
10088         p->rng_fault_state = true;
10089         return WERR_NOT_SUPPORTED;
10090 }
10091
10092 /****************************************************************
10093  _spoolss_65
10094 ****************************************************************/
10095
10096 WERROR _spoolss_65(pipes_struct *p,
10097                    struct spoolss_65 *r)
10098 {
10099         p->rng_fault_state = true;
10100         return WERR_NOT_SUPPORTED;
10101 }
10102
10103 /****************************************************************
10104  _spoolss_GetCorePrinterDrivers
10105 ****************************************************************/
10106
10107 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10108                                       struct spoolss_GetCorePrinterDrivers *r)
10109 {
10110         p->rng_fault_state = true;
10111         return WERR_NOT_SUPPORTED;
10112 }
10113
10114 /****************************************************************
10115  _spoolss_67
10116 ****************************************************************/
10117
10118 WERROR _spoolss_67(pipes_struct *p,
10119                    struct spoolss_67 *r)
10120 {
10121         p->rng_fault_state = true;
10122         return WERR_NOT_SUPPORTED;
10123 }
10124
10125 /****************************************************************
10126  _spoolss_GetPrinterDriverPackagePath
10127 ****************************************************************/
10128
10129 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10130                                             struct spoolss_GetPrinterDriverPackagePath *r)
10131 {
10132         p->rng_fault_state = true;
10133         return WERR_NOT_SUPPORTED;
10134 }
10135
10136 /****************************************************************
10137  _spoolss_69
10138 ****************************************************************/
10139
10140 WERROR _spoolss_69(pipes_struct *p,
10141                    struct spoolss_69 *r)
10142 {
10143         p->rng_fault_state = true;
10144         return WERR_NOT_SUPPORTED;
10145 }
10146
10147 /****************************************************************
10148  _spoolss_6a
10149 ****************************************************************/
10150
10151 WERROR _spoolss_6a(pipes_struct *p,
10152                    struct spoolss_6a *r)
10153 {
10154         p->rng_fault_state = true;
10155         return WERR_NOT_SUPPORTED;
10156 }
10157
10158 /****************************************************************
10159  _spoolss_6b
10160 ****************************************************************/
10161
10162 WERROR _spoolss_6b(pipes_struct *p,
10163                    struct spoolss_6b *r)
10164 {
10165         p->rng_fault_state = true;
10166         return WERR_NOT_SUPPORTED;
10167 }
10168
10169 /****************************************************************
10170  _spoolss_6c
10171 ****************************************************************/
10172
10173 WERROR _spoolss_6c(pipes_struct *p,
10174                    struct spoolss_6c *r)
10175 {
10176         p->rng_fault_state = true;
10177         return WERR_NOT_SUPPORTED;
10178 }
10179
10180 /****************************************************************
10181  _spoolss_6d
10182 ****************************************************************/
10183
10184 WERROR _spoolss_6d(pipes_struct *p,
10185                    struct spoolss_6d *r)
10186 {
10187         p->rng_fault_state = true;
10188         return WERR_NOT_SUPPORTED;
10189 }