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