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