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