s3-spoolss: in spoolss_EnumPrinters r->in.server is a *unique* pointer!
[samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35         ((info)?ndr_size_##fn(info, level, ic, 0):0)
36
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
39
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
42
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44
45
46 extern userdom_struct current_user_info;
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_RPC_SRV
50
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
53 #endif
54
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32_t counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected == true) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected = false;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231                                                 struct policy_handle *hnd)
232 {
233         Printer_entry *find_printer = NULL;
234
235         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
237                 return NULL;
238         }
239
240         return find_printer;
241 }
242
243 /****************************************************************************
244  Close printer index by handle.
245 ****************************************************************************/
246
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
248 {
249         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250
251         if (!Printer) {
252                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
253                         OUR_HANDLE(hnd)));
254                 return false;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return true;
260 }
261
262 /****************************************************************************
263  Delete a printer given a handle.
264 ****************************************************************************/
265
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
267 {
268         char *cmd = lp_deleteprinter_cmd();
269         char *command = NULL;
270         int ret;
271         SE_PRIV se_printop = SE_PRINT_OPERATOR;
272         bool is_print_op = false;
273
274         /* can't fail if we don't try */
275
276         if ( !*cmd )
277                 return WERR_OK;
278
279         command = talloc_asprintf(ctx,
280                         "%s \"%s\"",
281                         cmd, sharename);
282         if (!command) {
283                 return WERR_NOMEM;
284         }
285         if ( token )
286                 is_print_op = user_has_privileges( token, &se_printop );
287
288         DEBUG(10,("Running [%s]\n", command));
289
290         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
291
292         if ( is_print_op )
293                 become_root();
294
295         if ( (ret = smbrun(command, NULL)) == 0 ) {
296                 /* Tell everyone we updated smb.conf. */
297                 message_send_all(smbd_messaging_context(),
298                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299         }
300
301         if ( is_print_op )
302                 unbecome_root();
303
304         /********** END SePrintOperatorPrivlege BLOCK **********/
305
306         DEBUGADD(10,("returned [%d]\n", ret));
307
308         TALLOC_FREE(command);
309
310         if (ret != 0)
311                 return WERR_BADFID; /* What to return here? */
312
313         /* go ahead and re-read the services immediately */
314         become_root();
315         reload_services(false);
316         unbecome_root();
317
318         if ( lp_servicenumber( sharename )  < 0 )
319                 return WERR_ACCESS_DENIED;
320
321         return WERR_OK;
322 }
323
324 /****************************************************************************
325  Delete a printer given a handle.
326 ****************************************************************************/
327
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
329 {
330         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331
332         if (!Printer) {
333                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
334                         OUR_HANDLE(hnd)));
335                 return WERR_BADFID;
336         }
337
338         /*
339          * It turns out that Windows allows delete printer on a handle
340          * opened by an admin user, then used on a pipe handle created
341          * by an anonymous user..... but they're working on security.... riiight !
342          * JRA.
343          */
344
345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347                 return WERR_ACCESS_DENIED;
348         }
349
350         /* this does not need a become root since the access check has been
351            done on the handle already */
352
353         if (del_a_printer( Printer->sharename ) != 0) {
354                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
355                 return WERR_BADFID;
356         }
357
358         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359                                    Printer->sharename );
360 }
361
362 /****************************************************************************
363  Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
365
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367                              int *number, struct share_params **params)
368 {
369         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370
371         if (!Printer) {
372                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
373                         OUR_HANDLE(hnd)));
374                 return false;
375         }
376
377         switch (Printer->printer_type) {
378                 case SPLHND_PRINTER:
379                         DEBUG(4,("short name:%s\n", Printer->sharename));
380                         *number = print_queue_snum(Printer->sharename);
381                         return (*number != -1);
382                 case SPLHND_SERVER:
383                         return false;
384                 default:
385                         return false;
386         }
387 }
388
389 /****************************************************************************
390  Set printer handle type.
391  Check if it's \\server or \\server\printer
392 ****************************************************************************/
393
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
395 {
396         DEBUG(3,("Setting printer type=%s\n", handlename));
397
398         if ( strlen(handlename) < 3 ) {
399                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
400                 return false;
401         }
402
403         /* it's a print server */
404         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405                 DEBUGADD(4,("Printer is a print server\n"));
406                 Printer->printer_type = SPLHND_SERVER;
407         }
408         /* it's a printer (set_printer_hnd_name() will handle port monitors */
409         else {
410                 DEBUGADD(4,("Printer is a printer\n"));
411                 Printer->printer_type = SPLHND_PRINTER;
412         }
413
414         return true;
415 }
416
417 /****************************************************************************
418  Set printer handle name..  Accept names like \\server, \\server\printer,
419  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
420  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421  XcvDataPort() interface.
422 ****************************************************************************/
423
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 {
426         int snum;
427         int n_services=lp_numservices();
428         char *aprinter, *printername;
429         const char *servername;
430         fstring sname;
431         bool found = false;
432         NT_PRINTER_INFO_LEVEL *printer = NULL;
433         WERROR result;
434
435         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436                 (unsigned long)strlen(handlename)));
437
438         aprinter = CONST_DISCARD(char *, handlename);
439         if ( *handlename == '\\' ) {
440                 servername = canon_servername(handlename);
441                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
442                         *aprinter = '\0';
443                         aprinter++;
444                 }
445         } else {
446                 servername = global_myname();
447         }
448
449         /* save the servername to fill in replies on this handle */
450
451         if ( !is_myname_or_ipaddr( servername ) )
452                 return false;
453
454         fstrcpy( Printer->servername, servername );
455
456         if ( Printer->printer_type == SPLHND_SERVER )
457                 return true;
458
459         if ( Printer->printer_type != SPLHND_PRINTER )
460                 return false;
461
462         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
463
464         /* check for the Port Monitor Interface */
465
466         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467                 Printer->printer_type = SPLHND_PORTMON_TCP;
468                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469                 found = true;
470         }
471         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474                 found = true;
475         }
476
477         /* Search all sharenames first as this is easier than pulling
478            the printer_info_2 off of disk. Don't use find_service() since
479            that calls out to map_username() */
480
481         /* do another loop to look for printernames */
482
483         for (snum=0; !found && snum<n_services; snum++) {
484
485                 /* no point going on if this is not a printer */
486
487                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488                         continue;
489
490                 fstrcpy(sname, lp_servicename(snum));
491                 if ( strequal( aprinter, sname ) ) {
492                         found = true;
493                         break;
494                 }
495
496                 /* no point looking up the printer object if
497                    we aren't allowing printername != sharename */
498
499                 if ( lp_force_printername(snum) )
500                         continue;
501
502                 fstrcpy(sname, lp_servicename(snum));
503
504                 printer = NULL;
505
506                 /* This call doesn't fill in the location or comment from
507                  * a CUPS server for efficiency with large numbers of printers.
508                  * JRA.
509                  */
510
511                 result = get_a_printer_search( NULL, &printer, 2, sname );
512                 if ( !W_ERROR_IS_OK(result) ) {
513                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514                                 sname, win_errstr(result)));
515                         continue;
516                 }
517
518                 /* printername is always returned as \\server\printername */
519                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521                                 printer->info_2->printername));
522                         free_a_printer( &printer, 2);
523                         continue;
524                 }
525
526                 printername++;
527
528                 if ( strequal(printername, aprinter) ) {
529                         free_a_printer( &printer, 2);
530                         found = true;
531                         break;
532                 }
533
534                 DEBUGADD(10, ("printername: %s\n", printername));
535
536                 free_a_printer( &printer, 2);
537         }
538
539         free_a_printer( &printer, 2);
540
541         if ( !found ) {
542                 DEBUGADD(4,("Printer not found\n"));
543                 return false;
544         }
545
546         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
547
548         fstrcpy(Printer->sharename, sname);
549
550         return true;
551 }
552
553 /****************************************************************************
554  Find first available printer slot. creates a printer handle for you.
555  ****************************************************************************/
556
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558                              const char *name, uint32_t access_granted)
559 {
560         Printer_entry *new_printer;
561
562         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
563
564         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565         if (new_printer == NULL) {
566                 return false;
567         }
568         talloc_set_destructor(new_printer, printer_entry_destructor);
569
570         if (!create_policy_hnd(p, hnd, new_printer)) {
571                 TALLOC_FREE(new_printer);
572                 return false;
573         }
574
575         /* Add to the internal list. */
576         DLIST_ADD(printers_list, new_printer);
577
578         new_printer->notify.option=NULL;
579
580         if (!set_printer_hnd_printertype(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return false;
583         }
584
585         if (!set_printer_hnd_name(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         new_printer->access_granted = access_granted;
591
592         DEBUG(5, ("%d printer handles active\n",
593                   (int)num_pipe_handles(p->pipe_handles)));
594
595         return true;
596 }
597
598 /***************************************************************************
599  check to see if the client motify handle is monitoring the notification
600  given by (notify_type, notify_field).
601  **************************************************************************/
602
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604                                       uint16_t notify_field)
605 {
606         return true;
607 }
608
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610                                 uint16_t notify_field)
611 {
612         struct spoolss_NotifyOption *option = p->notify.option;
613         uint32_t i, j;
614
615         /*
616          * Flags should always be zero when the change notify
617          * is registered by the client's spooler.  A user Win32 app
618          * might use the flags though instead of the NOTIFY_OPTION_INFO
619          * --jerry
620          */
621
622         if (!option) {
623                 return false;
624         }
625
626         if (p->notify.flags)
627                 return is_monitoring_event_flags(
628                         p->notify.flags, notify_type, notify_field);
629
630         for (i = 0; i < option->count; i++) {
631
632                 /* Check match for notify_type */
633
634                 if (option->types[i].type != notify_type)
635                         continue;
636
637                 /* Check match for field */
638
639                 for (j = 0; j < option->types[i].count; j++) {
640                         if (option->types[i].fields[j].field == notify_field) {
641                                 return true;
642                         }
643                 }
644         }
645
646         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647                    p->servername, p->sharename, notify_type, notify_field));
648
649         return false;
650 }
651
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653         _data->data.integer[0] = _integer; \
654         _data->data.integer[1] = 0;
655
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659         if (!_data->data.string.string) {\
660                 _data->data.string.size = 0; \
661         } \
662         _data->data.string.size = strlen_m_term(_p) * 2;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665         _data->data.devmode.devmode = _devmode;
666
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669         if (!_data->data.sd.sd) { \
670                 _data->data.sd.sd_size = 0; \
671         } \
672         _data->data.sd.sd_size = _size;
673
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
675                                    struct tm *t,
676                                    const char **pp,
677                                    uint32_t *plen)
678 {
679         struct spoolss_Time st;
680         uint32_t len = 16;
681         char *p;
682
683         if (!init_systemtime(&st, t)) {
684                 return;
685         }
686
687         p = talloc_array(mem_ctx, char, len);
688         if (!p) {
689                 return;
690         }
691
692         /*
693          * Systemtime must be linearized as a set of UINT16's.
694          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695          */
696
697         SSVAL(p, 0, st.year);
698         SSVAL(p, 2, st.month);
699         SSVAL(p, 4, st.day_of_week);
700         SSVAL(p, 6, st.day);
701         SSVAL(p, 8, st.hour);
702         SSVAL(p, 10, st.minute);
703         SSVAL(p, 12, st.second);
704         SSVAL(p, 14, st.millisecond);
705
706         *pp = p;
707         *plen = len;
708 }
709
710 /* Convert a notification message to a struct spoolss_Notify */
711
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713                              struct spoolss_Notify *data,
714                              TALLOC_CTX *mem_ctx)
715 {
716         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 }
718
719 static void notify_string(struct spoolss_notify_msg *msg,
720                           struct spoolss_Notify *data,
721                           TALLOC_CTX *mem_ctx)
722 {
723         /* The length of the message includes the trailing \0 */
724
725         data->data.string.size = msg->len * 2;
726         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727         if (!data->data.string.string) {
728                 data->data.string.size = 0;
729                 return;
730         }
731 }
732
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734                                struct spoolss_Notify *data,
735                                TALLOC_CTX *mem_ctx)
736 {
737         data->data.string.string = NULL;
738         data->data.string.size = 0;
739
740         if (msg->len != sizeof(time_t)) {
741                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
742                           msg->len));
743                 return;
744         }
745
746         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747                                &data->data.string.string,
748                                &data->data.string.size);
749 }
750
751 struct notify2_message_table {
752         const char *name;
753         void (*fn)(struct spoolss_notify_msg *msg,
754                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 };
756
757 static struct notify2_message_table printer_notify_table[] = {
758         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 };
778
779 static struct notify2_message_table job_notify_table[] = {
780         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 };
805
806
807 /***********************************************************************
808  Allocate talloc context for container object
809  **********************************************************************/
810
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 {
813         if ( !ctr )
814                 return;
815
816         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817
818         return;
819 }
820
821 /***********************************************************************
822  release all allocated memory and zero out structure
823  **********************************************************************/
824
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 {
827         if ( !ctr )
828                 return;
829
830         if ( ctr->ctx )
831                 talloc_destroy(ctr->ctx);
832
833         ZERO_STRUCTP(ctr);
834
835         return;
836 }
837
838 /***********************************************************************
839  **********************************************************************/
840
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 {
843         if ( !ctr )
844                 return NULL;
845
846         return ctr->ctx;
847 }
848
849 /***********************************************************************
850  **********************************************************************/
851
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
853 {
854         if ( !ctr || !ctr->msg_groups )
855                 return NULL;
856
857         if ( idx >= ctr->num_groups )
858                 return NULL;
859
860         return &ctr->msg_groups[idx];
861
862 }
863
864 /***********************************************************************
865  How many groups of change messages do we have ?
866  **********************************************************************/
867
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 {
870         if ( !ctr )
871                 return 0;
872
873         return ctr->num_groups;
874 }
875
876 /***********************************************************************
877  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878  **********************************************************************/
879
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 {
882         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
883         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
884         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
885         int                             i, new_slot;
886
887         if ( !ctr || !msg )
888                 return 0;
889
890         /* loop over all groups looking for a matching printer name */
891
892         for ( i=0; i<ctr->num_groups; i++ ) {
893                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894                         break;
895         }
896
897         /* add a new group? */
898
899         if ( i == ctr->num_groups ) {
900                 ctr->num_groups++;
901
902                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904                         return 0;
905                 }
906                 ctr->msg_groups = groups;
907
908                 /* clear the new entry and set the printer name */
909
910                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912         }
913
914         /* add the change messages; 'i' is the correct index now regardless */
915
916         msg_grp = &ctr->msg_groups[i];
917
918         msg_grp->num_msgs++;
919
920         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922                 return 0;
923         }
924         msg_grp->msgs = msg_list;
925
926         new_slot = msg_grp->num_msgs-1;
927         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928
929         /* need to allocate own copy of data */
930
931         if ( msg->len != 0 )
932                 msg_grp->msgs[new_slot].notify.data = (char *)
933                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934
935         return ctr->num_groups;
936 }
937
938 /***********************************************************************
939  Send a change notication message on all handles which have a call
940  back registered
941  **********************************************************************/
942
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 {
945         Printer_entry            *p;
946         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
947         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948         SPOOLSS_NOTIFY_MSG       *messages;
949         int                      sending_msg_count;
950
951         if ( !msg_group ) {
952                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953                 return;
954         }
955
956         messages = msg_group->msgs;
957
958         if ( !messages ) {
959                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960                 return;
961         }
962
963         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964
965         /* loop over all printers */
966
967         for (p = printers_list; p; p = p->next) {
968                 struct spoolss_Notify *notifies;
969                 uint32_t count = 0;
970                 uint32_t id;
971                 int     i;
972
973                 /* Is there notification on this handle? */
974
975                 if ( !p->notify.client_connected )
976                         continue;
977
978                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979
980                 /* For this printer?  Print servers always receive
981                    notifications. */
982
983                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
984                     ( !strequal(msg_group->printername, p->sharename) ) )
985                         continue;
986
987                 DEBUG(10,("Our printer\n"));
988
989                 /* allocate the max entries possible */
990
991                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
992                 if (!notifies) {
993                         return;
994                 }
995
996                 /* build the array of change notifications */
997
998                 sending_msg_count = 0;
999
1000                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1002
1003                         /* Are we monitoring this event? */
1004
1005                         if (!is_monitoring_event(p, msg->type, msg->field))
1006                                 continue;
1007
1008                         sending_msg_count++;
1009
1010
1011                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012                                 msg->type, msg->field, p->sharename));
1013
1014                         /*
1015                          * if the is a printer notification handle and not a job notification
1016                          * type, then set the id to 0.  Other wise just use what was specified
1017                          * in the message.
1018                          *
1019                          * When registering change notification on a print server handle
1020                          * we always need to send back the id (snum) matching the printer
1021                          * for which the change took place.  For change notify registered
1022                          * on a printer handle, this does not matter and the id should be 0.
1023                          *
1024                          * --jerry
1025                          */
1026
1027                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028                                 id = 0;
1029                         else
1030                                 id = msg->id;
1031
1032
1033                         /* Convert unix jobid to smb jobid */
1034
1035                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036                                 id = sysjob_to_jobid(msg->id);
1037
1038                                 if (id == -1) {
1039                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040                                         goto done;
1041                                 }
1042                         }
1043
1044                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1045
1046                         switch(msg->type) {
1047                         case PRINTER_NOTIFY_TYPE:
1048                                 if ( printer_notify_table[msg->field].fn )
1049                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1050                                 break;
1051
1052                         case JOB_NOTIFY_TYPE:
1053                                 if ( job_notify_table[msg->field].fn )
1054                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1055                                 break;
1056
1057                         default:
1058                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059                                 goto done;
1060                         }
1061
1062                         count++;
1063                 }
1064
1065                 if ( sending_msg_count ) {
1066                         NTSTATUS status;
1067                         WERROR werr;
1068                         union spoolss_ReplyPrinterInfo info;
1069                         struct spoolss_NotifyInfo info0;
1070                         uint32_t reply_result;
1071
1072                         info0.version   = 0x2;
1073                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074                         info0.count     = count;
1075                         info0.notifies  = notifies;
1076
1077                         info.info0 = &info0;
1078
1079                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080                                                                      &p->notify.client_hnd,
1081                                                                      p->notify.change, /* color */
1082                                                                      p->notify.flags,
1083                                                                      &reply_result,
1084                                                                      0, /* reply_type, must be 0 */
1085                                                                      info,
1086                                                                      &werr);
1087                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089                                         notify_cli_pipe->srv_name_slash,
1090                                         win_errstr(werr)));
1091                         }
1092                         switch (reply_result) {
1093                                 case 0:
1094                                         break;
1095                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1096                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1098                                         break;
1099                                 default:
1100                                         break;
1101                         }
1102                 }
1103         }
1104
1105 done:
1106         DEBUG(8,("send_notify2_changes: Exit...\n"));
1107         return;
1108 }
1109
1110 /***********************************************************************
1111  **********************************************************************/
1112
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 {
1115
1116         uint32_t tv_sec, tv_usec;
1117         size_t offset = 0;
1118
1119         /* Unpack message */
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122                              msg->printer);
1123
1124         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1125                                 &tv_sec, &tv_usec,
1126                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127
1128         if (msg->len == 0)
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130                            &msg->notify.value[0], &msg->notify.value[1]);
1131         else
1132                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133                            &msg->len, &msg->notify.data);
1134
1135         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1137
1138         tv->tv_sec = tv_sec;
1139         tv->tv_usec = tv_usec;
1140
1141         if (msg->len == 0)
1142                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143                           msg->notify.value[1]));
1144         else
1145                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1146
1147         return true;
1148 }
1149
1150 /********************************************************************
1151  Receive a notify2 message list
1152  ********************************************************************/
1153
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1155                                          void *private_data,
1156                                          uint32_t msg_type,
1157                                          struct server_id server_id,
1158                                          DATA_BLOB *data)
1159 {
1160         size_t                  msg_count, i;
1161         char                    *buf = (char *)data->data;
1162         char                    *msg_ptr;
1163         size_t                  msg_len;
1164         SPOOLSS_NOTIFY_MSG      notify;
1165         SPOOLSS_NOTIFY_MSG_CTR  messages;
1166         int                     num_groups;
1167
1168         if (data->length < 4) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170                 return;
1171         }
1172
1173         msg_count = IVAL(buf, 0);
1174         msg_ptr = buf + 4;
1175
1176         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1177
1178         if (msg_count == 0) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180                 return;
1181         }
1182
1183         /* initialize the container */
1184
1185         ZERO_STRUCT( messages );
1186         notify_msg_ctr_init( &messages );
1187
1188         /*
1189          * build message groups for each printer identified
1190          * in a change_notify msg.  Remember that a PCN message
1191          * includes the handle returned for the srv_spoolss_replyopenprinter()
1192          * call.  Therefore messages are grouped according to printer handle.
1193          */
1194
1195         for ( i=0; i<msg_count; i++ ) {
1196                 struct timeval msg_tv;
1197
1198                 if (msg_ptr + 4 - buf > data->length) {
1199                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200                         return;
1201                 }
1202
1203                 msg_len = IVAL(msg_ptr,0);
1204                 msg_ptr += 4;
1205
1206                 if (msg_ptr + msg_len - buf > data->length) {
1207                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208                         return;
1209                 }
1210
1211                 /* unpack messages */
1212
1213                 ZERO_STRUCT( notify );
1214                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215                 msg_ptr += msg_len;
1216
1217                 /* add to correct list in container */
1218
1219                 notify_msg_ctr_addmsg( &messages, &notify );
1220
1221                 /* free memory that might have been allocated by notify2_unpack_msg() */
1222
1223                 if ( notify.len != 0 )
1224                         SAFE_FREE( notify.notify.data );
1225         }
1226
1227         /* process each group of messages */
1228
1229         num_groups = notify_msg_ctr_numgroups( &messages );
1230         for ( i=0; i<num_groups; i++ )
1231                 send_notify2_changes( &messages, i );
1232
1233
1234         /* cleanup */
1235
1236         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237                 (uint32_t)msg_count ));
1238
1239         notify_msg_ctr_destroy( &messages );
1240
1241         return;
1242 }
1243
1244 /********************************************************************
1245  Send a message to ourself about new driver being installed
1246  so we can upgrade the information for each printer bound to this
1247  driver
1248  ********************************************************************/
1249
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1251 {
1252         int len = strlen(drivername);
1253
1254         if (!len)
1255                 return false;
1256
1257         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258                 drivername));
1259
1260         messaging_send_buf(smbd_messaging_context(), procid_self(),
1261                            MSG_PRINTER_DRVUPGRADE,
1262                            (uint8_t *)drivername, len+1);
1263
1264         return true;
1265 }
1266
1267 /**********************************************************************
1268  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269  over all printers, upgrading ones as necessary
1270  **********************************************************************/
1271
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1273                             void *private_data,
1274                             uint32_t msg_type,
1275                             struct server_id server_id,
1276                             DATA_BLOB *data)
1277 {
1278         fstring drivername;
1279         int snum;
1280         int n_services = lp_numservices();
1281         size_t len;
1282
1283         len = MIN(data->length,sizeof(drivername)-1);
1284         strncpy(drivername, (const char *)data->data, len);
1285
1286         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287
1288         /* Iterate the printer list */
1289
1290         for (snum=0; snum<n_services; snum++)
1291         {
1292                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293                 {
1294                         WERROR result;
1295                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1296
1297                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298                         if (!W_ERROR_IS_OK(result))
1299                                 continue;
1300
1301                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302                         {
1303                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304
1305                                 /* all we care about currently is the change_id */
1306
1307                                 result = mod_a_printer(printer, 2);
1308                                 if (!W_ERROR_IS_OK(result)) {
1309                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310                                                 win_errstr(result)));
1311                                 }
1312                         }
1313
1314                         free_a_printer(&printer, 2);
1315                 }
1316         }
1317
1318         /* all done */
1319 }
1320
1321 /********************************************************************
1322  Update the cache for all printq's with a registered client
1323  connection
1324  ********************************************************************/
1325
1326 void update_monitored_printq_cache( void )
1327 {
1328         Printer_entry *printer = printers_list;
1329         int snum;
1330
1331         /* loop through all printers and update the cache where
1332            client_connected == true */
1333         while ( printer )
1334         {
1335                 if ( (printer->printer_type == SPLHND_PRINTER)
1336                         && printer->notify.client_connected )
1337                 {
1338                         snum = print_queue_snum(printer->sharename);
1339                         print_queue_status( snum, NULL, NULL );
1340                 }
1341
1342                 printer = printer->next;
1343         }
1344
1345         return;
1346 }
1347 /********************************************************************
1348  Send a message to ourself about new driver being installed
1349  so we can upgrade the information for each printer bound to this
1350  driver
1351  ********************************************************************/
1352
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 {
1355         int len = strlen(drivername);
1356
1357         if (!len)
1358                 return false;
1359
1360         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361                 drivername));
1362
1363         messaging_send_buf(smbd_messaging_context(), procid_self(),
1364                            MSG_PRINTERDATA_INIT_RESET,
1365                            (uint8_t *)drivername, len+1);
1366
1367         return true;
1368 }
1369
1370 /**********************************************************************
1371  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372  over all printers, resetting printer data as neessary
1373  **********************************************************************/
1374
1375 void reset_all_printerdata(struct messaging_context *msg,
1376                            void *private_data,
1377                            uint32_t msg_type,
1378                            struct server_id server_id,
1379                            DATA_BLOB *data)
1380 {
1381         fstring drivername;
1382         int snum;
1383         int n_services = lp_numservices();
1384         size_t len;
1385
1386         len = MIN( data->length, sizeof(drivername)-1 );
1387         strncpy( drivername, (const char *)data->data, len );
1388
1389         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390
1391         /* Iterate the printer list */
1392
1393         for ( snum=0; snum<n_services; snum++ )
1394         {
1395                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396                 {
1397                         WERROR result;
1398                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1399
1400                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401                         if ( !W_ERROR_IS_OK(result) )
1402                                 continue;
1403
1404                         /*
1405                          * if the printer is bound to the driver,
1406                          * then reset to the new driver initdata
1407                          */
1408
1409                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410                         {
1411                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412
1413                                 if ( !set_driver_init(printer, 2) ) {
1414                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415                                                 printer->info_2->printername, printer->info_2->drivername));
1416                                 }
1417
1418                                 result = mod_a_printer( printer, 2 );
1419                                 if ( !W_ERROR_IS_OK(result) ) {
1420                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1421                                                 get_dos_error_msg(result)));
1422                                 }
1423                         }
1424
1425                         free_a_printer( &printer, 2 );
1426                 }
1427         }
1428
1429         /* all done */
1430
1431         return;
1432 }
1433
1434 /****************************************************************
1435  _spoolss_OpenPrinter
1436 ****************************************************************/
1437
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439                             struct spoolss_OpenPrinter *r)
1440 {
1441         struct spoolss_OpenPrinterEx e;
1442         WERROR werr;
1443
1444         ZERO_STRUCT(e.in.userlevel);
1445
1446         e.in.printername        = r->in.printername;
1447         e.in.datatype           = r->in.datatype;
1448         e.in.devmode_ctr        = r->in.devmode_ctr;
1449         e.in.access_mask        = r->in.access_mask;
1450         e.in.level              = 0;
1451
1452         e.out.handle            = r->out.handle;
1453
1454         werr = _spoolss_OpenPrinterEx(p, &e);
1455
1456         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457                 /* OpenPrinterEx returns this for a bad
1458                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1459                  * instead.
1460                  */
1461                 werr = WERR_INVALID_PRINTER_NAME;
1462         }
1463
1464         return werr;
1465 }
1466
1467 /********************************************************************
1468  ********************************************************************/
1469
1470 bool convert_devicemode(const char *printername,
1471                         const struct spoolss_DeviceMode *devmode,
1472                         NT_DEVICEMODE **pp_nt_devmode)
1473 {
1474         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475
1476         /*
1477          * Ensure nt_devmode is a valid pointer
1478          * as we will be overwriting it.
1479          */
1480
1481         if (nt_devmode == NULL) {
1482                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484                         return false;
1485         }
1486
1487         fstrcpy(nt_devmode->devicename, devmode->devicename);
1488         fstrcpy(nt_devmode->formname, devmode->formname);
1489
1490         nt_devmode->devicename[31] = '\0';
1491         nt_devmode->formname[31] = '\0';
1492
1493         nt_devmode->specversion         = devmode->specversion;
1494         nt_devmode->driverversion       = devmode->driverversion;
1495         nt_devmode->size                = devmode->size;
1496         nt_devmode->fields              = devmode->fields;
1497         nt_devmode->orientation         = devmode->orientation;
1498         nt_devmode->papersize           = devmode->papersize;
1499         nt_devmode->paperlength         = devmode->paperlength;
1500         nt_devmode->paperwidth          = devmode->paperwidth;
1501         nt_devmode->scale               = devmode->scale;
1502         nt_devmode->copies              = devmode->copies;
1503         nt_devmode->defaultsource       = devmode->defaultsource;
1504         nt_devmode->printquality        = devmode->printquality;
1505         nt_devmode->color               = devmode->color;
1506         nt_devmode->duplex              = devmode->duplex;
1507         nt_devmode->yresolution         = devmode->yresolution;
1508         nt_devmode->ttoption            = devmode->ttoption;
1509         nt_devmode->collate             = devmode->collate;
1510
1511         nt_devmode->logpixels           = devmode->logpixels;
1512         nt_devmode->bitsperpel          = devmode->bitsperpel;
1513         nt_devmode->pelswidth           = devmode->pelswidth;
1514         nt_devmode->pelsheight          = devmode->pelsheight;
1515         nt_devmode->displayflags        = devmode->displayflags;
1516         nt_devmode->displayfrequency    = devmode->displayfrequency;
1517         nt_devmode->icmmethod           = devmode->icmmethod;
1518         nt_devmode->icmintent           = devmode->icmintent;
1519         nt_devmode->mediatype           = devmode->mediatype;
1520         nt_devmode->dithertype          = devmode->dithertype;
1521         nt_devmode->reserved1           = devmode->reserved1;
1522         nt_devmode->reserved2           = devmode->reserved2;
1523         nt_devmode->panningwidth        = devmode->panningwidth;
1524         nt_devmode->panningheight       = devmode->panningheight;
1525
1526         /*
1527          * Only change private and driverextra if the incoming devmode
1528          * has a new one. JRA.
1529          */
1530
1531         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532                 SAFE_FREE(nt_devmode->nt_dev_private);
1533                 nt_devmode->driverextra = devmode->__driverextra_length;
1534                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1535                         return false;
1536                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1537         }
1538
1539         *pp_nt_devmode = nt_devmode;
1540
1541         return true;
1542 }
1543
1544 /****************************************************************
1545  _spoolss_OpenPrinterEx
1546 ****************************************************************/
1547
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549                               struct spoolss_OpenPrinterEx *r)
1550 {
1551         int snum;
1552         Printer_entry *Printer=NULL;
1553
1554         if (!r->in.printername) {
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         /* some sanity check because you can open a printer or a print server */
1559         /* aka: \\server\printer or \\server */
1560
1561         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1562
1563         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564                 ZERO_STRUCTP(r->out.handle);
1565                 return WERR_INVALID_PARAM;
1566         }
1567
1568         Printer = find_printer_index_by_hnd(p, r->out.handle);
1569         if ( !Printer ) {
1570                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1571                         "handle we created for printer %s\n", r->in.printername));
1572                 close_printer_handle(p, r->out.handle);
1573                 ZERO_STRUCTP(r->out.handle);
1574                 return WERR_INVALID_PARAM;
1575         }
1576
1577         /*
1578          * First case: the user is opening the print server:
1579          *
1580          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1582          *
1583          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585          * or if the user is listed in the smb.conf printer admin parameter.
1586          *
1587          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588          * client view printer folder, but does not show the MSAPW.
1589          *
1590          * Note: this test needs code to check access rights here too. Jeremy
1591          * could you look at this?
1592          *
1593          * Second case: the user is opening a printer:
1594          * NT doesn't let us connect to a printer if the connecting user
1595          * doesn't have print permission.
1596          *
1597          * Third case: user is opening a Port Monitor
1598          * access checks same as opening a handle to the print server.
1599          */
1600
1601         switch (Printer->printer_type )
1602         {
1603         case SPLHND_SERVER:
1604         case SPLHND_PORTMON_TCP:
1605         case SPLHND_PORTMON_LOCAL:
1606                 /* Printserver handles use global struct... */
1607
1608                 snum = -1;
1609
1610                 /* Map standard access rights to object specific access rights */
1611
1612                 se_map_standard(&r->in.access_mask,
1613                                 &printserver_std_mapping);
1614
1615                 /* Deny any object specific bits that don't apply to print
1616                    servers (i.e printer and job specific bits) */
1617
1618                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1619
1620                 if (r->in.access_mask &
1621                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623                         close_printer_handle(p, r->out.handle);
1624                         ZERO_STRUCTP(r->out.handle);
1625                         return WERR_ACCESS_DENIED;
1626                 }
1627
1628                 /* Allow admin access */
1629
1630                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1631                 {
1632                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1633
1634                         if (!lp_ms_add_printer_wizard()) {
1635                                 close_printer_handle(p, r->out.handle);
1636                                 ZERO_STRUCTP(r->out.handle);
1637                                 return WERR_ACCESS_DENIED;
1638                         }
1639
1640                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641                            and not a printer admin, then fail */
1642
1643                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644                             !user_has_privileges(p->server_info->ptok,
1645                                                  &se_printop ) &&
1646                             !token_contains_name_in_list(
1647                                     uidtoname(p->server_info->utok.uid),
1648                                     NULL, NULL,
1649                                     p->server_info->ptok,
1650                                     lp_printer_admin(snum))) {
1651                                 close_printer_handle(p, r->out.handle);
1652                                 ZERO_STRUCTP(r->out.handle);
1653                                 return WERR_ACCESS_DENIED;
1654                         }
1655
1656                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657                 }
1658                 else
1659                 {
1660                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661                 }
1662
1663                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1665
1666                 /* We fall through to return WERR_OK */
1667                 break;
1668
1669         case SPLHND_PRINTER:
1670                 /* NT doesn't let us connect to a printer if the connecting user
1671                    doesn't have print permission.  */
1672
1673                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674                         close_printer_handle(p, r->out.handle);
1675                         ZERO_STRUCTP(r->out.handle);
1676                         return WERR_BADFID;
1677                 }
1678
1679                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681                 }
1682
1683                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1684
1685                 /* map an empty access mask to the minimum access mask */
1686                 if (r->in.access_mask == 0x0)
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688
1689                 /*
1690                  * If we are not serving the printer driver for this printer,
1691                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1692                  * will keep NT clients happy  --jerry
1693                  */
1694
1695                 if (lp_use_client_driver(snum)
1696                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1697                 {
1698                         r->in.access_mask = PRINTER_ACCESS_USE;
1699                 }
1700
1701                 /* check smb.conf parameters and the the sec_desc */
1702
1703                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708
1709                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710                                    p->server_info->ptok, snum) ||
1711                     !print_access_check(p->server_info, snum,
1712                                         r->in.access_mask)) {
1713                         DEBUG(3, ("access DENIED for printer open\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 & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721                         close_printer_handle(p, r->out.handle);
1722                         ZERO_STRUCTP(r->out.handle);
1723                         return WERR_ACCESS_DENIED;
1724                 }
1725
1726                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1728                 else
1729                         r->in.access_mask = PRINTER_ACCESS_USE;
1730
1731                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1733
1734                 break;
1735
1736         default:
1737                 /* sanity check to prevent programmer error */
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_BADFID;
1740         }
1741
1742         Printer->access_granted = r->in.access_mask;
1743
1744         /*
1745          * If the client sent a devmode in the OpenPrinter() call, then
1746          * save it here in case we get a job submission on this handle
1747          */
1748
1749          if ((Printer->printer_type != SPLHND_SERVER) &&
1750              r->in.devmode_ctr.devmode) {
1751                 convert_devicemode(Printer->sharename,
1752                                    r->in.devmode_ctr.devmode,
1753                                    &Printer->nt_devmode);
1754          }
1755
1756 #if 0   /* JERRY -- I'm doubtful this is really effective */
1757         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758            optimization in Windows 2000 clients  --jerry */
1759
1760         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761                 && (RA_WIN2K == get_remote_arch()) )
1762         {
1763                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764                 sys_usleep( 500000 );
1765         }
1766 #endif
1767
1768         return WERR_OK;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775                                               NT_PRINTER_INFO_LEVEL_2 *d)
1776 {
1777         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1778
1779         if (!r || !d) {
1780                 return false;
1781         }
1782
1783         d->attributes           = r->attributes;
1784         d->priority             = r->priority;
1785         d->default_priority     = r->defaultpriority;
1786         d->starttime            = r->starttime;
1787         d->untiltime            = r->untiltime;
1788         d->status               = r->status;
1789         d->cjobs                = r->cjobs;
1790
1791         fstrcpy(d->servername,  r->servername);
1792         fstrcpy(d->printername, r->printername);
1793         fstrcpy(d->sharename,   r->sharename);
1794         fstrcpy(d->portname,    r->portname);
1795         fstrcpy(d->drivername,  r->drivername);
1796         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797         fstrcpy(d->location,    r->location);
1798         fstrcpy(d->sepfile,     r->sepfile);
1799         fstrcpy(d->printprocessor, r->printprocessor);
1800         fstrcpy(d->datatype,    r->datatype);
1801         fstrcpy(d->parameters,  r->parameters);
1802
1803         return true;
1804 }
1805
1806 /****************************************************************************
1807 ****************************************************************************/
1808
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810                                  NT_PRINTER_INFO_LEVEL *printer)
1811 {
1812         bool ret;
1813
1814         switch (info_ctr->level) {
1815         case 2:
1816                 /* allocate memory if needed.  Messy because
1817                    convert_printer_info is used to update an existing
1818                    printer or build a new one */
1819
1820                 if (!printer->info_2) {
1821                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822                         if (!printer->info_2) {
1823                                 DEBUG(0,("convert_printer_info: "
1824                                         "talloc() failed!\n"));
1825                                 return false;
1826                         }
1827                 }
1828
1829                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1830                                                         printer->info_2);
1831                 printer->info_2->setuptime = time(NULL);
1832                 return ret;
1833         }
1834
1835         return false;
1836 }
1837
1838 /****************************************************************
1839  _spoolss_ClosePrinter
1840 ****************************************************************/
1841
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843                              struct spoolss_ClosePrinter *r)
1844 {
1845         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1846
1847         if (Printer && Printer->document_started) {
1848                 struct spoolss_EndDocPrinter e;
1849
1850                 e.in.handle = r->in.handle;
1851
1852                 _spoolss_EndDocPrinter(p, &e);
1853         }
1854
1855         if (!close_printer_handle(p, r->in.handle))
1856                 return WERR_BADFID;
1857
1858         /* clear the returned printer handle.  Observed behavior
1859            from Win2k server.  Don't think this really matters.
1860            Previous code just copied the value of the closed
1861            handle.    --jerry */
1862
1863         ZERO_STRUCTP(r->out.handle);
1864
1865         return WERR_OK;
1866 }
1867
1868 /****************************************************************
1869  _spoolss_DeletePrinter
1870 ****************************************************************/
1871
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873                               struct spoolss_DeletePrinter *r)
1874 {
1875         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1876         WERROR result;
1877
1878         if (Printer && Printer->document_started) {
1879                 struct spoolss_EndDocPrinter e;
1880
1881                 e.in.handle = r->in.handle;
1882
1883                 _spoolss_EndDocPrinter(p, &e);
1884         }
1885
1886         result = delete_printer_handle(p, r->in.handle);
1887
1888         update_c_setprinter(false);
1889
1890         return result;
1891 }
1892
1893 /*******************************************************************
1894  * static function to lookup the version id corresponding to an
1895  * long architecture string
1896  ******************************************************************/
1897
1898 static const struct print_architecture_table_node archi_table[]= {
1899
1900         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1901         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1902         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1903         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1904         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1905         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1906         {"Windows x64",          SPL_ARCH_X64,          3 },
1907         {NULL,                   "",            -1 }
1908 };
1909
1910 static int get_version_id(const char *arch)
1911 {
1912         int i;
1913
1914         for (i=0; archi_table[i].long_archi != NULL; i++)
1915         {
1916                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917                         return (archi_table[i].version);
1918         }
1919
1920         return -1;
1921 }
1922
1923 /****************************************************************
1924  _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1926
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928                                     struct spoolss_DeletePrinterDriver *r)
1929 {
1930
1931         struct spoolss_DriverInfo8 *info = NULL;
1932         struct spoolss_DriverInfo8 *info_win2k = NULL;
1933         int                             version;
1934         WERROR                          status;
1935         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1936         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1937
1938         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1939            and not a printer admin, then fail */
1940
1941         if ( (p->server_info->utok.uid != sec_initial_uid())
1942                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1943                 && !token_contains_name_in_list(
1944                         uidtoname(p->server_info->utok.uid), NULL,
1945                         NULL, p->server_info->ptok,
1946                         lp_printer_admin(-1)) )
1947         {
1948                 return WERR_ACCESS_DENIED;
1949         }
1950
1951         /* check that we have a valid driver name first */
1952
1953         if ((version = get_version_id(r->in.architecture)) == -1)
1954                 return WERR_INVALID_ENVIRONMENT;
1955
1956         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1957                                                 r->in.architecture,
1958                                                 version)))
1959         {
1960                 /* try for Win2k driver if "Windows NT x86" */
1961
1962                 if ( version == 2 ) {
1963                         version = 3;
1964                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1965                                                                 &info,
1966                                                                 r->in.driver,
1967                                                                 r->in.architecture,
1968                                                                 version))) {
1969                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970                                 goto done;
1971                         }
1972                 }
1973                 /* otherwise it was a failure */
1974                 else {
1975                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1976                         goto done;
1977                 }
1978
1979         }
1980
1981         if (printer_driver_in_use(info)) {
1982                 status = WERR_PRINTER_DRIVER_IN_USE;
1983                 goto done;
1984         }
1985
1986         if ( version == 2 )
1987         {
1988                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1989                                                        &info_win2k,
1990                                                        r->in.driver,
1991                                                        r->in.architecture, 3)))
1992                 {
1993                         /* if we get to here, we now have 2 driver info structures to remove */
1994                         /* remove the Win2k driver first*/
1995
1996                         status_win2k = delete_printer_driver(
1997                                 p, info_win2k, 3, false);
1998                         free_a_printer_driver(info_win2k);
1999
2000                         /* this should not have failed---if it did, report to client */
2001                         if ( !W_ERROR_IS_OK(status_win2k) )
2002                         {
2003                                 status = status_win2k;
2004                                 goto done;
2005                         }
2006                 }
2007         }
2008
2009         status = delete_printer_driver(p, info, version, false);
2010
2011         /* if at least one of the deletes succeeded return OK */
2012
2013         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2014                 status = WERR_OK;
2015
2016 done:
2017         free_a_printer_driver(info);
2018
2019         return status;
2020 }
2021
2022 /****************************************************************
2023  _spoolss_DeletePrinterDriverEx
2024 ****************************************************************/
2025
2026 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2027                                       struct spoolss_DeletePrinterDriverEx *r)
2028 {
2029         struct spoolss_DriverInfo8      *info = NULL;
2030         struct spoolss_DriverInfo8      *info_win2k = NULL;
2031         int                             version;
2032         bool                            delete_files;
2033         WERROR                          status;
2034         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2035         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2036
2037         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038            and not a printer admin, then fail */
2039
2040         if ( (p->server_info->utok.uid != sec_initial_uid())
2041                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2042                 && !token_contains_name_in_list(
2043                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2044                         p->server_info->ptok, lp_printer_admin(-1)) )
2045         {
2046                 return WERR_ACCESS_DENIED;
2047         }
2048
2049         /* check that we have a valid driver name first */
2050         if ((version = get_version_id(r->in.architecture)) == -1) {
2051                 /* this is what NT returns */
2052                 return WERR_INVALID_ENVIRONMENT;
2053         }
2054
2055         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2056                 version = r->in.version;
2057
2058         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2059                                       r->in.architecture, version);
2060
2061         if ( !W_ERROR_IS_OK(status) )
2062         {
2063                 /*
2064                  * if the client asked for a specific version,
2065                  * or this is something other than Windows NT x86,
2066                  * then we've failed
2067                  */
2068
2069                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2070                         goto done;
2071
2072                 /* try for Win2k driver if "Windows NT x86" */
2073
2074                 version = 3;
2075                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2076                                                         r->in.architecture,
2077                                                         version))) {
2078                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2079                         goto done;
2080                 }
2081         }
2082
2083         if (printer_driver_in_use(info)) {
2084                 status = WERR_PRINTER_DRIVER_IN_USE;
2085                 goto done;
2086         }
2087
2088         /*
2089          * we have a couple of cases to consider.
2090          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2091          *     then the delete should fail if **any** files overlap with
2092          *     other drivers
2093          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094          *     non-overlapping files
2095          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096          *     is set, the do not delete any files
2097          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2098          */
2099
2100         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2101
2102         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2103
2104         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2105                 /* no idea of the correct error here */
2106                 status = WERR_ACCESS_DENIED;
2107                 goto done;
2108         }
2109
2110
2111         /* also check for W32X86/3 if necessary; maybe we already have? */
2112
2113         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2114                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2115                                                        r->in.driver,
2116                                                        r->in.architecture, 3)))
2117                 {
2118
2119                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2120                                 /* no idea of the correct error here */
2121                                 free_a_printer_driver(info_win2k);
2122                                 status = WERR_ACCESS_DENIED;
2123                                 goto done;
2124                         }
2125
2126                         /* if we get to here, we now have 2 driver info structures to remove */
2127                         /* remove the Win2k driver first*/
2128
2129                         status_win2k = delete_printer_driver(
2130                                 p, info_win2k, 3, delete_files);
2131                         free_a_printer_driver(info_win2k);
2132
2133                         /* this should not have failed---if it did, report to client */
2134
2135                         if ( !W_ERROR_IS_OK(status_win2k) )
2136                                 goto done;
2137                 }
2138         }
2139
2140         status = delete_printer_driver(p, info, version, delete_files);
2141
2142         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2143                 status = WERR_OK;
2144 done:
2145         free_a_printer_driver(info);
2146
2147         return status;
2148 }
2149
2150
2151 /****************************************************************************
2152  Internal routine for removing printerdata
2153  ***************************************************************************/
2154
2155 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2156 {
2157         return delete_printer_data( printer->info_2, key, value );
2158 }
2159
2160 /****************************************************************************
2161  Internal routine for storing printerdata
2162  ***************************************************************************/
2163
2164 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2165                           const char *key, const char *value,
2166                           uint32_t type, uint8_t *data, int real_len)
2167 {
2168         /* the registry objects enforce uniqueness based on value name */
2169
2170         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2171 }
2172
2173 /********************************************************************
2174  GetPrinterData on a printer server Handle.
2175 ********************************************************************/
2176
2177 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2178                                             const char *value,
2179                                             enum winreg_Type *type,
2180                                             union spoolss_PrinterData *data)
2181 {
2182         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2183
2184         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2185                 *type = REG_DWORD;
2186                 data->value = 0x00;
2187                 return WERR_OK;
2188         }
2189
2190         if (!StrCaseCmp(value, "BeepEnabled")) {
2191                 *type = REG_DWORD;
2192                 data->value = 0x00;
2193                 return WERR_OK;
2194         }
2195
2196         if (!StrCaseCmp(value, "EventLog")) {
2197                 *type = REG_DWORD;
2198                 /* formally was 0x1b */
2199                 data->value = 0x00;
2200                 return WERR_OK;
2201         }
2202
2203         if (!StrCaseCmp(value, "NetPopup")) {
2204                 *type = REG_DWORD;
2205                 data->value = 0x00;
2206                 return WERR_OK;
2207         }
2208
2209         if (!StrCaseCmp(value, "MajorVersion")) {
2210                 *type = REG_DWORD;
2211
2212                 /* Windows NT 4.0 seems to not allow uploading of drivers
2213                    to a server that reports 0x3 as the MajorVersion.
2214                    need to investigate more how Win2k gets around this .
2215                    -- jerry */
2216
2217                 if (RA_WINNT == get_remote_arch()) {
2218                         data->value = 0x02;
2219                 } else {
2220                         data->value = 0x03;
2221                 }
2222
2223                 return WERR_OK;
2224         }
2225
2226         if (!StrCaseCmp(value, "MinorVersion")) {
2227                 *type = REG_DWORD;
2228                 data->value = 0x00;
2229                 return WERR_OK;
2230         }
2231
2232         /* REG_BINARY
2233          *  uint32_t size        = 0x114
2234          *  uint32_t major       = 5
2235          *  uint32_t minor       = [0|1]
2236          *  uint32_t build       = [2195|2600]
2237          *  extra unicode string = e.g. "Service Pack 3"
2238          */
2239         if (!StrCaseCmp(value, "OSVersion")) {
2240                 DATA_BLOB blob;
2241                 enum ndr_err_code ndr_err;
2242                 struct spoolss_OSVersion os;
2243
2244                 os.major                = 5;    /* Windows 2000 == 5.0 */
2245                 os.minor                = 0;
2246                 os.build                = 2195; /* build */
2247                 os.extra_string         = "";   /* leave extra string empty */
2248
2249                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2250                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2251                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2252                         return WERR_GENERAL_FAILURE;
2253                 }
2254
2255                 *type = REG_BINARY;
2256                 data->binary = blob;
2257
2258                 return WERR_OK;
2259         }
2260
2261
2262         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2263                 *type = REG_SZ;
2264
2265                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2266                 W_ERROR_HAVE_NO_MEMORY(data->string);
2267
2268                 return WERR_OK;
2269         }
2270
2271         if (!StrCaseCmp(value, "Architecture")) {
2272                 *type = REG_SZ;
2273                 data->string = talloc_strdup(mem_ctx,
2274                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2275                 W_ERROR_HAVE_NO_MEMORY(data->string);
2276
2277                 return WERR_OK;
2278         }
2279
2280         if (!StrCaseCmp(value, "DsPresent")) {
2281                 *type = REG_DWORD;
2282
2283                 /* only show the publish check box if we are a
2284                    member of a AD domain */
2285
2286                 if (lp_security() == SEC_ADS) {
2287                         data->value = 0x01;
2288                 } else {
2289                         data->value = 0x00;
2290                 }
2291                 return WERR_OK;
2292         }
2293
2294         if (!StrCaseCmp(value, "DNSMachineName")) {
2295                 const char *hostname = get_mydnsfullname();
2296
2297                 if (!hostname) {
2298                         return WERR_BADFILE;
2299                 }
2300
2301                 *type = REG_SZ;
2302                 data->string = talloc_strdup(mem_ctx, hostname);
2303                 W_ERROR_HAVE_NO_MEMORY(data->string);
2304
2305                 return WERR_OK;
2306         }
2307
2308         *type = REG_NONE;
2309
2310         return WERR_INVALID_PARAM;
2311 }
2312
2313 /****************************************************************
2314  _spoolss_GetPrinterData
2315 ****************************************************************/
2316
2317 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2318                                struct spoolss_GetPrinterData *r)
2319 {
2320         struct spoolss_GetPrinterDataEx r2;
2321
2322         r2.in.handle            = r->in.handle;
2323         r2.in.key_name          = "PrinterDriverData";
2324         r2.in.value_name        = r->in.value_name;
2325         r2.in.offered           = r->in.offered;
2326         r2.out.type             = r->out.type;
2327         r2.out.data             = r->out.data;
2328         r2.out.needed           = r->out.needed;
2329
2330         return _spoolss_GetPrinterDataEx(p, &r2);
2331 }
2332
2333 /*********************************************************
2334  Connect to the client machine.
2335 **********************************************************/
2336
2337 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2338                         struct sockaddr_storage *client_ss, const char *remote_machine)
2339 {
2340         NTSTATUS ret;
2341         struct cli_state *the_cli;
2342         struct sockaddr_storage rm_addr;
2343         char addr[INET6_ADDRSTRLEN];
2344
2345         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2346                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2347                         remote_machine));
2348                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2349                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2350                         return false;
2351                 }
2352                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2353         } else {
2354                 rm_addr = *client_ss;
2355                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2356                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2357                         addr));
2358         }
2359
2360         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2361                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2362                         addr));
2363                 return false;
2364         }
2365
2366         /* setup the connection */
2367         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2368                 &rm_addr, 0, "IPC$", "IPC",
2369                 "", /* username */
2370                 "", /* domain */
2371                 "", /* password */
2372                 0, lp_client_signing(), NULL );
2373
2374         if ( !NT_STATUS_IS_OK( ret ) ) {
2375                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2376                         remote_machine ));
2377                 return false;
2378         }
2379
2380         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2381                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2382                 cli_shutdown(the_cli);
2383                 return false;
2384         }
2385
2386         /*
2387          * Ok - we have an anonymous connection to the IPC$ share.
2388          * Now start the NT Domain stuff :-).
2389          */
2390
2391         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2392         if (!NT_STATUS_IS_OK(ret)) {
2393                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2394                         remote_machine, nt_errstr(ret)));
2395                 cli_shutdown(the_cli);
2396                 return false;
2397         }
2398
2399         return true;
2400 }
2401
2402 /***************************************************************************
2403  Connect to the client.
2404 ****************************************************************************/
2405
2406 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2407                                         uint32_t localprinter, uint32_t type,
2408                                         struct policy_handle *handle,
2409                                         struct sockaddr_storage *client_ss)
2410 {
2411         WERROR result;
2412         NTSTATUS status;
2413
2414         /*
2415          * If it's the first connection, contact the client
2416          * and connect to the IPC$ share anonymously
2417          */
2418         if (smb_connections==0) {
2419                 fstring unix_printer;
2420
2421                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2422
2423                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2424                         return false;
2425
2426                 messaging_register(smbd_messaging_context(), NULL,
2427                                    MSG_PRINTER_NOTIFY2,
2428                                    receive_notify2_message_list);
2429                 /* Tell the connections db we're now interested in printer
2430                  * notify messages. */
2431                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2432         }
2433
2434         /*
2435          * Tell the specific printing tdb we want messages for this printer
2436          * by registering our PID.
2437          */
2438
2439         if (!print_notify_register_pid(snum))
2440                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2441
2442         smb_connections++;
2443
2444         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2445                                                  printer,
2446                                                  localprinter,
2447                                                  type,
2448                                                  0,
2449                                                  NULL,
2450                                                  handle,
2451                                                  &result);
2452         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2453                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2454                         win_errstr(result)));
2455
2456         return (W_ERROR_IS_OK(result));
2457 }
2458
2459 /****************************************************************
2460  ****************************************************************/
2461
2462 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2463                                                              const struct spoolss_NotifyOption *r)
2464 {
2465         struct spoolss_NotifyOption *option;
2466         uint32_t i,k;
2467
2468         if (!r) {
2469                 return NULL;
2470         }
2471
2472         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2473         if (!option) {
2474                 return NULL;
2475         }
2476
2477         *option = *r;
2478
2479         if (!option->count) {
2480                 return option;
2481         }
2482
2483         option->types = talloc_zero_array(option,
2484                 struct spoolss_NotifyOptionType, option->count);
2485         if (!option->types) {
2486                 talloc_free(option);
2487                 return NULL;
2488         }
2489
2490         for (i=0; i < option->count; i++) {
2491                 option->types[i] = r->types[i];
2492
2493                 if (option->types[i].count) {
2494                         option->types[i].fields = talloc_zero_array(option,
2495                                 union spoolss_Field, option->types[i].count);
2496                         if (!option->types[i].fields) {
2497                                 talloc_free(option);
2498                                 return NULL;
2499                         }
2500                         for (k=0; k<option->types[i].count; k++) {
2501                                 option->types[i].fields[k] =
2502                                         r->types[i].fields[k];
2503                         }
2504                 }
2505         }
2506
2507         return option;
2508 }
2509
2510 /****************************************************************
2511  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2512  *
2513  * before replying OK: status=0 a rpc call is made to the workstation
2514  * asking ReplyOpenPrinter
2515  *
2516  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2517  * called from api_spoolss_rffpcnex
2518 ****************************************************************/
2519
2520 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2521                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2522 {
2523         int snum = -1;
2524         struct spoolss_NotifyOption *option = r->in.notify_options;
2525         struct sockaddr_storage client_ss;
2526
2527         /* store the notify value in the printer struct */
2528
2529         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2530
2531         if (!Printer) {
2532                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2533                         "Invalid handle (%s:%u:%u).\n",
2534                         OUR_HANDLE(r->in.handle)));
2535                 return WERR_BADFID;
2536         }
2537
2538         Printer->notify.flags           = r->in.flags;
2539         Printer->notify.options         = r->in.options;
2540         Printer->notify.printerlocal    = r->in.printer_local;
2541
2542         TALLOC_FREE(Printer->notify.option);
2543         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2544
2545         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2546
2547         /* Connect to the client machine and send a ReplyOpenPrinter */
2548
2549         if ( Printer->printer_type == SPLHND_SERVER)
2550                 snum = -1;
2551         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2552                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2553                 return WERR_BADFID;
2554
2555         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2556                 "client_address is %s\n", p->client_address));
2557
2558         if (!interpret_string_addr(&client_ss, p->client_address,
2559                                    AI_NUMERICHOST)) {
2560                 return WERR_SERVER_UNAVAILABLE;
2561         }
2562
2563         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2564                                         Printer->notify.printerlocal, 1,
2565                                         &Printer->notify.client_hnd, &client_ss))
2566                 return WERR_SERVER_UNAVAILABLE;
2567
2568         Printer->notify.client_connected = true;
2569
2570         return WERR_OK;
2571 }
2572
2573 /*******************************************************************
2574  * fill a notify_info_data with the servername
2575  ********************************************************************/
2576
2577 void spoolss_notify_server_name(int snum,
2578                                        struct spoolss_Notify *data,
2579                                        print_queue_struct *queue,
2580                                        NT_PRINTER_INFO_LEVEL *printer,
2581                                        TALLOC_CTX *mem_ctx)
2582 {
2583         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2584 }
2585
2586 /*******************************************************************
2587  * fill a notify_info_data with the printername (not including the servername).
2588  ********************************************************************/
2589
2590 void spoolss_notify_printer_name(int snum,
2591                                         struct spoolss_Notify *data,
2592                                         print_queue_struct *queue,
2593                                         NT_PRINTER_INFO_LEVEL *printer,
2594                                         TALLOC_CTX *mem_ctx)
2595 {
2596         /* the notify name should not contain the \\server\ part */
2597         char *p = strrchr(printer->info_2->printername, '\\');
2598
2599         if (!p) {
2600                 p = printer->info_2->printername;
2601         } else {
2602                 p++;
2603         }
2604
2605         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2606 }
2607
2608 /*******************************************************************
2609  * fill a notify_info_data with the servicename
2610  ********************************************************************/
2611
2612 void spoolss_notify_share_name(int snum,
2613                                       struct spoolss_Notify *data,
2614                                       print_queue_struct *queue,
2615                                       NT_PRINTER_INFO_LEVEL *printer,
2616                                       TALLOC_CTX *mem_ctx)
2617 {
2618         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2619 }
2620
2621 /*******************************************************************
2622  * fill a notify_info_data with the port name
2623  ********************************************************************/
2624
2625 void spoolss_notify_port_name(int snum,
2626                                      struct spoolss_Notify *data,
2627                                      print_queue_struct *queue,
2628                                      NT_PRINTER_INFO_LEVEL *printer,
2629                                      TALLOC_CTX *mem_ctx)
2630 {
2631         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2632 }
2633
2634 /*******************************************************************
2635  * fill a notify_info_data with the printername
2636  * but it doesn't exist, have to see what to do
2637  ********************************************************************/
2638
2639 void spoolss_notify_driver_name(int snum,
2640                                        struct spoolss_Notify *data,
2641                                        print_queue_struct *queue,
2642                                        NT_PRINTER_INFO_LEVEL *printer,
2643                                        TALLOC_CTX *mem_ctx)
2644 {
2645         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2646 }
2647
2648 /*******************************************************************
2649  * fill a notify_info_data with the comment
2650  ********************************************************************/
2651
2652 void spoolss_notify_comment(int snum,
2653                                    struct spoolss_Notify *data,
2654                                    print_queue_struct *queue,
2655                                    NT_PRINTER_INFO_LEVEL *printer,
2656                                    TALLOC_CTX *mem_ctx)
2657 {
2658         char *p;
2659
2660         if (*printer->info_2->comment == '\0') {
2661                 p = lp_comment(snum);
2662         } else {
2663                 p = printer->info_2->comment;
2664         }
2665
2666         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2667 }
2668
2669 /*******************************************************************
2670  * fill a notify_info_data with the comment
2671  * location = "Room 1, floor 2, building 3"
2672  ********************************************************************/
2673
2674 void spoolss_notify_location(int snum,
2675                                     struct spoolss_Notify *data,
2676                                     print_queue_struct *queue,
2677                                     NT_PRINTER_INFO_LEVEL *printer,
2678                                     TALLOC_CTX *mem_ctx)
2679 {
2680         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2681 }
2682
2683 /*******************************************************************
2684  * fill a notify_info_data with the device mode
2685  * jfm:xxxx don't to it for know but that's a real problem !!!
2686  ********************************************************************/
2687
2688 static void spoolss_notify_devmode(int snum,
2689                                    struct spoolss_Notify *data,
2690                                    print_queue_struct *queue,
2691                                    NT_PRINTER_INFO_LEVEL *printer,
2692                                    TALLOC_CTX *mem_ctx)
2693 {
2694         /* for a dummy implementation we have to zero the fields */
2695         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2696 }
2697
2698 /*******************************************************************
2699  * fill a notify_info_data with the separator file name
2700  ********************************************************************/
2701
2702 void spoolss_notify_sepfile(int snum,
2703                                    struct spoolss_Notify *data,
2704                                    print_queue_struct *queue,
2705                                    NT_PRINTER_INFO_LEVEL *printer,
2706                                    TALLOC_CTX *mem_ctx)
2707 {
2708         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2709 }
2710
2711 /*******************************************************************
2712  * fill a notify_info_data with the print processor
2713  * jfm:xxxx return always winprint to indicate we don't do anything to it
2714  ********************************************************************/
2715
2716 void spoolss_notify_print_processor(int snum,
2717                                            struct spoolss_Notify *data,
2718                                            print_queue_struct *queue,
2719                                            NT_PRINTER_INFO_LEVEL *printer,
2720                                            TALLOC_CTX *mem_ctx)
2721 {
2722         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2723 }
2724
2725 /*******************************************************************
2726  * fill a notify_info_data with the print processor options
2727  * jfm:xxxx send an empty string
2728  ********************************************************************/
2729
2730 void spoolss_notify_parameters(int snum,
2731                                       struct spoolss_Notify *data,
2732                                       print_queue_struct *queue,
2733                                       NT_PRINTER_INFO_LEVEL *printer,
2734                                       TALLOC_CTX *mem_ctx)
2735 {
2736         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2737 }
2738
2739 /*******************************************************************
2740  * fill a notify_info_data with the data type
2741  * jfm:xxxx always send RAW as data type
2742  ********************************************************************/
2743
2744 void spoolss_notify_datatype(int snum,
2745                                     struct spoolss_Notify *data,
2746                                     print_queue_struct *queue,
2747                                     NT_PRINTER_INFO_LEVEL *printer,
2748                                     TALLOC_CTX *mem_ctx)
2749 {
2750         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2751 }
2752
2753 /*******************************************************************
2754  * fill a notify_info_data with the security descriptor
2755  * jfm:xxxx send an null pointer to say no security desc
2756  * have to implement security before !
2757  ********************************************************************/
2758
2759 static void spoolss_notify_security_desc(int snum,
2760                                          struct spoolss_Notify *data,
2761                                          print_queue_struct *queue,
2762                                          NT_PRINTER_INFO_LEVEL *printer,
2763                                          TALLOC_CTX *mem_ctx)
2764 {
2765         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2766                                           printer->info_2->secdesc_buf->sd_size,
2767                                           printer->info_2->secdesc_buf->sd);
2768 }
2769
2770 /*******************************************************************
2771  * fill a notify_info_data with the attributes
2772  * jfm:xxxx a samba printer is always shared
2773  ********************************************************************/
2774
2775 void spoolss_notify_attributes(int snum,
2776                                       struct spoolss_Notify *data,
2777                                       print_queue_struct *queue,
2778                                       NT_PRINTER_INFO_LEVEL *printer,
2779                                       TALLOC_CTX *mem_ctx)
2780 {
2781         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2782 }
2783
2784 /*******************************************************************
2785  * fill a notify_info_data with the priority
2786  ********************************************************************/
2787
2788 static void spoolss_notify_priority(int snum,
2789                                     struct spoolss_Notify *data,
2790                                     print_queue_struct *queue,
2791                                     NT_PRINTER_INFO_LEVEL *printer,
2792                                     TALLOC_CTX *mem_ctx)
2793 {
2794         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2795 }
2796
2797 /*******************************************************************
2798  * fill a notify_info_data with the default priority
2799  ********************************************************************/
2800
2801 static void spoolss_notify_default_priority(int snum,
2802                                             struct spoolss_Notify *data,
2803                                             print_queue_struct *queue,
2804                                             NT_PRINTER_INFO_LEVEL *printer,
2805                                             TALLOC_CTX *mem_ctx)
2806 {
2807         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2808 }
2809
2810 /*******************************************************************
2811  * fill a notify_info_data with the start time
2812  ********************************************************************/
2813
2814 static void spoolss_notify_start_time(int snum,
2815                                       struct spoolss_Notify *data,
2816                                       print_queue_struct *queue,
2817                                       NT_PRINTER_INFO_LEVEL *printer,
2818                                       TALLOC_CTX *mem_ctx)
2819 {
2820         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2821 }
2822
2823 /*******************************************************************
2824  * fill a notify_info_data with the until time
2825  ********************************************************************/
2826
2827 static void spoolss_notify_until_time(int snum,
2828                                       struct spoolss_Notify *data,
2829                                       print_queue_struct *queue,
2830                                       NT_PRINTER_INFO_LEVEL *printer,
2831                                       TALLOC_CTX *mem_ctx)
2832 {
2833         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2834 }
2835
2836 /*******************************************************************
2837  * fill a notify_info_data with the status
2838  ********************************************************************/
2839
2840 static void spoolss_notify_status(int snum,
2841                                   struct spoolss_Notify *data,
2842                                   print_queue_struct *queue,
2843                                   NT_PRINTER_INFO_LEVEL *printer,
2844                                   TALLOC_CTX *mem_ctx)
2845 {
2846         print_status_struct status;
2847
2848         print_queue_length(snum, &status);
2849         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2850 }
2851
2852 /*******************************************************************
2853  * fill a notify_info_data with the number of jobs queued
2854  ********************************************************************/
2855
2856 void spoolss_notify_cjobs(int snum,
2857                                  struct spoolss_Notify *data,
2858                                  print_queue_struct *queue,
2859                                  NT_PRINTER_INFO_LEVEL *printer,
2860                                  TALLOC_CTX *mem_ctx)
2861 {
2862         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2863 }
2864
2865 /*******************************************************************
2866  * fill a notify_info_data with the average ppm
2867  ********************************************************************/
2868
2869 static void spoolss_notify_average_ppm(int snum,
2870                                        struct spoolss_Notify *data,
2871                                        print_queue_struct *queue,
2872                                        NT_PRINTER_INFO_LEVEL *printer,
2873                                        TALLOC_CTX *mem_ctx)
2874 {
2875         /* always respond 8 pages per minutes */
2876         /* a little hard ! */
2877         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2878 }
2879
2880 /*******************************************************************
2881  * fill a notify_info_data with username
2882  ********************************************************************/
2883
2884 static void spoolss_notify_username(int snum,
2885                                     struct spoolss_Notify *data,
2886                                     print_queue_struct *queue,
2887                                     NT_PRINTER_INFO_LEVEL *printer,
2888                                     TALLOC_CTX *mem_ctx)
2889 {
2890         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2891 }
2892
2893 /*******************************************************************
2894  * fill a notify_info_data with job status
2895  ********************************************************************/
2896
2897 static void spoolss_notify_job_status(int snum,
2898                                       struct spoolss_Notify *data,
2899                                       print_queue_struct *queue,
2900                                       NT_PRINTER_INFO_LEVEL *printer,
2901                                       TALLOC_CTX *mem_ctx)
2902 {
2903         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2904 }
2905
2906 /*******************************************************************
2907  * fill a notify_info_data with job name
2908  ********************************************************************/
2909
2910 static void spoolss_notify_job_name(int snum,
2911                                     struct spoolss_Notify *data,
2912                                     print_queue_struct *queue,
2913                                     NT_PRINTER_INFO_LEVEL *printer,
2914                                     TALLOC_CTX *mem_ctx)
2915 {
2916         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2917 }
2918
2919 /*******************************************************************
2920  * fill a notify_info_data with job status
2921  ********************************************************************/
2922
2923 static void spoolss_notify_job_status_string(int snum,
2924                                              struct spoolss_Notify *data,
2925                                              print_queue_struct *queue,
2926                                              NT_PRINTER_INFO_LEVEL *printer,
2927                                              TALLOC_CTX *mem_ctx)
2928 {
2929         /*
2930          * Now we're returning job status codes we just return a "" here. JRA.
2931          */
2932
2933         const char *p = "";
2934
2935 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2936         p = "unknown";
2937
2938         switch (queue->status) {
2939         case LPQ_QUEUED:
2940                 p = "Queued";
2941                 break;
2942         case LPQ_PAUSED:
2943                 p = "";    /* NT provides the paused string */
2944                 break;
2945         case LPQ_SPOOLING:
2946                 p = "Spooling";
2947                 break;
2948         case LPQ_PRINTING:
2949                 p = "Printing";
2950                 break;
2951         }
2952 #endif /* NO LONGER NEEDED. */
2953
2954         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2955 }
2956
2957 /*******************************************************************
2958  * fill a notify_info_data with job time
2959  ********************************************************************/
2960
2961 static void spoolss_notify_job_time(int snum,
2962                                     struct spoolss_Notify *data,
2963                                     print_queue_struct *queue,
2964                                     NT_PRINTER_INFO_LEVEL *printer,
2965                                     TALLOC_CTX *mem_ctx)
2966 {
2967         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2968 }
2969
2970 /*******************************************************************
2971  * fill a notify_info_data with job size
2972  ********************************************************************/
2973
2974 static void spoolss_notify_job_size(int snum,
2975                                     struct spoolss_Notify *data,
2976                                     print_queue_struct *queue,
2977                                     NT_PRINTER_INFO_LEVEL *printer,
2978                                     TALLOC_CTX *mem_ctx)
2979 {
2980         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2981 }
2982
2983 /*******************************************************************
2984  * fill a notify_info_data with page info
2985  ********************************************************************/
2986 static void spoolss_notify_total_pages(int snum,
2987                                 struct spoolss_Notify *data,
2988                                 print_queue_struct *queue,
2989                                 NT_PRINTER_INFO_LEVEL *printer,
2990                                 TALLOC_CTX *mem_ctx)
2991 {
2992         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2993 }
2994
2995 /*******************************************************************
2996  * fill a notify_info_data with pages printed info.
2997  ********************************************************************/
2998 static void spoolss_notify_pages_printed(int snum,
2999                                 struct spoolss_Notify *data,
3000                                 print_queue_struct *queue,
3001                                 NT_PRINTER_INFO_LEVEL *printer,
3002                                 TALLOC_CTX *mem_ctx)
3003 {
3004         /* Add code when back-end tracks this */
3005         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3006 }
3007
3008 /*******************************************************************
3009  Fill a notify_info_data with job position.
3010  ********************************************************************/
3011
3012 static void spoolss_notify_job_position(int snum,
3013                                         struct spoolss_Notify *data,
3014                                         print_queue_struct *queue,
3015                                         NT_PRINTER_INFO_LEVEL *printer,
3016                                         TALLOC_CTX *mem_ctx)
3017 {
3018         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3019 }
3020
3021 /*******************************************************************
3022  Fill a notify_info_data with submitted time.
3023  ********************************************************************/
3024
3025 static void spoolss_notify_submitted_time(int snum,
3026                                           struct spoolss_Notify *data,
3027                                           print_queue_struct *queue,
3028                                           NT_PRINTER_INFO_LEVEL *printer,
3029                                           TALLOC_CTX *mem_ctx)
3030 {
3031         data->data.string.string = NULL;
3032         data->data.string.size = 0;
3033
3034         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3035                                &data->data.string.string,
3036                                &data->data.string.size);
3037
3038 }
3039
3040 struct s_notify_info_data_table
3041 {
3042         enum spoolss_NotifyType type;
3043         uint16_t field;
3044         const char *name;
3045         enum spoolss_NotifyTable variable_type;
3046         void (*fn) (int snum, struct spoolss_Notify *data,
3047                     print_queue_struct *queue,
3048                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3049 };
3050
3051 /* A table describing the various print notification constants and
3052    whether the notification data is a pointer to a variable sized
3053    buffer, a one value uint32_t or a two value uint32_t. */
3054
3055 static const struct s_notify_info_data_table notify_info_data_table[] =
3056 {
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3083 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3084 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3085 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3086 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3087 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3088 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3100 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3101 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3102 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3103 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3104 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3105 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3106 };
3107
3108 /*******************************************************************
3109  Return the variable_type of info_data structure.
3110 ********************************************************************/
3111
3112 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3113                                                   uint16_t field)
3114 {
3115         int i=0;
3116
3117         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3118                 if ( (notify_info_data_table[i].type == type) &&
3119                      (notify_info_data_table[i].field == field) ) {
3120                         return notify_info_data_table[i].variable_type;
3121                 }
3122         }
3123
3124         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3125
3126         return 0;
3127 }
3128
3129 /****************************************************************************
3130 ****************************************************************************/
3131
3132 static bool search_notify(enum spoolss_NotifyType type,
3133                           uint16_t field,
3134                           int *value)
3135 {
3136         int i;
3137
3138         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3139                 if (notify_info_data_table[i].type == type &&
3140                     notify_info_data_table[i].field == field &&
3141                     notify_info_data_table[i].fn != NULL) {
3142                         *value = i;
3143                         return true;
3144                 }
3145         }
3146
3147         return false;
3148 }
3149
3150 /****************************************************************************
3151 ****************************************************************************/
3152
3153 void construct_info_data(struct spoolss_Notify *info_data,
3154                          enum spoolss_NotifyType type,
3155                          uint16_t field,
3156                          int id)
3157 {
3158         info_data->type                 = type;
3159         info_data->field.field          = field;
3160         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3161         info_data->job_id               = id;
3162 }
3163
3164 /*******************************************************************
3165  *
3166  * fill a notify_info struct with info asked
3167  *
3168  ********************************************************************/
3169
3170 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3171                                           struct spoolss_NotifyInfo *info,
3172                                           int snum,
3173                                           const struct spoolss_NotifyOptionType *option_type,
3174                                           uint32_t id,
3175                                           TALLOC_CTX *mem_ctx)
3176 {
3177         int field_num,j;
3178         enum spoolss_NotifyType type;
3179         uint16_t field;
3180
3181         struct spoolss_Notify *current_data;
3182         NT_PRINTER_INFO_LEVEL *printer = NULL;
3183         print_queue_struct *queue=NULL;
3184
3185         type = option_type->type;
3186
3187         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3188                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3189                 option_type->count, lp_servicename(snum)));
3190
3191         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3192                 return false;
3193
3194         for(field_num=0; field_num < option_type->count; field_num++) {
3195                 field = option_type->fields[field_num].field;
3196
3197                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3198
3199                 if (!search_notify(type, field, &j) )
3200                         continue;
3201
3202                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3203                                                       struct spoolss_Notify,
3204                                                       info->count + 1);
3205                 if (info->notifies == NULL) {
3206                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3207                         free_a_printer(&printer, 2);
3208                         return false;
3209                 }
3210
3211                 current_data = &info->notifies[info->count];
3212
3213                 construct_info_data(current_data, type, field, id);
3214
3215                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3216                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3217
3218                 notify_info_data_table[j].fn(snum, current_data, queue,
3219                                              printer, mem_ctx);
3220
3221                 info->count++;
3222         }
3223
3224         free_a_printer(&printer, 2);
3225         return true;
3226 }
3227
3228 /*******************************************************************
3229  *
3230  * fill a notify_info struct with info asked
3231  *
3232  ********************************************************************/
3233
3234 static bool construct_notify_jobs_info(print_queue_struct *queue,
3235                                        struct spoolss_NotifyInfo *info,
3236                                        NT_PRINTER_INFO_LEVEL *printer,
3237                                        int snum,
3238                                        const struct spoolss_NotifyOptionType *option_type,
3239                                        uint32_t id,
3240                                        TALLOC_CTX *mem_ctx)
3241 {
3242         int field_num,j;
3243         enum spoolss_NotifyType type;
3244         uint16_t field;
3245         struct spoolss_Notify *current_data;
3246
3247         DEBUG(4,("construct_notify_jobs_info\n"));
3248
3249         type = option_type->type;
3250
3251         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3252                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3253                 option_type->count));
3254
3255         for(field_num=0; field_num<option_type->count; field_num++) {
3256                 field = option_type->fields[field_num].field;
3257
3258                 if (!search_notify(type, field, &j) )
3259                         continue;
3260
3261                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3262                                                       struct spoolss_Notify,
3263                                                       info->count + 1);
3264                 if (info->notifies == NULL) {
3265                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3266                         return false;
3267                 }
3268
3269                 current_data=&(info->notifies[info->count]);
3270
3271                 construct_info_data(current_data, type, field, id);
3272                 notify_info_data_table[j].fn(snum, current_data, queue,
3273                                              printer, mem_ctx);
3274                 info->count++;
3275         }
3276
3277         return true;
3278 }
3279
3280 /*
3281  * JFM: The enumeration is not that simple, it's even non obvious.
3282  *
3283  * let's take an example: I want to monitor the PRINTER SERVER for
3284  * the printer's name and the number of jobs currently queued.
3285  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3286  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3287  *
3288  * I have 3 printers on the back of my server.
3289  *
3290  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3291  * structures.
3292  *   Number     Data                    Id
3293  *      1       printer 1 name          1
3294  *      2       printer 1 cjob          1
3295  *      3       printer 2 name          2
3296  *      4       printer 2 cjob          2
3297  *      5       printer 3 name          3
3298  *      6       printer 3 name          3
3299  *
3300  * that's the print server case, the printer case is even worse.
3301  */
3302
3303 /*******************************************************************
3304  *
3305  * enumerate all printers on the printserver
3306  * fill a notify_info struct with info asked
3307  *
3308  ********************************************************************/
3309
3310 static WERROR printserver_notify_info(pipes_struct *p,
3311                                       struct policy_handle *hnd,
3312                                       struct spoolss_NotifyInfo *info,
3313                                       TALLOC_CTX *mem_ctx)
3314 {
3315         int snum;
3316         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3317         int n_services=lp_numservices();
3318         int i;
3319         struct spoolss_NotifyOption *option;
3320         struct spoolss_NotifyOptionType option_type;
3321
3322         DEBUG(4,("printserver_notify_info\n"));
3323
3324         if (!Printer)
3325                 return WERR_BADFID;
3326
3327         option = Printer->notify.option;
3328
3329         info->version   = 2;
3330         info->notifies  = NULL;
3331         info->count     = 0;
3332
3333         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3334            sending a ffpcn() request first */
3335
3336         if ( !option )
3337                 return WERR_BADFID;
3338
3339         for (i=0; i<option->count; i++) {
3340                 option_type = option->types[i];
3341
3342                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3343                         continue;
3344
3345                 for (snum=0; snum<n_services; snum++)
3346                 {
3347                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3348                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3349                 }
3350         }
3351
3352 #if 0
3353         /*
3354          * Debugging information, don't delete.
3355          */
3356
3357         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3358         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3359         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3360
3361         for (i=0; i<info->count; i++) {
3362                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3363                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3364                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3365         }
3366 #endif
3367
3368         return WERR_OK;
3369 }
3370
3371 /*******************************************************************
3372  *
3373  * fill a notify_info struct with info asked
3374  *
3375  ********************************************************************/
3376
3377 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3378                                   struct spoolss_NotifyInfo *info,
3379                                   TALLOC_CTX *mem_ctx)
3380 {
3381         int snum;
3382         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3383         int i;
3384         uint32_t id;
3385         struct spoolss_NotifyOption *option;
3386         struct spoolss_NotifyOptionType option_type;
3387         int count,j;
3388         print_queue_struct *queue=NULL;
3389         print_status_struct status;
3390
3391         DEBUG(4,("printer_notify_info\n"));
3392
3393         if (!Printer)
3394                 return WERR_BADFID;
3395
3396         option = Printer->notify.option;
3397         id = 0x0;
3398
3399         info->version   = 2;
3400         info->notifies  = NULL;
3401         info->count     = 0;
3402
3403         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3404            sending a ffpcn() request first */
3405
3406         if ( !option )
3407                 return WERR_BADFID;
3408
3409         get_printer_snum(p, hnd, &snum, NULL);
3410
3411         for (i=0; i<option->count; i++) {
3412                 option_type = option->types[i];
3413
3414                 switch (option_type.type) {
3415                 case PRINTER_NOTIFY_TYPE:
3416                         if(construct_notify_printer_info(Printer, info, snum,
3417                                                          &option_type, id,
3418                                                          mem_ctx))
3419                                 id--;
3420                         break;
3421
3422                 case JOB_NOTIFY_TYPE: {
3423                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3424
3425                         count = print_queue_status(snum, &queue, &status);
3426
3427                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3428                                 goto done;
3429
3430                         for (j=0; j<count; j++) {
3431                                 construct_notify_jobs_info(&queue[j], info,
3432                                                            printer, snum,
3433                                                            &option_type,
3434                                                            queue[j].job,
3435                                                            mem_ctx);
3436                         }
3437
3438                         free_a_printer(&printer, 2);
3439
3440                 done:
3441                         SAFE_FREE(queue);
3442                         break;
3443                 }
3444                 }
3445         }
3446
3447         /*
3448          * Debugging information, don't delete.
3449          */
3450         /*
3451         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3452         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3453         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3454
3455         for (i=0; i<info->count; i++) {
3456                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3457                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3458                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3459         }
3460         */
3461         return WERR_OK;
3462 }
3463
3464 /****************************************************************
3465  _spoolss_RouterRefreshPrinterChangeNotify
3466 ****************************************************************/
3467
3468 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3469                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3470 {
3471         struct spoolss_NotifyInfo *info;
3472
3473         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3474         WERROR result = WERR_BADFID;
3475
3476         /* we always have a spoolss_NotifyInfo struct */
3477         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3478         if (!info) {
3479                 result = WERR_NOMEM;
3480                 goto done;
3481         }
3482
3483         *r->out.info = info;
3484
3485         if (!Printer) {
3486                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3487                         "Invalid handle (%s:%u:%u).\n",
3488                         OUR_HANDLE(r->in.handle)));
3489                 goto done;
3490         }
3491
3492         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3493
3494         /*
3495          *      We are now using the change value, and
3496          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3497          *      I don't have a global notification system, I'm sending back all the
3498          *      informations even when _NOTHING_ has changed.
3499          */
3500
3501         /* We need to keep track of the change value to send back in
3502            RRPCN replies otherwise our updates are ignored. */
3503
3504         Printer->notify.fnpcn = true;
3505
3506         if (Printer->notify.client_connected) {
3507                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3508                         "Saving change value in request [%x]\n",
3509                         r->in.change_low));
3510                 Printer->notify.change = r->in.change_low;
3511         }
3512
3513         /* just ignore the spoolss_NotifyOption */
3514
3515         switch (Printer->printer_type) {
3516                 case SPLHND_SERVER:
3517                         result = printserver_notify_info(p, r->in.handle,
3518                                                          info, p->mem_ctx);
3519                         break;
3520
3521                 case SPLHND_PRINTER:
3522                         result = printer_notify_info(p, r->in.handle,
3523                                                      info, p->mem_ctx);
3524                         break;
3525         }
3526
3527         Printer->notify.fnpcn = false;
3528
3529 done:
3530         return result;
3531 }
3532
3533 /********************************************************************
3534  * construct_printer_info_0
3535  * fill a printer_info_0 struct
3536  ********************************************************************/
3537
3538 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3539                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3540                                       struct spoolss_PrinterInfo0 *r,
3541                                       int snum)
3542 {
3543         int count;
3544         counter_printer_0 *session_counter;
3545         time_t setuptime;
3546         print_status_struct status;
3547
3548         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3549         W_ERROR_HAVE_NO_MEMORY(r->printername);
3550
3551         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3552         W_ERROR_HAVE_NO_MEMORY(r->servername);
3553
3554         count = print_queue_length(snum, &status);
3555
3556         /* check if we already have a counter for this printer */
3557         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3558                 if (session_counter->snum == snum)
3559                         break;
3560         }
3561
3562         /* it's the first time, add it to the list */
3563         if (session_counter == NULL) {
3564                 session_counter = SMB_MALLOC_P(counter_printer_0);
3565                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3566                 ZERO_STRUCTP(session_counter);
3567                 session_counter->snum           = snum;
3568                 session_counter->counter        = 0;
3569                 DLIST_ADD(counter_list, session_counter);
3570         }
3571
3572         /* increment it */
3573         session_counter->counter++;
3574
3575         r->cjobs                        = count;
3576         r->total_jobs                   = 0;
3577         r->total_bytes                  = 0;
3578
3579         setuptime = (time_t)ntprinter->info_2->setuptime;
3580
3581         init_systemtime(&r->time, gmtime(&setuptime));
3582
3583         /* JFM:
3584          * the global_counter should be stored in a TDB as it's common to all the clients
3585          * and should be zeroed on samba startup
3586          */
3587         r->global_counter               = session_counter->counter;
3588         r->total_pages                  = 0;
3589         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3590         r->version                      = 0x0005;       /* NT 5 */
3591         r->free_build                   = 0x0893;       /* build 2195 */
3592         r->spooling                     = 0;
3593         r->max_spooling                 = 0;
3594         r->session_counter              = session_counter->counter;
3595         r->num_error_out_of_paper       = 0x0;
3596         r->num_error_not_ready          = 0x0;          /* number of print failure */
3597         r->job_error                    = 0x0;
3598         r->number_of_processors         = 0x1;
3599         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3600         r->high_part_total_bytes        = 0x0;
3601         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3602         r->last_error                   = WERR_OK;
3603         r->status                       = nt_printq_status(status.status);
3604         r->enumerate_network_printers   = 0x0;
3605         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3606         r->processor_architecture       = 0x0;
3607         r->processor_level              = 0x6;          /* 6  ???*/
3608         r->ref_ic                       = 0;
3609         r->reserved2                    = 0;
3610         r->reserved3                    = 0;
3611
3612         return WERR_OK;
3613 }
3614
3615 /****************************************************************************
3616  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3617  should be valid upon entry
3618 ****************************************************************************/
3619
3620 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3621                                     struct spoolss_DeviceMode *r,
3622                                     const NT_DEVICEMODE *ntdevmode)
3623 {
3624         if (!r || !ntdevmode) {
3625                 return WERR_INVALID_PARAM;
3626         }
3627
3628         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3629         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3630
3631         r->specversion          = ntdevmode->specversion;
3632         r->driverversion        = ntdevmode->driverversion;
3633         r->size                 = ntdevmode->size;
3634         r->__driverextra_length = ntdevmode->driverextra;
3635         r->fields               = ntdevmode->fields;
3636
3637         r->orientation          = ntdevmode->orientation;
3638         r->papersize            = ntdevmode->papersize;
3639         r->paperlength          = ntdevmode->paperlength;
3640         r->paperwidth           = ntdevmode->paperwidth;
3641         r->scale                = ntdevmode->scale;
3642         r->copies               = ntdevmode->copies;
3643         r->defaultsource        = ntdevmode->defaultsource;
3644         r->printquality         = ntdevmode->printquality;
3645         r->color                = ntdevmode->color;
3646         r->duplex               = ntdevmode->duplex;
3647         r->yresolution          = ntdevmode->yresolution;
3648         r->ttoption             = ntdevmode->ttoption;
3649         r->collate              = ntdevmode->collate;
3650
3651         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3652         W_ERROR_HAVE_NO_MEMORY(r->formname);
3653
3654         /* all 0 below are values that have not been set in the old parsing/copy
3655          * function, maybe they should... - gd */
3656
3657         r->logpixels            = 0;
3658         r->bitsperpel           = 0;
3659         r->pelswidth            = 0;
3660         r->pelsheight           = 0;
3661         r->displayflags         = 0;
3662         r->displayfrequency     = 0;
3663         r->icmmethod            = ntdevmode->icmmethod;
3664         r->icmintent            = ntdevmode->icmintent;
3665         r->mediatype            = ntdevmode->mediatype;
3666         r->dithertype           = ntdevmode->dithertype;
3667         r->reserved1            = 0;
3668         r->reserved2            = 0;
3669         r->panningwidth         = 0;
3670         r->panningheight        = 0;
3671
3672         if (ntdevmode->nt_dev_private != NULL) {
3673                 r->driverextra_data = data_blob_talloc(mem_ctx,
3674                         ntdevmode->nt_dev_private,
3675                         ntdevmode->driverextra);
3676                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3677         }
3678
3679         return WERR_OK;
3680 }
3681
3682
3683 /****************************************************************************
3684  Create a spoolss_DeviceMode struct. Returns talloced memory.
3685 ****************************************************************************/
3686
3687 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3688                                               const char *servicename)
3689 {
3690         WERROR result;
3691         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3692         struct spoolss_DeviceMode *devmode = NULL;
3693
3694         DEBUG(7,("construct_dev_mode\n"));
3695
3696         DEBUGADD(8,("getting printer characteristics\n"));
3697
3698         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3699                 return NULL;
3700
3701         if (!printer->info_2->devmode) {
3702                 DEBUG(5, ("BONG! There was no device mode!\n"));
3703                 goto done;
3704         }
3705
3706         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3707         if (!devmode) {
3708                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3709                 goto done;
3710         }
3711
3712         DEBUGADD(8,("loading DEVICEMODE\n"));
3713
3714         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3715         if (!W_ERROR_IS_OK(result)) {
3716                 TALLOC_FREE(devmode);
3717         }
3718
3719 done:
3720         free_a_printer(&printer,2);
3721
3722         return devmode;
3723 }
3724
3725 /********************************************************************
3726  * construct_printer_info1
3727  * fill a spoolss_PrinterInfo1 struct
3728 ********************************************************************/
3729
3730 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3731                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3732                                       uint32_t flags,
3733                                       struct spoolss_PrinterInfo1 *r,
3734                                       int snum)
3735 {
3736         r->flags                = flags;
3737
3738         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3739                                                   ntprinter->info_2->printername,
3740                                                   ntprinter->info_2->drivername,
3741                                                   ntprinter->info_2->location);
3742         W_ERROR_HAVE_NO_MEMORY(r->description);
3743
3744         if (*ntprinter->info_2->comment == '\0') {
3745                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3746         } else {
3747                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3748         }
3749         W_ERROR_HAVE_NO_MEMORY(r->comment);
3750
3751         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3752         W_ERROR_HAVE_NO_MEMORY(r->name);
3753
3754         return WERR_OK;
3755 }
3756
3757 /********************************************************************
3758  * construct_printer_info2
3759  * fill a spoolss_PrinterInfo2 struct
3760 ********************************************************************/
3761
3762 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3763                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3764                                       struct spoolss_PrinterInfo2 *r,
3765                                       int snum)
3766 {
3767         int count;
3768
3769         print_status_struct status;
3770
3771         count = print_queue_length(snum, &status);
3772
3773         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3774         W_ERROR_HAVE_NO_MEMORY(r->servername);
3775         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3776         W_ERROR_HAVE_NO_MEMORY(r->printername);
3777         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3778         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3779         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3780         W_ERROR_HAVE_NO_MEMORY(r->portname);
3781         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3782         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3783
3784         if (*ntprinter->info_2->comment == '\0') {
3785                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3786         } else {
3787                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3788         }
3789         W_ERROR_HAVE_NO_MEMORY(r->comment);
3790
3791         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3792         W_ERROR_HAVE_NO_MEMORY(r->location);
3793         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3794         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3795         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3796         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3797         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3798         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3799         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3800         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3801
3802         r->attributes           = ntprinter->info_2->attributes;
3803
3804         r->priority             = ntprinter->info_2->priority;
3805         r->defaultpriority      = ntprinter->info_2->default_priority;
3806         r->starttime            = ntprinter->info_2->starttime;
3807         r->untiltime            = ntprinter->info_2->untiltime;
3808         r->status               = nt_printq_status(status.status);
3809         r->cjobs                = count;
3810         r->averageppm           = ntprinter->info_2->averageppm;
3811
3812         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3813         if (!r->devmode) {
3814                 DEBUG(8,("Returning NULL Devicemode!\n"));
3815         }
3816
3817         r->secdesc              = NULL;
3818
3819         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3820                 /* don't use talloc_steal() here unless you do a deep steal of all
3821                    the SEC_DESC members */
3822
3823                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3824         }
3825
3826         return WERR_OK;
3827 }
3828
3829 /********************************************************************
3830  * construct_printer_info3
3831  * fill a spoolss_PrinterInfo3 struct
3832  ********************************************************************/
3833
3834 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3835                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3836                                       struct spoolss_PrinterInfo3 *r,
3837                                       int snum)
3838 {
3839         /* These are the components of the SD we are returning. */
3840
3841         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3842                 /* don't use talloc_steal() here unless you do a deep steal of all
3843                    the SEC_DESC members */
3844
3845                 r->secdesc = dup_sec_desc(mem_ctx,
3846                                           ntprinter->info_2->secdesc_buf->sd);
3847                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3848         }
3849
3850         return WERR_OK;
3851 }
3852
3853 /********************************************************************
3854  * construct_printer_info4
3855  * fill a spoolss_PrinterInfo4 struct
3856  ********************************************************************/
3857
3858 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3859                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3860                                       struct spoolss_PrinterInfo4 *r,
3861                                       int snum)
3862 {
3863         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3864         W_ERROR_HAVE_NO_MEMORY(r->printername);
3865         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3866         W_ERROR_HAVE_NO_MEMORY(r->servername);
3867
3868         r->attributes   = ntprinter->info_2->attributes;
3869
3870         return WERR_OK;
3871 }
3872
3873 /********************************************************************
3874  * construct_printer_info5
3875  * fill a spoolss_PrinterInfo5 struct
3876  ********************************************************************/
3877
3878 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3879                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3880                                       struct spoolss_PrinterInfo5 *r,
3881                                       int snum)
3882 {
3883         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3884         W_ERROR_HAVE_NO_MEMORY(r->printername);
3885         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3886         W_ERROR_HAVE_NO_MEMORY(r->portname);
3887
3888         r->attributes   = ntprinter->info_2->attributes;
3889
3890         /* these two are not used by NT+ according to MSDN */
3891
3892         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3893         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3894
3895         return WERR_OK;
3896 }
3897
3898 /********************************************************************
3899  * construct_printer_info_6
3900  * fill a spoolss_PrinterInfo6 struct
3901  ********************************************************************/
3902
3903 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3904                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3905                                       struct spoolss_PrinterInfo6 *r,
3906                                       int snum)
3907 {
3908         int count;
3909         print_status_struct status;
3910
3911         count = print_queue_length(snum, &status);
3912
3913         r->status = nt_printq_status(status.status);
3914
3915         return WERR_OK;
3916 }
3917
3918 /********************************************************************
3919  * construct_printer_info7
3920  * fill a spoolss_PrinterInfo7 struct
3921  ********************************************************************/
3922
3923 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3924                                       Printer_entry *print_hnd,
3925                                       struct spoolss_PrinterInfo7 *r,
3926                                       int snum)
3927 {
3928         struct GUID guid;
3929
3930         if (is_printer_published(print_hnd, snum, &guid)) {
3931                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3932                 r->action = DSPRINT_PUBLISH;
3933         } else {
3934                 r->guid = talloc_strdup(mem_ctx, "");
3935                 r->action = DSPRINT_UNPUBLISH;
3936         }
3937         W_ERROR_HAVE_NO_MEMORY(r->guid);
3938
3939         return WERR_OK;
3940 }
3941
3942 /********************************************************************
3943  * construct_printer_info8
3944  * fill a spoolss_PrinterInfo8 struct
3945  ********************************************************************/
3946
3947 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3948                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3949                                       struct spoolss_DeviceModeInfo *r,
3950                                       int snum)
3951 {
3952         struct spoolss_DeviceMode *devmode;
3953         WERROR result;
3954
3955         if (!ntprinter->info_2->devmode) {
3956                 r->devmode = NULL;
3957                 return WERR_OK;
3958         }
3959
3960         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3961         W_ERROR_HAVE_NO_MEMORY(devmode);
3962
3963         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
3964         if (!W_ERROR_IS_OK(result)) {
3965                 TALLOC_FREE(devmode);
3966                 return result;
3967         }
3968
3969         r->devmode      = devmode;
3970
3971         return WERR_OK;
3972 }
3973
3974
3975 /********************************************************************
3976 ********************************************************************/
3977
3978 static bool snum_is_shared_printer(int snum)
3979 {
3980         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3981 }
3982
3983 /********************************************************************
3984  Spoolss_enumprinters.
3985 ********************************************************************/
3986
3987 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3988                                            uint32_t level,
3989                                            uint32_t flags,
3990                                            union spoolss_PrinterInfo **info_p,
3991                                            uint32_t *count_p)
3992 {
3993         int snum;
3994         int n_services = lp_numservices();
3995         union spoolss_PrinterInfo *info = NULL;
3996         uint32_t count = 0;
3997         WERROR result = WERR_OK;
3998
3999         *count_p = 0;
4000         *info_p = NULL;
4001
4002         for (snum = 0; snum < n_services; snum++) {
4003
4004                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4005
4006                 if (!snum_is_shared_printer(snum)) {
4007                         continue;
4008                 }
4009
4010                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4011                         lp_servicename(snum), snum));
4012
4013                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4014                                             union spoolss_PrinterInfo,
4015                                             count + 1);
4016                 if (!info) {
4017                         result = WERR_NOMEM;
4018                         goto out;
4019                 }
4020
4021                 result = get_a_printer(NULL, &ntprinter, 2,
4022                                        lp_const_servicename(snum));
4023                 if (!W_ERROR_IS_OK(result)) {
4024                         goto out;
4025                 }
4026
4027                 switch (level) {
4028                 case 0:
4029                         result = construct_printer_info0(info, ntprinter,
4030                                                          &info[count].info0, snum);
4031                         break;
4032                 case 1:
4033                         result = construct_printer_info1(info, ntprinter, flags,
4034                                                          &info[count].info1, snum);
4035                         break;
4036                 case 2:
4037                         result = construct_printer_info2(info, ntprinter,
4038                                                          &info[count].info2, snum);
4039                         break;
4040                 case 4:
4041                         result = construct_printer_info4(info, ntprinter,
4042                                                          &info[count].info4, snum);
4043                         break;
4044                 case 5:
4045                         result = construct_printer_info5(info, ntprinter,
4046                                                          &info[count].info5, snum);
4047                         break;
4048
4049                 default:
4050                         result = WERR_UNKNOWN_LEVEL;
4051                         free_a_printer(&ntprinter, 2);
4052                         goto out;
4053                 }
4054
4055                 free_a_printer(&ntprinter, 2);
4056                 if (!W_ERROR_IS_OK(result)) {
4057                         goto out;
4058                 }
4059
4060                 count++;
4061         }
4062
4063         *count_p = count;
4064         *info_p = info;
4065
4066  out:
4067         if (!W_ERROR_IS_OK(result)) {
4068                 TALLOC_FREE(info);
4069                 return result;
4070         }
4071
4072         *info_p = info;
4073
4074         return WERR_OK;
4075 }
4076
4077 /********************************************************************
4078  * handle enumeration of printers at level 0
4079  ********************************************************************/
4080
4081 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4082                                   uint32_t flags,
4083                                   const char *servername,
4084                                   union spoolss_PrinterInfo **info,
4085                                   uint32_t *count)
4086 {
4087         DEBUG(4,("enum_all_printers_info_0\n"));
4088
4089         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4090 }
4091
4092
4093 /********************************************************************
4094 ********************************************************************/
4095
4096 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4097                                        uint32_t flags,
4098                                        union spoolss_PrinterInfo **info,
4099                                        uint32_t *count)
4100 {
4101         DEBUG(4,("enum_all_printers_info_1\n"));
4102
4103         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4104 }
4105
4106 /********************************************************************
4107  enum_all_printers_info_1_local.
4108 *********************************************************************/
4109
4110 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4111                                              union spoolss_PrinterInfo **info,
4112                                              uint32_t *count)
4113 {
4114         DEBUG(4,("enum_all_printers_info_1_local\n"));
4115
4116         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4117 }
4118
4119 /********************************************************************
4120  enum_all_printers_info_1_name.
4121 *********************************************************************/
4122
4123 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4124                                             const char *name,
4125                                             union spoolss_PrinterInfo **info,
4126                                             uint32_t *count)
4127 {
4128         const char *s = name;
4129
4130         DEBUG(4,("enum_all_printers_info_1_name\n"));
4131
4132         if ((name[0] == '\\') && (name[1] == '\\')) {
4133                 s = name + 2;
4134         }
4135
4136         if (!is_myname_or_ipaddr(s)) {
4137                 return WERR_INVALID_NAME;
4138         }
4139
4140         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4141 }
4142
4143 /********************************************************************
4144  enum_all_printers_info_1_network.
4145 *********************************************************************/
4146
4147 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4148                                                const char *name,
4149                                                union spoolss_PrinterInfo **info,
4150                                                uint32_t *count)
4151 {
4152         const char *s = name;
4153
4154         DEBUG(4,("enum_all_printers_info_1_network\n"));
4155
4156         /* If we respond to a enum_printers level 1 on our name with flags
4157            set to PRINTER_ENUM_REMOTE with a list of printers then these
4158            printers incorrectly appear in the APW browse list.
4159            Specifically the printers for the server appear at the workgroup
4160            level where all the other servers in the domain are
4161            listed. Windows responds to this call with a
4162            WERR_CAN_NOT_COMPLETE so we should do the same. */
4163
4164         if (name[0] == '\\' && name[1] == '\\') {
4165                  s = name + 2;
4166         }
4167
4168         if (is_myname_or_ipaddr(s)) {
4169                  return WERR_CAN_NOT_COMPLETE;
4170         }
4171
4172         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4173 }
4174
4175 /********************************************************************
4176  * api_spoolss_enumprinters
4177  *
4178  * called from api_spoolss_enumprinters (see this to understand)
4179  ********************************************************************/
4180
4181 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4182                                        union spoolss_PrinterInfo **info,
4183                                        uint32_t *count)
4184 {
4185         DEBUG(4,("enum_all_printers_info_2\n"));
4186
4187         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4188 }
4189
4190 /********************************************************************
4191  * handle enumeration of printers at level 1
4192  ********************************************************************/
4193
4194 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4195                                   uint32_t flags,
4196                                   const char *name,
4197                                   union spoolss_PrinterInfo **info,
4198                                   uint32_t *count)
4199 {
4200         /* Not all the flags are equals */
4201
4202         if (flags & PRINTER_ENUM_LOCAL) {
4203                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4204         }
4205
4206         if (flags & PRINTER_ENUM_NAME) {
4207                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4208         }
4209
4210         if (flags & PRINTER_ENUM_NETWORK) {
4211                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4212         }
4213
4214         return WERR_OK; /* NT4sp5 does that */
4215 }
4216
4217 /********************************************************************
4218  * handle enumeration of printers at level 2
4219  ********************************************************************/
4220
4221 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4222                                   uint32_t flags,
4223                                   const char *servername,
4224                                   union spoolss_PrinterInfo **info,
4225                                   uint32_t *count)
4226 {
4227         if (flags & PRINTER_ENUM_LOCAL) {
4228                 return enum_all_printers_info_2(mem_ctx, info, count);
4229         }
4230
4231         if (flags & PRINTER_ENUM_NAME) {
4232                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4233                         return WERR_INVALID_NAME;
4234                 }
4235
4236                 return enum_all_printers_info_2(mem_ctx, info, count);
4237         }
4238
4239         if (flags & PRINTER_ENUM_REMOTE) {
4240                 return WERR_UNKNOWN_LEVEL;
4241         }
4242
4243         return WERR_OK;
4244 }
4245
4246 /********************************************************************
4247  * handle enumeration of printers at level 4
4248  ********************************************************************/
4249
4250 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4251                                   uint32_t flags,
4252                                   const char *servername,
4253                                   union spoolss_PrinterInfo **info,
4254                                   uint32_t *count)
4255 {
4256         DEBUG(4,("enum_all_printers_info_4\n"));
4257
4258         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4259 }
4260
4261
4262 /********************************************************************
4263  * handle enumeration of printers at level 5
4264  ********************************************************************/
4265
4266 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4267                                   uint32_t flags,
4268                                   const char *servername,
4269                                   union spoolss_PrinterInfo **info,
4270                                   uint32_t *count)
4271 {
4272         DEBUG(4,("enum_all_printers_info_5\n"));
4273
4274         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4275 }
4276
4277 /****************************************************************
4278  _spoolss_EnumPrinters
4279 ****************************************************************/
4280
4281 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4282                              struct spoolss_EnumPrinters *r)
4283 {
4284         const char *name = NULL;
4285         WERROR result;
4286
4287         /* that's an [in out] buffer */
4288
4289         if (!r->in.buffer && (r->in.offered != 0)) {
4290                 return WERR_INVALID_PARAM;
4291         }
4292
4293         DEBUG(4,("_spoolss_EnumPrinters\n"));
4294
4295         *r->out.needed = 0;
4296         *r->out.count = 0;
4297         *r->out.info = NULL;
4298
4299         /*
4300          * Level 1:
4301          *          flags==PRINTER_ENUM_NAME
4302          *           if name=="" then enumerates all printers
4303          *           if name!="" then enumerate the printer
4304          *          flags==PRINTER_ENUM_REMOTE
4305          *          name is NULL, enumerate printers
4306          * Level 2: name!="" enumerates printers, name can't be NULL
4307          * Level 3: doesn't exist
4308          * Level 4: does a local registry lookup
4309          * Level 5: same as Level 2
4310          */
4311
4312         if (name) {
4313                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4314                 W_ERROR_HAVE_NO_MEMORY(name);
4315         }
4316
4317         switch (r->in.level) {
4318         case 0:
4319                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4320                                              r->out.info, r->out.count);
4321                 break;
4322         case 1:
4323                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4324                                              r->out.info, r->out.count);
4325                 break;
4326         case 2:
4327                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4328                                              r->out.info, r->out.count);
4329                 break;
4330         case 4:
4331                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4332                                              r->out.info, r->out.count);
4333                 break;
4334         case 5:
4335                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4336                                              r->out.info, r->out.count);
4337                 break;
4338         default:
4339                 return WERR_UNKNOWN_LEVEL;
4340         }
4341
4342         if (!W_ERROR_IS_OK(result)) {
4343                 return result;
4344         }
4345
4346         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4347                                                      spoolss_EnumPrinters, NULL,
4348                                                      *r->out.info, r->in.level,
4349                                                      *r->out.count);
4350         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4351         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4352
4353         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4354 }
4355
4356 /****************************************************************
4357  _spoolss_GetPrinter
4358 ****************************************************************/
4359
4360 WERROR _spoolss_GetPrinter(pipes_struct *p,
4361                            struct spoolss_GetPrinter *r)
4362 {
4363         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4364         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4365         WERROR result = WERR_OK;
4366
4367         int snum;
4368
4369         /* that's an [in out] buffer */
4370
4371         if (!r->in.buffer && (r->in.offered != 0)) {
4372                 return WERR_INVALID_PARAM;
4373         }
4374
4375         *r->out.needed = 0;
4376
4377         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4378                 return WERR_BADFID;
4379         }
4380
4381         result = get_a_printer(Printer, &ntprinter, 2,
4382                                lp_const_servicename(snum));
4383         if (!W_ERROR_IS_OK(result)) {
4384                 return result;
4385         }
4386
4387         switch (r->in.level) {
4388         case 0:
4389                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4390                                                  &r->out.info->info0, snum);
4391                 break;
4392         case 1:
4393                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4394                                                  PRINTER_ENUM_ICON8,
4395                                                  &r->out.info->info1, snum);
4396                 break;
4397         case 2:
4398                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4399                                                  &r->out.info->info2, snum);
4400                 break;
4401         case 3:
4402                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4403                                                  &r->out.info->info3, snum);
4404                 break;
4405         case 4:
4406                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4407                                                  &r->out.info->info4, snum);
4408                 break;
4409         case 5:
4410                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4411                                                  &r->out.info->info5, snum);
4412                 break;
4413         case 6:
4414                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4415                                                  &r->out.info->info6, snum);
4416                 break;
4417         case 7:
4418                 result = construct_printer_info7(p->mem_ctx, Printer,
4419                                                  &r->out.info->info7, snum);
4420                 break;
4421         case 8:
4422                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4423                                                  &r->out.info->info8, snum);
4424                 break;
4425         default:
4426                 result = WERR_UNKNOWN_LEVEL;
4427                 break;
4428         }
4429
4430         free_a_printer(&ntprinter, 2);
4431
4432         if (!W_ERROR_IS_OK(result)) {
4433                 TALLOC_FREE(r->out.info);
4434                 return result;
4435         }
4436
4437         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4438                                                r->out.info, r->in.level);
4439         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4440
4441         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4442 }
4443
4444 /********************************************************************
4445  ********************************************************************/
4446
4447 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4448                                                   const char **string_array,
4449                                                   const char *cservername)
4450 {
4451         int i, num_strings = 0;
4452         const char **array = NULL;
4453
4454         if (!string_array) {
4455                 return NULL;
4456         }
4457
4458         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4459
4460                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4461                                                   cservername, string_array[i]);
4462                 if (!str) {
4463                         TALLOC_FREE(array);
4464                         return NULL;
4465                 }
4466
4467
4468                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4469                         TALLOC_FREE(array);
4470                         return NULL;
4471                 }
4472         }
4473
4474         if (i > 0) {
4475                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4476                              &array, &num_strings);
4477         }
4478
4479         return array;
4480 }
4481
4482 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4483         do { \
4484                 if (in && strlen(in)) { \
4485                         out = talloc_strdup(mem_ctx, in); \
4486                         W_ERROR_HAVE_NO_MEMORY(out); \
4487                 } else { \
4488                         out = NULL; \
4489                 } \
4490         } while (0);
4491
4492 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4493         do { \
4494                 if (in && strlen(in)) { \
4495                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4496                 } else { \
4497                         out = talloc_strdup(mem_ctx, ""); \
4498                 } \
4499                 W_ERROR_HAVE_NO_MEMORY(out); \
4500         } while (0);
4501
4502 /********************************************************************
4503  * fill a spoolss_DriverInfo1 struct
4504  ********************************************************************/
4505
4506 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4507                                         struct spoolss_DriverInfo1 *r,
4508                                         const struct spoolss_DriverInfo8 *driver,
4509                                         const char *servername)
4510 {
4511         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4512         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4513
4514         return WERR_OK;
4515 }
4516
4517 /********************************************************************
4518  * fill a spoolss_DriverInfo2 struct
4519  ********************************************************************/
4520
4521 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4522                                         struct spoolss_DriverInfo2 *r,
4523                                         const struct spoolss_DriverInfo8 *driver,
4524                                         const char *servername)
4525
4526 {
4527         const char *cservername = canon_servername(servername);
4528
4529         r->version              = driver->version;
4530
4531         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4532         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4533         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4534         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4535
4536         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4537                                driver->driver_path,
4538                                r->driver_path);
4539
4540         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4541                                driver->data_file,
4542                                r->data_file);
4543
4544         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4545                                driver->config_file,
4546                                r->config_file);
4547
4548         return WERR_OK;
4549 }
4550
4551 /********************************************************************
4552  * fill a spoolss_DriverInfo3 struct
4553  ********************************************************************/
4554
4555 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4556                                         struct spoolss_DriverInfo3 *r,
4557                                         const struct spoolss_DriverInfo8 *driver,
4558                                         const char *servername)
4559 {
4560         const char *cservername = canon_servername(servername);
4561
4562         r->version              = driver->version;
4563
4564         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4565         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4566         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4567         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4568
4569         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4570                                driver->driver_path,
4571                                r->driver_path);
4572
4573         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4574                                driver->data_file,
4575                                r->data_file);
4576
4577         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4578                                driver->config_file,
4579                                r->config_file);
4580
4581         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4582                                driver->help_file,
4583                                r->help_file);
4584
4585         FILL_DRIVER_STRING(mem_ctx,
4586                            driver->monitor_name,
4587                            r->monitor_name);
4588
4589         FILL_DRIVER_STRING(mem_ctx,
4590                            driver->default_datatype,
4591                            r->default_datatype);
4592
4593         r->dependent_files = string_array_from_driver_info(mem_ctx,
4594                                                            driver->dependent_files,
4595                                                            cservername);
4596         return WERR_OK;
4597 }
4598
4599 /********************************************************************
4600  * fill a spoolss_DriverInfo4 struct
4601  ********************************************************************/
4602
4603 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4604                                         struct spoolss_DriverInfo4 *r,
4605                                         const struct spoolss_DriverInfo8 *driver,
4606                                         const char *servername)
4607 {
4608         const char *cservername = canon_servername(servername);
4609
4610         r->version              = driver->version;
4611
4612         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4613         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4614         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4615         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4616
4617         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4618                                driver->driver_path,
4619                                r->driver_path);
4620
4621         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4622                                driver->data_file,
4623                                r->data_file);
4624
4625         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4626                                driver->config_file,
4627                                r->config_file);
4628
4629         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4630                                driver->help_file,
4631                                r->help_file);
4632
4633         r->dependent_files = string_array_from_driver_info(mem_ctx,
4634                                                            driver->dependent_files,
4635                                                            cservername);
4636
4637         FILL_DRIVER_STRING(mem_ctx,
4638                            driver->monitor_name,
4639                            r->monitor_name);
4640
4641         FILL_DRIVER_STRING(mem_ctx,
4642                            driver->default_datatype,
4643                            r->default_datatype);
4644
4645         r->previous_names = string_array_from_driver_info(mem_ctx,
4646                                                           driver->previous_names,
4647                                                           cservername);
4648
4649         return WERR_OK;
4650 }
4651
4652 /********************************************************************
4653  * fill a spoolss_DriverInfo5 struct
4654  ********************************************************************/
4655
4656 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4657                                         struct spoolss_DriverInfo5 *r,
4658                                         const struct spoolss_DriverInfo8 *driver,
4659                                         const char *servername)
4660 {
4661         const char *cservername = canon_servername(servername);
4662
4663         r->version              = driver->version;
4664
4665         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4666         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4667         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4668         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4669
4670         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4671                                driver->driver_path,
4672                                r->driver_path);
4673
4674         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4675                                driver->data_file,
4676                                r->data_file);
4677
4678         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4679                                driver->config_file,
4680                                r->config_file);
4681
4682         r->driver_attributes    = 0;
4683         r->config_version       = 0;
4684         r->driver_version       = 0;
4685
4686         return WERR_OK;
4687 }
4688 /********************************************************************
4689  * fill a spoolss_DriverInfo6 struct
4690  ********************************************************************/
4691
4692 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4693                                         struct spoolss_DriverInfo6 *r,
4694                                         const struct spoolss_DriverInfo8 *driver,
4695                                         const char *servername)
4696 {
4697         const char *cservername = canon_servername(servername);
4698
4699         r->version              = driver->version;
4700
4701         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4702         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4703         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4704         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4705
4706         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4707                                driver->driver_path,
4708                                r->driver_path);
4709
4710         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4711                                driver->data_file,
4712                                r->data_file);
4713
4714         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4715                                driver->config_file,
4716                                r->config_file);
4717
4718         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4719                                driver->help_file,
4720                                r->help_file);
4721
4722         FILL_DRIVER_STRING(mem_ctx,
4723                            driver->monitor_name,
4724                            r->monitor_name);
4725
4726         FILL_DRIVER_STRING(mem_ctx,
4727                            driver->default_datatype,
4728                            r->default_datatype);
4729
4730         r->dependent_files = string_array_from_driver_info(mem_ctx,
4731                                                            driver->dependent_files,
4732                                                            cservername);
4733         r->previous_names = string_array_from_driver_info(mem_ctx,
4734                                                           driver->previous_names,
4735                                                           cservername);
4736
4737         r->driver_date          = driver->driver_date;
4738         r->driver_version       = driver->driver_version;
4739
4740         FILL_DRIVER_STRING(mem_ctx,
4741                            driver->manufacturer_name,
4742                            r->manufacturer_name);
4743         FILL_DRIVER_STRING(mem_ctx,
4744                            driver->manufacturer_url,
4745                            r->manufacturer_url);
4746         FILL_DRIVER_STRING(mem_ctx,
4747                            driver->hardware_id,
4748                            r->hardware_id);
4749         FILL_DRIVER_STRING(mem_ctx,
4750                            driver->provider,
4751                            r->provider);
4752
4753         return WERR_OK;
4754 }
4755
4756 /********************************************************************
4757  * fill a spoolss_DriverInfo8 struct
4758  ********************************************************************/
4759
4760 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4761                                         struct spoolss_DriverInfo8 *r,
4762                                         const struct spoolss_DriverInfo8 *driver,
4763                                         const char *servername)
4764 {
4765         const char *cservername = canon_servername(servername);
4766
4767         r->version              = driver->version;
4768
4769         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4770         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4771         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4772         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4773
4774         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4775                                driver->driver_path,
4776                                r->driver_path);
4777
4778         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4779                                driver->data_file,
4780                                r->data_file);
4781
4782         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4783                                driver->config_file,
4784                                r->config_file);
4785
4786         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4787                                driver->help_file,
4788                                r->help_file);
4789
4790         FILL_DRIVER_STRING(mem_ctx,
4791                            driver->monitor_name,
4792                            r->monitor_name);
4793
4794         FILL_DRIVER_STRING(mem_ctx,
4795                            driver->default_datatype,
4796                            r->default_datatype);
4797
4798         r->dependent_files = string_array_from_driver_info(mem_ctx,
4799                                                            driver->dependent_files,
4800                                                            cservername);
4801         r->previous_names = string_array_from_driver_info(mem_ctx,
4802                                                           driver->previous_names,
4803                                                           cservername);
4804
4805         r->driver_date          = driver->driver_date;
4806         r->driver_version       = driver->driver_version;
4807
4808         FILL_DRIVER_STRING(mem_ctx,
4809                            driver->manufacturer_name,
4810                            r->manufacturer_name);
4811         FILL_DRIVER_STRING(mem_ctx,
4812                            driver->manufacturer_url,
4813                            r->manufacturer_url);
4814         FILL_DRIVER_STRING(mem_ctx,
4815                            driver->hardware_id,
4816                            r->hardware_id);
4817         FILL_DRIVER_STRING(mem_ctx,
4818                            driver->provider,
4819                            r->provider);
4820
4821         FILL_DRIVER_STRING(mem_ctx,
4822                            driver->print_processor,
4823                            r->print_processor);
4824         FILL_DRIVER_STRING(mem_ctx,
4825                            driver->vendor_setup,
4826                            r->vendor_setup);
4827
4828         r->color_profiles = string_array_from_driver_info(mem_ctx,
4829                                                           driver->color_profiles,
4830                                                           cservername);
4831
4832         FILL_DRIVER_STRING(mem_ctx,
4833                            driver->inf_path,
4834                            r->inf_path);
4835
4836         r->printer_driver_attributes    = driver->printer_driver_attributes;
4837
4838         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4839                                                                     driver->core_driver_dependencies,
4840                                                                     cservername);
4841
4842         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4843         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4844
4845         return WERR_OK;
4846 }
4847
4848 #if 0 /* disabled until marshalling issues are resolved - gd */
4849 /********************************************************************
4850  ********************************************************************/
4851
4852 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4853                                           struct spoolss_DriverFileInfo *r,
4854                                           const char *cservername,
4855                                           const char *file_name,
4856                                           enum spoolss_DriverFileType file_type,
4857                                           uint32_t file_version)
4858 {
4859         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4860                                           cservername, file_name);
4861         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4862         r->file_type    = file_type;
4863         r->file_version = file_version;
4864
4865         return WERR_OK;
4866 }
4867
4868 /********************************************************************
4869  ********************************************************************/
4870
4871 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4872                                                  const struct spoolss_DriverInfo8 *driver,
4873                                                  const char *cservername,
4874                                                  struct spoolss_DriverFileInfo **info_p,
4875                                                  uint32_t *count_p)
4876 {
4877         struct spoolss_DriverFileInfo *info = NULL;
4878         uint32_t count = 0;
4879         WERROR result;
4880         uint32_t i;
4881
4882         *info_p = NULL;
4883         *count_p = 0;
4884
4885         if (strlen(driver->driver_path)) {
4886                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4887                                             struct spoolss_DriverFileInfo,
4888                                             count + 1);
4889                 W_ERROR_HAVE_NO_MEMORY(info);
4890                 result = fill_spoolss_DriverFileInfo(info,
4891                                                      &info[count],
4892                                                      cservername,
4893                                                      driver->driver_path,
4894                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4895                                                      0);
4896                 W_ERROR_NOT_OK_RETURN(result);
4897                 count++;
4898         }
4899
4900         if (strlen(driver->config_file)) {
4901                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4902                                             struct spoolss_DriverFileInfo,
4903                                             count + 1);
4904                 W_ERROR_HAVE_NO_MEMORY(info);
4905                 result = fill_spoolss_DriverFileInfo(info,
4906                                                      &info[count],
4907                                                      cservername,
4908                                                      driver->config_file,
4909                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4910                                                      0);
4911                 W_ERROR_NOT_OK_RETURN(result);
4912                 count++;
4913         }
4914
4915         if (strlen(driver->data_file)) {
4916                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4917                                             struct spoolss_DriverFileInfo,
4918                                             count + 1);
4919                 W_ERROR_HAVE_NO_MEMORY(info);
4920                 result = fill_spoolss_DriverFileInfo(info,
4921                                                      &info[count],
4922                                                      cservername,
4923                                                      driver->data_file,
4924                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4925                                                      0);
4926                 W_ERROR_NOT_OK_RETURN(result);
4927                 count++;
4928         }
4929
4930         if (strlen(driver->help_file)) {
4931                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4932                                             struct spoolss_DriverFileInfo,
4933                                             count + 1);
4934                 W_ERROR_HAVE_NO_MEMORY(info);
4935                 result = fill_spoolss_DriverFileInfo(info,
4936                                                      &info[count],
4937                                                      cservername,
4938                                                      driver->help_file,
4939                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4940                                                      0);
4941                 W_ERROR_NOT_OK_RETURN(result);
4942                 count++;
4943         }
4944
4945         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4946                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4947                                             struct spoolss_DriverFileInfo,
4948                                             count + 1);
4949                 W_ERROR_HAVE_NO_MEMORY(info);
4950                 result = fill_spoolss_DriverFileInfo(info,
4951                                                      &info[count],
4952                                                      cservername,
4953                                                      driver->dependent_files[i],
4954                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4955                                                      0);
4956                 W_ERROR_NOT_OK_RETURN(result);
4957                 count++;
4958         }
4959
4960         *info_p = info;
4961         *count_p = count;
4962
4963         return WERR_OK;
4964 }
4965
4966 /********************************************************************
4967  * fill a spoolss_DriverInfo101 struct
4968  ********************************************************************/
4969
4970 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4971                                           struct spoolss_DriverInfo101 *r,
4972                                           const struct spoolss_DriverInfo8 *driver,
4973                                           const char *servername)
4974 {
4975         const char *cservername = canon_servername(servername);
4976         WERROR result;
4977
4978         r->version              = driver->version;
4979
4980         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4981         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4982         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4983         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4984
4985         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4986                                                     cservername,
4987                                                     &r->file_info,
4988                                                     &r->file_count);
4989         if (!W_ERROR_IS_OK(result)) {
4990                 return result;
4991         }
4992
4993         FILL_DRIVER_STRING(mem_ctx,
4994                            driver->monitor_name,
4995                            r->monitor_name);
4996
4997         FILL_DRIVER_STRING(mem_ctx,
4998                            driver->default_datatype,
4999                            r->default_datatype);
5000
5001         r->previous_names = string_array_from_driver_info(mem_ctx,
5002                                                           driver->previous_names,
5003                                                           cservername);
5004         r->driver_date          = driver->driver_date;
5005         r->driver_version       = driver->driver_version;
5006
5007         FILL_DRIVER_STRING(mem_ctx,
5008                            driver->manufacturer_name,
5009                            r->manufacturer_name);
5010         FILL_DRIVER_STRING(mem_ctx,
5011                            driver->manufacturer_url,
5012                            r->manufacturer_url);
5013         FILL_DRIVER_STRING(mem_ctx,
5014                            driver->hardware_id,
5015                            r->hardware_id);
5016         FILL_DRIVER_STRING(mem_ctx,
5017                            driver->provider,
5018                            r->provider);
5019
5020         return WERR_OK;
5021 }
5022 #endif
5023 /********************************************************************
5024  ********************************************************************/
5025
5026 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5027                                                   uint32_t level,
5028                                                   union spoolss_DriverInfo *r,
5029                                                   int snum,
5030                                                   const char *servername,
5031                                                   const char *architecture,
5032                                                   uint32_t version)
5033 {
5034         NT_PRINTER_INFO_LEVEL *printer = NULL;
5035         struct spoolss_DriverInfo8 *driver;
5036         WERROR result;
5037
5038         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5039
5040         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5041                 win_errstr(result)));
5042
5043         if (!W_ERROR_IS_OK(result)) {
5044                 return WERR_INVALID_PRINTER_NAME;
5045         }
5046
5047         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5048                                       architecture, version);
5049
5050         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5051                 win_errstr(result)));
5052
5053         if (!W_ERROR_IS_OK(result)) {
5054                 /*
5055                  * Is this a W2k client ?
5056                  */
5057
5058                 if (version < 3) {
5059                         free_a_printer(&printer, 2);
5060                         return WERR_UNKNOWN_PRINTER_DRIVER;
5061                 }
5062
5063                 /* Yes - try again with a WinNT driver. */
5064                 version = 2;
5065                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5066                                               architecture, version);
5067                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5068                         win_errstr(result)));
5069                 if (!W_ERROR_IS_OK(result)) {
5070                         free_a_printer(&printer, 2);
5071                         return WERR_UNKNOWN_PRINTER_DRIVER;
5072                 }
5073         }
5074
5075         switch (level) {
5076         case 1:
5077                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5078                 break;
5079         case 2:
5080                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5081                 break;
5082         case 3:
5083                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5084                 break;
5085         case 4:
5086                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5087                 break;
5088         case 5:
5089                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5090                 break;
5091         case 6:
5092                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5093                 break;
5094         case 8:
5095                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5096                 break;
5097 #if 0 /* disabled until marshalling issues are resolved - gd */
5098         case 101:
5099                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5100                 break;
5101 #endif
5102         default:
5103                 result = WERR_UNKNOWN_LEVEL;
5104                 break;
5105         }
5106
5107         free_a_printer(&printer, 2);
5108         free_a_printer_driver(driver);
5109
5110         return result;
5111 }
5112
5113 /****************************************************************
5114  _spoolss_GetPrinterDriver2
5115 ****************************************************************/
5116
5117 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5118                                   struct spoolss_GetPrinterDriver2 *r)
5119 {
5120         Printer_entry *printer;
5121         WERROR result;
5122
5123         const char *servername;
5124         int snum;
5125
5126         /* that's an [in out] buffer */
5127
5128         if (!r->in.buffer && (r->in.offered != 0)) {
5129                 return WERR_INVALID_PARAM;
5130         }
5131
5132         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5133
5134         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5135                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5136                 return WERR_INVALID_PRINTER_NAME;
5137         }
5138
5139         *r->out.needed = 0;
5140         *r->out.server_major_version = 0;
5141         *r->out.server_minor_version = 0;
5142
5143         servername = get_server_name(printer);
5144
5145         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5146                 return WERR_BADFID;
5147         }
5148
5149         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5150                                                      r->out.info, snum,
5151                                                      servername,
5152                                                      r->in.architecture,
5153                                                      r->in.client_major_version);
5154         if (!W_ERROR_IS_OK(result)) {
5155                 TALLOC_FREE(r->out.info);
5156                 return result;
5157         }
5158
5159         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5160                                                r->out.info, r->in.level);
5161         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5162
5163         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5164 }
5165
5166
5167 /****************************************************************
5168  _spoolss_StartPagePrinter
5169 ****************************************************************/
5170
5171 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5172                                  struct spoolss_StartPagePrinter *r)
5173 {
5174         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5175
5176         if (!Printer) {
5177                 DEBUG(3,("_spoolss_StartPagePrinter: "
5178                         "Error in startpageprinter printer handle\n"));
5179                 return WERR_BADFID;
5180         }
5181
5182         Printer->page_started = true;
5183         return WERR_OK;
5184 }
5185
5186 /****************************************************************
5187  _spoolss_EndPagePrinter
5188 ****************************************************************/
5189
5190 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5191                                struct spoolss_EndPagePrinter *r)
5192 {
5193         int snum;
5194
5195         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5196
5197         if (!Printer) {
5198                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5199                         OUR_HANDLE(r->in.handle)));
5200                 return WERR_BADFID;
5201         }
5202
5203         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5204                 return WERR_BADFID;
5205
5206         Printer->page_started = false;
5207         print_job_endpage(snum, Printer->jobid);
5208
5209         return WERR_OK;
5210 }
5211
5212 /****************************************************************
5213  _spoolss_StartDocPrinter
5214 ****************************************************************/
5215
5216 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5217                                 struct spoolss_StartDocPrinter *r)
5218 {
5219         struct spoolss_DocumentInfo1 *info_1;
5220         int snum;
5221         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5222
5223         if (!Printer) {
5224                 DEBUG(2,("_spoolss_StartDocPrinter: "
5225                         "Invalid handle (%s:%u:%u)\n",
5226                         OUR_HANDLE(r->in.handle)));
5227                 return WERR_BADFID;
5228         }
5229
5230         if (r->in.level != 1) {
5231                 return WERR_UNKNOWN_LEVEL;
5232         }
5233
5234         info_1 = r->in.info.info1;
5235
5236         /*
5237          * a nice thing with NT is it doesn't listen to what you tell it.
5238          * when asked to send _only_ RAW datas, it tries to send datas
5239          * in EMF format.
5240          *
5241          * So I add checks like in NT Server ...
5242          */
5243
5244         if (info_1->datatype) {
5245                 if (strcmp(info_1->datatype, "RAW") != 0) {
5246                         *r->out.job_id = 0;
5247                         return WERR_INVALID_DATATYPE;
5248                 }
5249         }
5250
5251         /* get the share number of the printer */
5252         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5253                 return WERR_BADFID;
5254         }
5255
5256         Printer->jobid = print_job_start(p->server_info, snum,
5257                                          info_1->document_name,
5258                                          Printer->nt_devmode);
5259
5260         /* An error occured in print_job_start() so return an appropriate
5261            NT error code. */
5262
5263         if (Printer->jobid == -1) {
5264                 return map_werror_from_unix(errno);
5265         }
5266
5267         Printer->document_started = true;
5268         *r->out.job_id = Printer->jobid;
5269
5270         return WERR_OK;
5271 }
5272
5273 /****************************************************************
5274  _spoolss_EndDocPrinter
5275 ****************************************************************/
5276
5277 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5278                               struct spoolss_EndDocPrinter *r)
5279 {
5280         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5281         int snum;
5282
5283         if (!Printer) {
5284                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5285                         OUR_HANDLE(r->in.handle)));
5286                 return WERR_BADFID;
5287         }
5288
5289         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5290                 return WERR_BADFID;
5291         }
5292
5293         Printer->document_started = false;
5294         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5295         /* error codes unhandled so far ... */
5296
5297         return WERR_OK;
5298 }
5299
5300 /****************************************************************
5301  _spoolss_WritePrinter
5302 ****************************************************************/
5303
5304 WERROR _spoolss_WritePrinter(pipes_struct *p,
5305                              struct spoolss_WritePrinter *r)
5306 {
5307         uint32_t buffer_written;
5308         int snum;
5309         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5310
5311         if (!Printer) {
5312                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5313                         OUR_HANDLE(r->in.handle)));
5314                 *r->out.num_written = r->in._data_size;
5315                 return WERR_BADFID;
5316         }
5317
5318         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5319                 return WERR_BADFID;
5320
5321         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5322                                                    (const char *)r->in.data.data,
5323                                                    (SMB_OFF_T)-1,
5324                                                    (size_t)r->in._data_size);
5325         if (buffer_written == (uint32_t)-1) {
5326                 *r->out.num_written = 0;
5327                 if (errno == ENOSPC)
5328                         return WERR_NO_SPOOL_SPACE;
5329                 else
5330                         return WERR_ACCESS_DENIED;
5331         }
5332
5333         *r->out.num_written = r->in._data_size;
5334
5335         return WERR_OK;
5336 }
5337
5338 /********************************************************************
5339  * api_spoolss_getprinter
5340  * called from the spoolss dispatcher
5341  *
5342  ********************************************************************/
5343
5344 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5345                               pipes_struct *p)
5346 {
5347         int snum;
5348         WERROR errcode = WERR_BADFUNC;
5349         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5350
5351         if (!Printer) {
5352                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5353                         OUR_HANDLE(handle)));
5354                 return WERR_BADFID;
5355         }
5356
5357         if (!get_printer_snum(p, handle, &snum, NULL))
5358                 return WERR_BADFID;
5359
5360         switch (command) {
5361         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5362                 errcode = print_queue_pause(p->server_info, snum);
5363                 break;
5364         case SPOOLSS_PRINTER_CONTROL_RESUME:
5365         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5366                 errcode = print_queue_resume(p->server_info, snum);
5367                 break;
5368         case SPOOLSS_PRINTER_CONTROL_PURGE:
5369                 errcode = print_queue_purge(p->server_info, snum);
5370                 break;
5371         default:
5372                 return WERR_UNKNOWN_LEVEL;
5373         }
5374
5375         return errcode;
5376 }
5377
5378
5379 /****************************************************************
5380  _spoolss_AbortPrinter
5381  * From MSDN: "Deletes printer's spool file if printer is configured
5382  * for spooling"
5383 ****************************************************************/
5384
5385 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5386                              struct spoolss_AbortPrinter *r)
5387 {
5388         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5389         int             snum;
5390         WERROR          errcode = WERR_OK;
5391
5392         if (!Printer) {
5393                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5394                         OUR_HANDLE(r->in.handle)));
5395                 return WERR_BADFID;
5396         }
5397
5398         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5399                 return WERR_BADFID;
5400
5401         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5402
5403         return errcode;
5404 }
5405
5406 /********************************************************************
5407  * called by spoolss_api_setprinter
5408  * when updating a printer description
5409  ********************************************************************/
5410
5411 static WERROR update_printer_sec(struct policy_handle *handle,
5412                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5413 {
5414         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5415         WERROR result;
5416         int snum;
5417
5418         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5419
5420         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5421                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5422                          OUR_HANDLE(handle)));
5423
5424                 result = WERR_BADFID;
5425                 goto done;
5426         }
5427
5428         if (!secdesc_ctr) {
5429                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5430                 result = WERR_INVALID_PARAM;
5431                 goto done;
5432         }
5433
5434         /* Check the user has permissions to change the security
5435            descriptor.  By experimentation with two NT machines, the user
5436            requires Full Access to the printer to change security
5437            information. */
5438
5439         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5440                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5441                 result = WERR_ACCESS_DENIED;
5442                 goto done;
5443         }
5444
5445         /* NT seems to like setting the security descriptor even though
5446            nothing may have actually changed. */
5447
5448         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5449                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5450                 result = WERR_BADFID;
5451                 goto done;
5452         }
5453
5454         if (DEBUGLEVEL >= 10) {
5455                 SEC_ACL *the_acl;
5456                 int i;
5457
5458                 the_acl = old_secdesc_ctr->sd->dacl;
5459                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5460                            PRINTERNAME(snum), the_acl->num_aces));
5461
5462                 for (i = 0; i < the_acl->num_aces; i++) {
5463                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5464                                            &the_acl->aces[i].trustee),
5465                                   the_acl->aces[i].access_mask));
5466                 }
5467
5468                 the_acl = secdesc_ctr->sd->dacl;
5469
5470                 if (the_acl) {
5471                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5472                                    PRINTERNAME(snum), the_acl->num_aces));
5473
5474                         for (i = 0; i < the_acl->num_aces; i++) {
5475                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5476                                                    &the_acl->aces[i].trustee),
5477                                            the_acl->aces[i].access_mask));
5478                         }
5479                 } else {
5480                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5481                 }
5482         }
5483
5484         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5485         if (!new_secdesc_ctr) {
5486                 result = WERR_NOMEM;
5487                 goto done;
5488         }
5489
5490         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5491                 result = WERR_OK;
5492                 goto done;
5493         }
5494
5495         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5496
5497  done:
5498
5499         return result;
5500 }
5501
5502 /********************************************************************
5503  Canonicalize printer info from a client
5504
5505  ATTN: It does not matter what we set the servername to hear
5506  since we do the necessary work in get_a_printer() to set it to
5507  the correct value based on what the client sent in the
5508  _spoolss_open_printer_ex().
5509  ********************************************************************/
5510
5511 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5512 {
5513         fstring printername;
5514         const char *p;
5515
5516         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5517                 "portname=%s drivername=%s comment=%s location=%s\n",
5518                 info->servername, info->printername, info->sharename,
5519                 info->portname, info->drivername, info->comment, info->location));
5520
5521         /* we force some elements to "correct" values */
5522         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5523         fstrcpy(info->sharename, lp_servicename(snum));
5524
5525         /* check to see if we allow printername != sharename */
5526
5527         if ( lp_force_printername(snum) ) {
5528                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5529                         global_myname(), info->sharename );
5530         } else {
5531
5532                 /* make sure printername is in \\server\printername format */
5533
5534                 fstrcpy( printername, info->printername );
5535                 p = printername;
5536                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5537                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5538                                 p++;
5539                 }
5540
5541                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5542                          global_myname(), p );
5543         }
5544
5545         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5546         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5547
5548
5549
5550         return true;
5551 }
5552
5553 /****************************************************************************
5554 ****************************************************************************/
5555
5556 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5557 {
5558         char *cmd = lp_addport_cmd();
5559         char *command = NULL;
5560         int ret;
5561         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5562         bool is_print_op = false;
5563
5564         if ( !*cmd ) {
5565                 return WERR_ACCESS_DENIED;
5566         }
5567
5568         command = talloc_asprintf(ctx,
5569                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5570         if (!command) {
5571                 return WERR_NOMEM;
5572         }
5573
5574         if ( token )
5575                 is_print_op = user_has_privileges( token, &se_printop );
5576
5577         DEBUG(10,("Running [%s]\n", command));
5578
5579         /********* BEGIN SePrintOperatorPrivilege **********/
5580
5581         if ( is_print_op )
5582                 become_root();
5583
5584         ret = smbrun(command, NULL);
5585
5586         if ( is_print_op )
5587                 unbecome_root();
5588
5589         /********* END SePrintOperatorPrivilege **********/
5590
5591         DEBUGADD(10,("returned [%d]\n", ret));
5592
5593         TALLOC_FREE(command);
5594
5595         if ( ret != 0 ) {
5596                 return WERR_ACCESS_DENIED;
5597         }
5598
5599         return WERR_OK;
5600 }
5601
5602 /****************************************************************************
5603 ****************************************************************************/
5604
5605 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5606 {
5607         char *cmd = lp_addprinter_cmd();
5608         char **qlines;
5609         char *command = NULL;
5610         int numlines;
5611         int ret;
5612         int fd;
5613         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5614         bool is_print_op = false;
5615         char *remote_machine = talloc_strdup(ctx, "%m");
5616
5617         if (!remote_machine) {
5618                 return false;
5619         }
5620         remote_machine = talloc_sub_basic(ctx,
5621                                 current_user_info.smb_name,
5622                                 current_user_info.domain,
5623                                 remote_machine);
5624         if (!remote_machine) {
5625                 return false;
5626         }
5627
5628         command = talloc_asprintf(ctx,
5629                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5630                         cmd, printer->info_2->printername, printer->info_2->sharename,
5631                         printer->info_2->portname, printer->info_2->drivername,
5632                         printer->info_2->location, printer->info_2->comment, remote_machine);
5633         if (!command) {
5634                 return false;
5635         }
5636
5637         if ( token )
5638                 is_print_op = user_has_privileges( token, &se_printop );
5639
5640         DEBUG(10,("Running [%s]\n", command));
5641
5642         /********* BEGIN SePrintOperatorPrivilege **********/
5643
5644         if ( is_print_op )
5645                 become_root();
5646
5647         if ( (ret = smbrun(command, &fd)) == 0 ) {
5648                 /* Tell everyone we updated smb.conf. */
5649                 message_send_all(smbd_messaging_context(),
5650                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5651         }
5652
5653         if ( is_print_op )
5654                 unbecome_root();
5655
5656         /********* END SePrintOperatorPrivilege **********/
5657
5658         DEBUGADD(10,("returned [%d]\n", ret));
5659
5660         TALLOC_FREE(command);
5661         TALLOC_FREE(remote_machine);
5662
5663         if ( ret != 0 ) {
5664                 if (fd != -1)
5665                         close(fd);
5666                 return false;
5667         }
5668
5669         /* reload our services immediately */
5670         become_root();
5671         reload_services(false);
5672         unbecome_root();
5673
5674         numlines = 0;
5675         /* Get lines and convert them back to dos-codepage */
5676         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5677         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5678         close(fd);
5679
5680         /* Set the portname to what the script says the portname should be. */
5681         /* but don't require anything to be return from the script exit a good error code */
5682
5683         if (numlines) {
5684                 /* Set the portname to what the script says the portname should be. */
5685                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5686                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5687         }
5688
5689         TALLOC_FREE(qlines);
5690         return true;
5691 }
5692
5693
5694 /********************************************************************
5695  * Called by spoolss_api_setprinter
5696  * when updating a printer description.
5697  ********************************************************************/
5698
5699 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5700                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5701                              struct spoolss_DeviceMode *devmode)
5702 {
5703         int snum;
5704         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5705         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5706         WERROR result;
5707         DATA_BLOB buffer;
5708         fstring asc_buffer;
5709
5710         DEBUG(8,("update_printer\n"));
5711
5712         result = WERR_OK;
5713
5714         if (!Printer) {
5715                 result = WERR_BADFID;
5716                 goto done;
5717         }
5718
5719         if (!get_printer_snum(p, handle, &snum, NULL)) {
5720                 result = WERR_BADFID;
5721                 goto done;
5722         }
5723
5724         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5725             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5726                 result = WERR_BADFID;
5727                 goto done;
5728         }
5729
5730         DEBUGADD(8,("Converting info_2 struct\n"));
5731
5732         /*
5733          * convert_printer_info converts the incoming
5734          * info from the client and overwrites the info
5735          * just read from the tdb in the pointer 'printer'.
5736          */
5737
5738         if (!convert_printer_info(info_ctr, printer)) {
5739                 result =  WERR_NOMEM;
5740                 goto done;
5741         }
5742
5743         if (devmode) {
5744                 /* we have a valid devmode
5745                    convert it and link it*/
5746
5747                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5748                 if (!convert_devicemode(printer->info_2->printername, devmode,
5749                                         &printer->info_2->devmode)) {
5750                         result =  WERR_NOMEM;
5751                         goto done;
5752                 }
5753         }
5754
5755         /* Do sanity check on the requested changes for Samba */
5756
5757         if (!check_printer_ok(printer->info_2, snum)) {
5758                 result = WERR_INVALID_PARAM;
5759                 goto done;
5760         }
5761
5762         /* FIXME!!! If the driver has changed we really should verify that
5763            it is installed before doing much else   --jerry */
5764
5765         /* Check calling user has permission to update printer description */
5766
5767         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5768                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5769                 result = WERR_ACCESS_DENIED;
5770                 goto done;
5771         }
5772
5773         /* Call addprinter hook */
5774         /* Check changes to see if this is really needed */
5775
5776         if ( *lp_addprinter_cmd()
5777                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5778                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5779                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5780                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5781         {
5782                 /* add_printer_hook() will call reload_services() */
5783
5784                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5785                                        printer) ) {
5786                         result = WERR_ACCESS_DENIED;
5787                         goto done;
5788                 }
5789         }
5790
5791         /*
5792          * When a *new* driver is bound to a printer, the drivername is used to
5793          * lookup previously saved driver initialization info, which is then
5794          * bound to the printer, simulating what happens in the Windows arch.
5795          */
5796         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5797         {
5798                 if (!set_driver_init(printer, 2))
5799                 {
5800                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5801                                 printer->info_2->drivername));
5802                 }
5803
5804                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5805                         printer->info_2->drivername));
5806
5807                 notify_printer_driver(snum, printer->info_2->drivername);
5808         }
5809
5810         /*
5811          * flag which changes actually occured.  This is a small subset of
5812          * all the possible changes.  We also have to update things in the
5813          * DsSpooler key.
5814          */
5815
5816         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5817                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5818                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5819                         REG_SZ, buffer.data, buffer.length);
5820
5821                 notify_printer_comment(snum, printer->info_2->comment);
5822         }
5823
5824         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5825                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5826                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5827                         REG_SZ, buffer.data, buffer.length);
5828
5829                 notify_printer_sharename(snum, printer->info_2->sharename);
5830         }
5831
5832         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5833                 char *pname;
5834
5835                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5836                         pname++;
5837                 else
5838                         pname = printer->info_2->printername;
5839
5840
5841                 push_reg_sz(talloc_tos(), &buffer, pname);
5842                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5843                         REG_SZ, buffer.data, buffer.length);
5844
5845                 notify_printer_printername( snum, pname );
5846         }
5847
5848         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5849                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5850                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5851                         REG_SZ, buffer.data, buffer.length);
5852
5853                 notify_printer_port(snum, printer->info_2->portname);
5854         }
5855
5856         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5857                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5858                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5859                         REG_SZ, buffer.data, buffer.length);
5860
5861                 notify_printer_location(snum, printer->info_2->location);
5862         }
5863
5864         /* here we need to update some more DsSpooler keys */
5865         /* uNCName, serverName, shortServerName */
5866
5867         push_reg_sz(talloc_tos(), &buffer, global_myname());
5868         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5869                 REG_SZ, buffer.data, buffer.length);
5870         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5871                 REG_SZ, buffer.data, buffer.length);
5872
5873         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5874                  global_myname(), printer->info_2->sharename );
5875         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5876         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5877                 REG_SZ, buffer.data, buffer.length);
5878
5879         /* Update printer info */
5880         result = mod_a_printer(printer, 2);
5881
5882 done:
5883         free_a_printer(&printer, 2);
5884         free_a_printer(&old_printer, 2);
5885
5886
5887         return result;
5888 }
5889
5890 /****************************************************************************
5891 ****************************************************************************/
5892 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5893                                            struct policy_handle *handle,
5894                                            struct spoolss_SetPrinterInfo7 *info7)
5895 {
5896 #ifdef HAVE_ADS
5897         int snum;
5898         Printer_entry *Printer;
5899
5900         if ( lp_security() != SEC_ADS ) {
5901                 return WERR_UNKNOWN_LEVEL;
5902         }
5903
5904         Printer = find_printer_index_by_hnd(p, handle);
5905
5906         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5907
5908         if (!Printer)
5909                 return WERR_BADFID;
5910
5911         if (!get_printer_snum(p, handle, &snum, NULL))
5912                 return WERR_BADFID;
5913
5914         nt_printer_publish(Printer, snum, info7->action);
5915
5916         return WERR_OK;
5917 #else
5918         return WERR_UNKNOWN_LEVEL;
5919 #endif
5920 }
5921
5922 /****************************************************************
5923  _spoolss_SetPrinter
5924 ****************************************************************/
5925
5926 WERROR _spoolss_SetPrinter(pipes_struct *p,
5927                            struct spoolss_SetPrinter *r)
5928 {
5929         WERROR result;
5930
5931         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5932
5933         if (!Printer) {
5934                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5935                         OUR_HANDLE(r->in.handle)));
5936                 return WERR_BADFID;
5937         }
5938
5939         /* check the level */
5940         switch (r->in.info_ctr->level) {
5941                 case 0:
5942                         return control_printer(r->in.handle, r->in.command, p);
5943                 case 2:
5944                         result = update_printer(p, r->in.handle,
5945                                                 r->in.info_ctr,
5946                                                 r->in.devmode_ctr->devmode);
5947                         if (!W_ERROR_IS_OK(result))
5948                                 return result;
5949                         if (r->in.secdesc_ctr->sd)
5950                                 result = update_printer_sec(r->in.handle, p,
5951                                                             r->in.secdesc_ctr);
5952                         return result;
5953                 case 3:
5954                         return update_printer_sec(r->in.handle, p,
5955                                                   r->in.secdesc_ctr);
5956                 case 7:
5957                         return publish_or_unpublish_printer(p, r->in.handle,
5958                                                             r->in.info_ctr->info.info7);
5959                 default:
5960                         return WERR_UNKNOWN_LEVEL;
5961         }
5962 }
5963
5964 /****************************************************************
5965  _spoolss_FindClosePrinterNotify
5966 ****************************************************************/
5967
5968 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5969                                        struct spoolss_FindClosePrinterNotify *r)
5970 {
5971         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5972
5973         if (!Printer) {
5974                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5975                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5976                 return WERR_BADFID;
5977         }
5978
5979         if (Printer->notify.client_connected == true) {
5980                 int snum = -1;
5981
5982                 if ( Printer->printer_type == SPLHND_SERVER)
5983                         snum = -1;
5984                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5985                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5986                         return WERR_BADFID;
5987
5988                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5989         }
5990
5991         Printer->notify.flags=0;
5992         Printer->notify.options=0;
5993         Printer->notify.localmachine[0]='\0';
5994         Printer->notify.printerlocal=0;
5995         TALLOC_FREE(Printer->notify.option);
5996         Printer->notify.client_connected = false;
5997
5998         return WERR_OK;
5999 }
6000
6001 /****************************************************************
6002  _spoolss_AddJob
6003 ****************************************************************/
6004
6005 WERROR _spoolss_AddJob(pipes_struct *p,
6006                        struct spoolss_AddJob *r)
6007 {
6008         if (!r->in.buffer && (r->in.offered != 0)) {
6009                 return WERR_INVALID_PARAM;
6010         }
6011
6012         /* this is what a NT server returns for AddJob. AddJob must fail on
6013          * non-local printers */
6014
6015         if (r->in.level != 1) {
6016                 return WERR_UNKNOWN_LEVEL;
6017         }
6018
6019         return WERR_INVALID_PARAM;
6020 }
6021
6022 /****************************************************************************
6023 fill_job_info1
6024 ****************************************************************************/
6025
6026 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6027                              struct spoolss_JobInfo1 *r,
6028                              const print_queue_struct *queue,
6029                              int position, int snum,
6030                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6031 {
6032         struct tm *t;
6033
6034         t = gmtime(&queue->time);
6035
6036         r->job_id               = queue->job;
6037
6038         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6039         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6040         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6041         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6042         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6043         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6044         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6045         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6046         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6047         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6048         r->text_status          = talloc_strdup(mem_ctx, "");
6049         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6050
6051         r->status               = nt_printj_status(queue->status);
6052         r->priority             = queue->priority;
6053         r->position             = position;
6054         r->total_pages          = queue->page_count;
6055         r->pages_printed        = 0; /* ??? */
6056
6057         init_systemtime(&r->submitted, t);
6058
6059         return WERR_OK;
6060 }
6061
6062 /****************************************************************************
6063 fill_job_info2
6064 ****************************************************************************/
6065
6066 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6067                              struct spoolss_JobInfo2 *r,
6068                              const print_queue_struct *queue,
6069                              int position, int snum,
6070                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6071                              struct spoolss_DeviceMode *devmode)
6072 {
6073         struct tm *t;
6074
6075         t = gmtime(&queue->time);
6076
6077         r->job_id               = queue->job;
6078
6079         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6080         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6081         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6082         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6083         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6084         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6085         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6086         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6087         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6088         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6089         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6090         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6091         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6092         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6093         r->parameters           = talloc_strdup(mem_ctx, "");
6094         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6095         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6096         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6097
6098         r->devmode              = devmode;
6099
6100         r->text_status          = talloc_strdup(mem_ctx, "");
6101         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6102
6103         r->secdesc              = NULL;
6104
6105         r->status               = nt_printj_status(queue->status);
6106         r->priority             = queue->priority;
6107         r->position             = position;
6108         r->start_time           = 0;
6109         r->until_time           = 0;
6110         r->total_pages          = queue->page_count;
6111         r->size                 = queue->size;
6112         init_systemtime(&r->submitted, t);
6113         r->time                 = 0;
6114         r->pages_printed        = 0; /* ??? */
6115
6116         return WERR_OK;
6117 }
6118
6119 /****************************************************************************
6120 fill_job_info3
6121 ****************************************************************************/
6122
6123 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6124                              struct spoolss_JobInfo3 *r,
6125                              const print_queue_struct *queue,
6126                              const print_queue_struct *next_queue,
6127                              int position, int snum,
6128                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6129 {
6130         r->job_id               = queue->job;
6131         r->next_job_id          = 0;
6132         if (next_queue) {
6133                 r->next_job_id  = next_queue->job;
6134         }
6135         r->reserved             = 0;
6136
6137         return WERR_OK;
6138 }
6139
6140 /****************************************************************************
6141  Enumjobs at level 1.
6142 ****************************************************************************/
6143
6144 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6145                               const print_queue_struct *queue,
6146                               uint32_t num_queues, int snum,
6147                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6148                               union spoolss_JobInfo **info_p,
6149                               uint32_t *count)
6150 {
6151         union spoolss_JobInfo *info;
6152         int i;
6153         WERROR result = WERR_OK;
6154
6155         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6156         W_ERROR_HAVE_NO_MEMORY(info);
6157
6158         *count = num_queues;
6159
6160         for (i=0; i<*count; i++) {
6161                 result = fill_job_info1(info,
6162                                         &info[i].info1,
6163                                         &queue[i],
6164                                         i,
6165                                         snum,
6166                                         ntprinter);
6167                 if (!W_ERROR_IS_OK(result)) {
6168                         goto out;
6169                 }
6170         }
6171
6172  out:
6173         if (!W_ERROR_IS_OK(result)) {
6174                 TALLOC_FREE(info);
6175                 *count = 0;
6176                 return result;
6177         }
6178
6179         *info_p = info;
6180
6181         return WERR_OK;
6182 }
6183
6184 /****************************************************************************
6185  Enumjobs at level 2.
6186 ****************************************************************************/
6187
6188 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6189                               const print_queue_struct *queue,
6190                               uint32_t num_queues, int snum,
6191                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6192                               union spoolss_JobInfo **info_p,
6193                               uint32_t *count)
6194 {
6195         union spoolss_JobInfo *info;
6196         int i;
6197         WERROR result = WERR_OK;
6198
6199         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6200         W_ERROR_HAVE_NO_MEMORY(info);
6201
6202         *count = num_queues;
6203
6204         for (i=0; i<*count; i++) {
6205
6206                 struct spoolss_DeviceMode *devmode;
6207
6208                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6209                 if (!devmode) {
6210                         result = WERR_NOMEM;
6211                         goto out;
6212                 }
6213
6214                 result = fill_job_info2(info,
6215                                         &info[i].info2,
6216                                         &queue[i],
6217                                         i,
6218                                         snum,
6219                                         ntprinter,
6220                                         devmode);
6221                 if (!W_ERROR_IS_OK(result)) {
6222                         goto out;
6223                 }
6224         }
6225
6226  out:
6227         if (!W_ERROR_IS_OK(result)) {
6228                 TALLOC_FREE(info);
6229                 *count = 0;
6230                 return result;
6231         }
6232
6233         *info_p = info;
6234
6235         return WERR_OK;
6236 }
6237
6238 /****************************************************************************
6239  Enumjobs at level 3.
6240 ****************************************************************************/
6241
6242 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6243                               const print_queue_struct *queue,
6244                               uint32_t num_queues, int snum,
6245                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6246                               union spoolss_JobInfo **info_p,
6247                               uint32_t *count)
6248 {
6249         union spoolss_JobInfo *info;
6250         int i;
6251         WERROR result = WERR_OK;
6252
6253         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6254         W_ERROR_HAVE_NO_MEMORY(info);
6255
6256         *count = num_queues;
6257
6258         for (i=0; i<*count; i++) {
6259                 const print_queue_struct *next_queue = NULL;
6260
6261                 if (i+1 < *count) {
6262                         next_queue = &queue[i+1];
6263                 }
6264
6265                 result = fill_job_info3(info,
6266                                         &info[i].info3,
6267                                         &queue[i],
6268                                         next_queue,
6269                                         i,
6270                                         snum,
6271                                         ntprinter);
6272                 if (!W_ERROR_IS_OK(result)) {
6273                         goto out;
6274                 }
6275         }
6276
6277  out:
6278         if (!W_ERROR_IS_OK(result)) {
6279                 TALLOC_FREE(info);
6280                 *count = 0;
6281                 return result;
6282         }
6283
6284         *info_p = info;
6285
6286         return WERR_OK;
6287 }
6288
6289 /****************************************************************
6290  _spoolss_EnumJobs
6291 ****************************************************************/
6292
6293 WERROR _spoolss_EnumJobs(pipes_struct *p,
6294                          struct spoolss_EnumJobs *r)
6295 {
6296         WERROR result;
6297         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6298         int snum;
6299         print_status_struct prt_status;
6300         print_queue_struct *queue = NULL;
6301         uint32_t count;
6302
6303         /* that's an [in out] buffer */
6304
6305         if (!r->in.buffer && (r->in.offered != 0)) {
6306                 return WERR_INVALID_PARAM;
6307         }
6308
6309         DEBUG(4,("_spoolss_EnumJobs\n"));
6310
6311         *r->out.needed = 0;
6312         *r->out.count = 0;
6313         *r->out.info = NULL;
6314
6315         /* lookup the printer snum and tdb entry */
6316
6317         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6318                 return WERR_BADFID;
6319         }
6320
6321         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6322         if (!W_ERROR_IS_OK(result)) {
6323                 return result;
6324         }
6325
6326         count = print_queue_status(snum, &queue, &prt_status);
6327         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6328                 count, prt_status.status, prt_status.message));
6329
6330         if (count == 0) {
6331                 SAFE_FREE(queue);
6332                 free_a_printer(&ntprinter, 2);
6333                 return WERR_OK;
6334         }
6335
6336         switch (r->in.level) {
6337         case 1:
6338                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6339                                          ntprinter, r->out.info, r->out.count);
6340                 break;
6341         case 2:
6342                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6343                                          ntprinter, r->out.info, r->out.count);
6344                 break;
6345         case 3:
6346                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6347                                          ntprinter, r->out.info, r->out.count);
6348                 break;
6349         default:
6350                 result = WERR_UNKNOWN_LEVEL;
6351                 break;
6352         }
6353
6354         SAFE_FREE(queue);
6355         free_a_printer(&ntprinter, 2);
6356
6357         if (!W_ERROR_IS_OK(result)) {
6358                 return result;
6359         }
6360
6361         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6362                                                      spoolss_EnumJobs, NULL,
6363                                                      *r->out.info, r->in.level,
6364                                                      *r->out.count);
6365         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6366         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6367
6368         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6369 }
6370
6371 /****************************************************************
6372  _spoolss_ScheduleJob
6373 ****************************************************************/
6374
6375 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6376                             struct spoolss_ScheduleJob *r)
6377 {
6378         return WERR_OK;
6379 }
6380
6381 /****************************************************************
6382  _spoolss_SetJob
6383 ****************************************************************/
6384
6385 WERROR _spoolss_SetJob(pipes_struct *p,
6386                        struct spoolss_SetJob *r)
6387 {
6388         int snum;
6389         WERROR errcode = WERR_BADFUNC;
6390
6391         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6392                 return WERR_BADFID;
6393         }
6394
6395         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6396                 return WERR_INVALID_PRINTER_NAME;
6397         }
6398
6399         switch (r->in.command) {
6400         case SPOOLSS_JOB_CONTROL_CANCEL:
6401         case SPOOLSS_JOB_CONTROL_DELETE:
6402                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6403                         errcode = WERR_OK;
6404                 }
6405                 break;
6406         case SPOOLSS_JOB_CONTROL_PAUSE:
6407                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6408                         errcode = WERR_OK;
6409                 }
6410                 break;
6411         case SPOOLSS_JOB_CONTROL_RESTART:
6412         case SPOOLSS_JOB_CONTROL_RESUME:
6413                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6414                         errcode = WERR_OK;
6415                 }
6416                 break;
6417         default:
6418                 return WERR_UNKNOWN_LEVEL;
6419         }
6420
6421         return errcode;
6422 }
6423
6424 /****************************************************************************
6425  Enumerates all printer drivers by level and architecture.
6426 ****************************************************************************/
6427
6428 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6429                                                        const char *servername,
6430                                                        const char *architecture,
6431                                                        uint32_t level,
6432                                                        union spoolss_DriverInfo **info_p,
6433                                                        uint32_t *count_p)
6434 {
6435         int i;
6436         int ndrivers;
6437         uint32_t version;
6438         fstring *list = NULL;
6439         struct spoolss_DriverInfo8 *driver;
6440         union spoolss_DriverInfo *info = NULL;
6441         uint32_t count = 0;
6442         WERROR result = WERR_OK;
6443
6444         *count_p = 0;
6445         *info_p = NULL;
6446
6447         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6448                 list = NULL;
6449                 ndrivers = get_ntdrivers(&list, architecture, version);
6450                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6451                         ndrivers, architecture, version));
6452
6453                 if (ndrivers == -1) {
6454                         result = WERR_NOMEM;
6455                         goto out;
6456                 }
6457
6458                 if (ndrivers != 0) {
6459                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6460                                                     union spoolss_DriverInfo,
6461                                                     count + ndrivers);
6462                         if (!info) {
6463                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6464                                         "failed to enlarge driver info buffer!\n"));
6465                                 result = WERR_NOMEM;
6466                                 goto out;
6467                         }
6468                 }
6469
6470                 for (i=0; i<ndrivers; i++) {
6471                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6472                         ZERO_STRUCT(driver);
6473                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6474                                                       architecture, version);
6475                         if (!W_ERROR_IS_OK(result)) {
6476                                 goto out;
6477                         }
6478
6479                         switch (level) {
6480                         case 1:
6481                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6482                                                                    driver, servername);
6483                                 break;
6484                         case 2:
6485                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6486                                                                    driver, servername);
6487                                 break;
6488                         case 3:
6489                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6490                                                                    driver, servername);
6491                                 break;
6492                         case 4:
6493                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6494                                                                    driver, servername);
6495                                 break;
6496                         case 5:
6497                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6498                                                                    driver, servername);
6499                                 break;
6500                         case 6:
6501                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6502                                                                    driver, servername);
6503                                 break;
6504                         case 8:
6505                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6506                                                                    driver, servername);
6507                                 break;
6508                         default:
6509                                 result = WERR_UNKNOWN_LEVEL;
6510                                 break;
6511                         }
6512
6513                         free_a_printer_driver(driver);
6514
6515                         if (!W_ERROR_IS_OK(result)) {
6516                                 goto out;
6517                         }
6518                 }
6519
6520                 count += ndrivers;
6521                 SAFE_FREE(list);
6522         }
6523
6524  out:
6525         SAFE_FREE(list);
6526
6527         if (!W_ERROR_IS_OK(result)) {
6528                 TALLOC_FREE(info);
6529                 return result;
6530         }
6531
6532         *info_p = info;
6533         *count_p = count;
6534
6535         return WERR_OK;
6536 }
6537
6538 /****************************************************************************
6539  Enumerates all printer drivers by level.
6540 ****************************************************************************/
6541
6542 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6543                                        const char *servername,
6544                                        const char *architecture,
6545                                        uint32_t level,
6546                                        union spoolss_DriverInfo **info_p,
6547                                        uint32_t *count_p)
6548 {
6549         uint32_t a,i;
6550         WERROR result = WERR_OK;
6551
6552         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6553
6554                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6555
6556                         union spoolss_DriverInfo *info = NULL;
6557                         uint32_t count = 0;
6558
6559                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6560                                                                           servername,
6561                                                                           archi_table[a].long_archi,
6562                                                                           level,
6563                                                                           &info,
6564                                                                           &count);
6565                         if (!W_ERROR_IS_OK(result)) {
6566                                 continue;
6567                         }
6568
6569                         for (i=0; i < count; i++) {
6570                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6571                                              info[i], info_p, count_p);
6572                         }
6573                 }
6574
6575                 return result;
6576         }
6577
6578         return enumprinterdrivers_level_by_architecture(mem_ctx,
6579                                                         servername,
6580                                                         architecture,
6581                                                         level,
6582                                                         info_p,
6583                                                         count_p);
6584 }
6585
6586 /****************************************************************
6587  _spoolss_EnumPrinterDrivers
6588 ****************************************************************/
6589
6590 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6591                                    struct spoolss_EnumPrinterDrivers *r)
6592 {
6593         const char *cservername;
6594         WERROR result;
6595
6596         /* that's an [in out] buffer */
6597
6598         if (!r->in.buffer && (r->in.offered != 0)) {
6599                 return WERR_INVALID_PARAM;
6600         }
6601
6602         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6603
6604         *r->out.needed = 0;
6605         *r->out.count = 0;
6606         *r->out.info = NULL;
6607
6608         cservername = canon_servername(r->in.server);
6609
6610         if (!is_myname_or_ipaddr(cservername)) {
6611                 return WERR_UNKNOWN_PRINTER_DRIVER;
6612         }
6613
6614         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6615                                           r->in.environment,
6616                                           r->in.level,
6617                                           r->out.info,
6618                                           r->out.count);
6619         if (!W_ERROR_IS_OK(result)) {
6620                 return result;
6621         }
6622
6623         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6624                                                      spoolss_EnumPrinterDrivers, NULL,
6625                                                      *r->out.info, r->in.level,
6626                                                      *r->out.count);
6627         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6628         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6629
6630         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6631 }
6632
6633 /****************************************************************************
6634 ****************************************************************************/
6635
6636 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6637                                struct spoolss_FormInfo1 *r,
6638                                const nt_forms_struct *form)
6639 {
6640         r->form_name    = talloc_strdup(mem_ctx, form->name);
6641         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6642
6643         r->flags        = form->flag;
6644         r->size.width   = form->width;
6645         r->size.height  = form->length;
6646         r->area.left    = form->left;
6647         r->area.top     = form->top;
6648         r->area.right   = form->right;
6649         r->area.bottom  = form->bottom;
6650
6651         return WERR_OK;
6652 }
6653
6654 /****************************************************************
6655  spoolss_enumforms_level1
6656 ****************************************************************/
6657
6658 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6659                                        const nt_forms_struct *builtin_forms,
6660                                        uint32_t num_builtin_forms,
6661                                        const nt_forms_struct *user_forms,
6662                                        uint32_t num_user_forms,
6663                                        union spoolss_FormInfo **info_p,
6664                                        uint32_t *count)
6665 {
6666         union spoolss_FormInfo *info;
6667         WERROR result = WERR_OK;
6668         int i;
6669
6670         *count = num_builtin_forms + num_user_forms;
6671
6672         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6673         W_ERROR_HAVE_NO_MEMORY(info);
6674
6675         /* construct the list of form structures */
6676         for (i=0; i<num_builtin_forms; i++) {
6677                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6678                 result = fill_form_info_1(info, &info[i].info1,
6679                                           &builtin_forms[i]);
6680                 if (!W_ERROR_IS_OK(result)) {
6681                         goto out;
6682                 }
6683         }
6684
6685         for (i=0; i<num_user_forms; i++) {
6686                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6687                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6688                                           &user_forms[i]);
6689                 if (!W_ERROR_IS_OK(result)) {
6690                         goto out;
6691                 }
6692         }
6693
6694  out:
6695         if (!W_ERROR_IS_OK(result)) {
6696                 TALLOC_FREE(info);
6697                 *count = 0;
6698                 return result;
6699         }
6700
6701         *info_p = info;
6702
6703         return WERR_OK;
6704 }
6705
6706 /****************************************************************
6707  _spoolss_EnumForms
6708 ****************************************************************/
6709
6710 WERROR _spoolss_EnumForms(pipes_struct *p,
6711                           struct spoolss_EnumForms *r)
6712 {
6713         WERROR result;
6714         nt_forms_struct *user_forms = NULL;
6715         nt_forms_struct *builtin_forms = NULL;
6716         uint32_t num_user_forms;
6717         uint32_t num_builtin_forms;
6718
6719         *r->out.count = 0;
6720         *r->out.needed = 0;
6721         *r->out.info = NULL;
6722
6723         /* that's an [in out] buffer */
6724
6725         if (!r->in.buffer && (r->in.offered != 0) ) {
6726                 return WERR_INVALID_PARAM;
6727         }
6728
6729         DEBUG(4,("_spoolss_EnumForms\n"));
6730         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6731         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6732
6733         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6734         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6735         num_user_forms = get_ntforms(&user_forms);
6736         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6737
6738         if (num_user_forms + num_builtin_forms == 0) {
6739                 SAFE_FREE(builtin_forms);
6740                 SAFE_FREE(user_forms);
6741                 return WERR_NO_MORE_ITEMS;
6742         }
6743
6744         switch (r->in.level) {
6745         case 1:
6746                 result = spoolss_enumforms_level1(p->mem_ctx,
6747                                                   builtin_forms,
6748                                                   num_builtin_forms,
6749                                                   user_forms,
6750                                                   num_user_forms,
6751                                                   r->out.info,
6752                                                   r->out.count);
6753                 break;
6754         default:
6755                 result = WERR_UNKNOWN_LEVEL;
6756                 break;
6757         }
6758
6759         SAFE_FREE(user_forms);
6760         SAFE_FREE(builtin_forms);
6761
6762         if (!W_ERROR_IS_OK(result)) {
6763                 return result;
6764         }
6765
6766         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6767                                                      spoolss_EnumForms, NULL,
6768                                                      *r->out.info, r->in.level,
6769                                                      *r->out.count);
6770         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6771         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6772
6773         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6774 }
6775
6776 /****************************************************************
6777 ****************************************************************/
6778
6779 static WERROR find_form_byname(const char *name,
6780                                nt_forms_struct *form)
6781 {
6782         nt_forms_struct *list = NULL;
6783         int num_forms = 0, i = 0;
6784
6785         if (get_a_builtin_ntform_by_string(name, form)) {
6786                 return WERR_OK;
6787         }
6788
6789         num_forms = get_ntforms(&list);
6790         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6791
6792         if (num_forms == 0) {
6793                 return WERR_BADFID;
6794         }
6795
6796         /* Check if the requested name is in the list of form structures */
6797         for (i = 0; i < num_forms; i++) {
6798
6799                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6800
6801                 if (strequal(name, list[i].name)) {
6802                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6803                         *form = list[i];
6804                         SAFE_FREE(list);
6805                         return WERR_OK;
6806                 }
6807         }
6808
6809         SAFE_FREE(list);
6810
6811         return WERR_BADFID;
6812 }
6813
6814 /****************************************************************
6815  _spoolss_GetForm
6816 ****************************************************************/
6817
6818 WERROR _spoolss_GetForm(pipes_struct *p,
6819                         struct spoolss_GetForm *r)
6820 {
6821         WERROR result;
6822         nt_forms_struct form;
6823
6824         /* that's an [in out] buffer */
6825
6826         if (!r->in.buffer && (r->in.offered != 0)) {
6827                 return WERR_INVALID_PARAM;
6828         }
6829
6830         DEBUG(4,("_spoolss_GetForm\n"));
6831         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6832         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6833
6834         result = find_form_byname(r->in.form_name, &form);
6835         if (!W_ERROR_IS_OK(result)) {
6836                 TALLOC_FREE(r->out.info);
6837                 return result;
6838         }
6839
6840         switch (r->in.level) {
6841         case 1:
6842                 result = fill_form_info_1(p->mem_ctx,
6843                                           &r->out.info->info1,
6844                                           &form);
6845                 break;
6846
6847         default:
6848                 result = WERR_UNKNOWN_LEVEL;
6849                 break;
6850         }
6851
6852         if (!W_ERROR_IS_OK(result)) {
6853                 TALLOC_FREE(r->out.info);
6854                 return result;
6855         }
6856
6857         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6858                                                r->out.info, r->in.level);
6859         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6860
6861         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6862 }
6863
6864 /****************************************************************************
6865 ****************************************************************************/
6866
6867 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6868                           struct spoolss_PortInfo1 *r,
6869                           const char *name)
6870 {
6871         r->port_name = talloc_strdup(mem_ctx, name);
6872         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6873
6874         return WERR_OK;
6875 }
6876
6877 /****************************************************************************
6878  TODO: This probably needs distinguish between TCP/IP and Local ports
6879  somehow.
6880 ****************************************************************************/
6881
6882 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6883                           struct spoolss_PortInfo2 *r,
6884                           const char *name)
6885 {
6886         r->port_name = talloc_strdup(mem_ctx, name);
6887         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6888
6889         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6890         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6891
6892         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6893         W_ERROR_HAVE_NO_MEMORY(r->description);
6894
6895         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6896         r->reserved = 0;
6897
6898         return WERR_OK;
6899 }
6900
6901
6902 /****************************************************************************
6903  wrapper around the enumer ports command
6904 ****************************************************************************/
6905
6906 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6907 {
6908         char *cmd = lp_enumports_cmd();
6909         char **qlines = NULL;
6910         char *command = NULL;
6911         int numlines;
6912         int ret;
6913         int fd;
6914
6915         *count = 0;
6916         *lines = NULL;
6917
6918         /* if no hook then just fill in the default port */
6919
6920         if ( !*cmd ) {
6921                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6922                         return WERR_NOMEM;
6923                 }
6924                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6925                         TALLOC_FREE(qlines);
6926                         return WERR_NOMEM;
6927                 }
6928                 qlines[1] = NULL;
6929                 numlines = 1;
6930         }
6931         else {
6932                 /* we have a valid enumport command */
6933
6934                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6935                 if (!command) {
6936                         return WERR_NOMEM;
6937                 }
6938
6939                 DEBUG(10,("Running [%s]\n", command));
6940                 ret = smbrun(command, &fd);
6941                 DEBUG(10,("Returned [%d]\n", ret));
6942                 TALLOC_FREE(command);
6943                 if (ret != 0) {
6944                         if (fd != -1) {
6945                                 close(fd);
6946                         }
6947                         return WERR_ACCESS_DENIED;
6948                 }
6949
6950                 numlines = 0;
6951                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6952                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6953                 close(fd);
6954         }
6955
6956         *count = numlines;
6957         *lines = qlines;
6958
6959         return WERR_OK;
6960 }
6961
6962 /****************************************************************************
6963  enumports level 1.
6964 ****************************************************************************/
6965
6966 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6967                                 union spoolss_PortInfo **info_p,
6968                                 uint32_t *count)
6969 {
6970         union spoolss_PortInfo *info = NULL;
6971         int i=0;
6972         WERROR result = WERR_OK;
6973         char **qlines = NULL;
6974         int numlines = 0;
6975
6976         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6977         if (!W_ERROR_IS_OK(result)) {
6978                 goto out;
6979         }
6980
6981         if (numlines) {
6982                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6983                 if (!info) {
6984                         DEBUG(10,("Returning WERR_NOMEM\n"));
6985                         result = WERR_NOMEM;
6986                         goto out;
6987                 }
6988
6989                 for (i=0; i<numlines; i++) {
6990                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6991                         result = fill_port_1(info, &info[i].info1, qlines[i]);
6992                         if (!W_ERROR_IS_OK(result)) {
6993                                 goto out;
6994                         }
6995                 }
6996         }
6997         TALLOC_FREE(qlines);
6998
6999 out:
7000         if (!W_ERROR_IS_OK(result)) {
7001                 TALLOC_FREE(info);
7002                 TALLOC_FREE(qlines);
7003                 *count = 0;
7004                 *info_p = NULL;
7005                 return result;
7006         }
7007
7008         *info_p = info;
7009         *count = numlines;
7010
7011         return WERR_OK;
7012 }
7013
7014 /****************************************************************************
7015  enumports level 2.
7016 ****************************************************************************/
7017
7018 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7019                                 union spoolss_PortInfo **info_p,
7020                                 uint32_t *count)
7021 {
7022         union spoolss_PortInfo *info = NULL;
7023         int i=0;
7024         WERROR result = WERR_OK;
7025         char **qlines = NULL;
7026         int numlines = 0;
7027
7028         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7029         if (!W_ERROR_IS_OK(result)) {
7030                 goto out;
7031         }
7032
7033         if (numlines) {
7034                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7035                 if (!info) {
7036                         DEBUG(10,("Returning WERR_NOMEM\n"));
7037                         result = WERR_NOMEM;
7038                         goto out;
7039                 }
7040
7041                 for (i=0; i<numlines; i++) {
7042                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7043                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7044                         if (!W_ERROR_IS_OK(result)) {
7045                                 goto out;
7046                         }
7047                 }
7048         }
7049         TALLOC_FREE(qlines);
7050
7051 out:
7052         if (!W_ERROR_IS_OK(result)) {
7053                 TALLOC_FREE(info);
7054                 TALLOC_FREE(qlines);
7055                 *count = 0;
7056                 *info_p = NULL;
7057                 return result;
7058         }
7059
7060         *info_p = info;
7061         *count = numlines;
7062
7063         return WERR_OK;
7064 }
7065
7066 /****************************************************************
7067  _spoolss_EnumPorts
7068 ****************************************************************/
7069
7070 WERROR _spoolss_EnumPorts(pipes_struct *p,
7071                           struct spoolss_EnumPorts *r)
7072 {
7073         WERROR result;
7074
7075         /* that's an [in out] buffer */
7076
7077         if (!r->in.buffer && (r->in.offered != 0)) {
7078                 return WERR_INVALID_PARAM;
7079         }
7080
7081         DEBUG(4,("_spoolss_EnumPorts\n"));
7082
7083         *r->out.count = 0;
7084         *r->out.needed = 0;
7085         *r->out.info = NULL;
7086
7087         switch (r->in.level) {
7088         case 1:
7089                 result = enumports_level_1(p->mem_ctx, r->out.info,
7090                                            r->out.count);
7091                 break;
7092         case 2:
7093                 result = enumports_level_2(p->mem_ctx, r->out.info,
7094                                            r->out.count);
7095                 break;
7096         default:
7097                 return WERR_UNKNOWN_LEVEL;
7098         }
7099
7100         if (!W_ERROR_IS_OK(result)) {
7101                 return result;
7102         }
7103
7104         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7105                                                      spoolss_EnumPorts, NULL,
7106                                                      *r->out.info, r->in.level,
7107                                                      *r->out.count);
7108         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7109         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7110
7111         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7112 }
7113
7114 /****************************************************************************
7115 ****************************************************************************/
7116
7117 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7118                                            const char *server,
7119                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7120                                            struct spoolss_DeviceMode *devmode,
7121                                            struct security_descriptor *sec_desc,
7122                                            struct spoolss_UserLevelCtr *user_ctr,
7123                                            struct policy_handle *handle)
7124 {
7125         NT_PRINTER_INFO_LEVEL *printer = NULL;
7126         fstring name;
7127         int     snum;
7128         WERROR err = WERR_OK;
7129
7130         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7131                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7132                 return WERR_NOMEM;
7133         }
7134
7135         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7136         if (!convert_printer_info(info_ctr, printer)) {
7137                 free_a_printer(&printer, 2);
7138                 return WERR_NOMEM;
7139         }
7140
7141         /* samba does not have a concept of local, non-shared printers yet, so
7142          * make sure we always setup sharename - gd */
7143         if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7144                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7145                         "no sharename has been set, setting printername %s as sharename\n",
7146                         printer->info_2->printername));
7147                 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7148         }
7149
7150         /* check to see if the printer already exists */
7151
7152         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7153                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7154                         printer->info_2->sharename));
7155                 free_a_printer(&printer, 2);
7156                 return WERR_PRINTER_ALREADY_EXISTS;
7157         }
7158
7159         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7160                 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7161                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7162                                 printer->info_2->printername));
7163                         free_a_printer(&printer, 2);
7164                         return WERR_PRINTER_ALREADY_EXISTS;
7165                 }
7166         }
7167
7168         /* validate printer info struct */
7169         if (!info_ctr->info.info2->printername ||
7170             strlen(info_ctr->info.info2->printername) == 0) {
7171                 free_a_printer(&printer,2);
7172                 return WERR_INVALID_PRINTER_NAME;
7173         }
7174         if (!info_ctr->info.info2->portname ||
7175             strlen(info_ctr->info.info2->portname) == 0) {
7176                 free_a_printer(&printer,2);
7177                 return WERR_UNKNOWN_PORT;
7178         }
7179         if (!info_ctr->info.info2->drivername ||
7180             strlen(info_ctr->info.info2->drivername) == 0) {
7181                 free_a_printer(&printer,2);
7182                 return WERR_UNKNOWN_PRINTER_DRIVER;
7183         }
7184         if (!info_ctr->info.info2->printprocessor ||
7185             strlen(info_ctr->info.info2->printprocessor) == 0) {
7186                 free_a_printer(&printer,2);
7187                 return WERR_UNKNOWN_PRINTPROCESSOR;
7188         }
7189
7190         /* FIXME!!!  smbd should check to see if the driver is installed before
7191            trying to add a printer like this  --jerry */
7192
7193         if (*lp_addprinter_cmd() ) {
7194                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7195                                        printer) ) {
7196                         free_a_printer(&printer,2);
7197                         return WERR_ACCESS_DENIED;
7198                 }
7199         } else {
7200                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7201                         "smb.conf parameter \"addprinter command\" is defined. This"
7202                         "parameter must exist for this call to succeed\n",
7203                         printer->info_2->sharename ));
7204         }
7205
7206         /* use our primary netbios name since get_a_printer() will convert
7207            it to what the client expects on a case by case basis */
7208
7209         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7210              printer->info_2->sharename);
7211
7212
7213         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7214                 free_a_printer(&printer,2);
7215                 return WERR_ACCESS_DENIED;
7216         }
7217
7218         /* you must be a printer admin to add a new printer */
7219         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7220                 free_a_printer(&printer,2);
7221                 return WERR_ACCESS_DENIED;
7222         }
7223
7224         /*
7225          * Do sanity check on the requested changes for Samba.
7226          */
7227
7228         if (!check_printer_ok(printer->info_2, snum)) {
7229                 free_a_printer(&printer,2);
7230                 return WERR_INVALID_PARAM;
7231         }
7232
7233         /*
7234          * When a printer is created, the drivername bound to the printer is used
7235          * to lookup previously saved driver initialization info, which is then
7236          * bound to the new printer, simulating what happens in the Windows arch.
7237          */
7238
7239         if (!devmode)
7240         {
7241                 set_driver_init(printer, 2);
7242         }
7243         else
7244         {
7245                 /* A valid devmode was included, convert and link it
7246                 */
7247                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7248
7249                 if (!convert_devicemode(printer->info_2->printername, devmode,
7250                                         &printer->info_2->devmode)) {
7251                         return  WERR_NOMEM;
7252                 }
7253         }
7254
7255         /* write the ASCII on disk */
7256         err = mod_a_printer(printer, 2);
7257         if (!W_ERROR_IS_OK(err)) {
7258                 free_a_printer(&printer,2);
7259                 return err;
7260         }
7261
7262         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7263                 /* Handle open failed - remove addition. */
7264                 del_a_printer(printer->info_2->sharename);
7265                 free_a_printer(&printer,2);
7266                 ZERO_STRUCTP(handle);
7267                 return WERR_ACCESS_DENIED;
7268         }
7269
7270         update_c_setprinter(false);
7271         free_a_printer(&printer,2);
7272
7273         return WERR_OK;
7274 }
7275
7276 /****************************************************************
7277  _spoolss_AddPrinterEx
7278 ****************************************************************/
7279
7280 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7281                              struct spoolss_AddPrinterEx *r)
7282 {
7283         switch (r->in.info_ctr->level) {
7284         case 1:
7285                 /* we don't handle yet */
7286                 /* but I know what to do ... */
7287                 return WERR_UNKNOWN_LEVEL;
7288         case 2:
7289                 return spoolss_addprinterex_level_2(p, r->in.server,
7290                                                     r->in.info_ctr,
7291                                                     r->in.devmode_ctr->devmode,
7292                                                     r->in.secdesc_ctr->sd,
7293                                                     r->in.userlevel_ctr,
7294                                                     r->out.handle);
7295         default:
7296                 return WERR_UNKNOWN_LEVEL;
7297         }
7298 }
7299
7300 /****************************************************************
7301  _spoolss_AddPrinter
7302 ****************************************************************/
7303
7304 WERROR _spoolss_AddPrinter(pipes_struct *p,
7305                            struct spoolss_AddPrinter *r)
7306 {
7307         struct spoolss_AddPrinterEx a;
7308         struct spoolss_UserLevelCtr userlevel_ctr;
7309
7310         ZERO_STRUCT(userlevel_ctr);
7311
7312         userlevel_ctr.level = 1;
7313
7314         a.in.server             = r->in.server;
7315         a.in.info_ctr           = r->in.info_ctr;
7316         a.in.devmode_ctr        = r->in.devmode_ctr;
7317         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7318         a.in.userlevel_ctr      = &userlevel_ctr;
7319         a.out.handle            = r->out.handle;
7320
7321         return _spoolss_AddPrinterEx(p, &a);
7322 }
7323
7324 /****************************************************************
7325  _spoolss_AddPrinterDriver
7326 ****************************************************************/
7327
7328 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7329                                  struct spoolss_AddPrinterDriver *r)
7330 {
7331         WERROR err = WERR_OK;
7332         char *driver_name = NULL;
7333         uint32_t version;
7334         const char *fn;
7335
7336         switch (p->hdr_req.opnum) {
7337                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7338                         fn = "_spoolss_AddPrinterDriver";
7339                         break;
7340                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7341                         fn = "_spoolss_AddPrinterDriverEx";
7342                         break;
7343                 default:
7344                         return WERR_INVALID_PARAM;
7345         }
7346
7347
7348         /* FIXME */
7349         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7350                 /* Clever hack from Martin Zielinski <mz@seh.de>
7351                  * to allow downgrade from level 8 (Vista).
7352                  */
7353                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7354                         r->in.info_ctr->level));
7355                 return WERR_UNKNOWN_LEVEL;
7356         }
7357
7358         DEBUG(5,("Cleaning driver's information\n"));
7359         err = clean_up_driver_struct(p, r->in.info_ctr);
7360         if (!W_ERROR_IS_OK(err))
7361                 goto done;
7362
7363         DEBUG(5,("Moving driver to final destination\n"));
7364         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7365                                                               &err)) ) {
7366                 goto done;
7367         }
7368
7369         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7370                 err = WERR_ACCESS_DENIED;
7371                 goto done;
7372         }
7373
7374         /*
7375          * I think this is where he DrvUpgradePrinter() hook would be
7376          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7377          * server.  Right now, we just need to send ourselves a message
7378          * to update each printer bound to this driver.   --jerry
7379          */
7380
7381         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7382                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7383                         fn, driver_name));
7384         }
7385
7386         /*
7387          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7388          * decide if the driver init data should be deleted. The rules are:
7389          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7390          *  2) delete init data only if there is no 2k/Xp driver
7391          *  3) always delete init data
7392          * The generalized rule is always use init data from the highest order driver.
7393          * It is necessary to follow the driver install by an initialization step to
7394          * finish off this process.
7395         */
7396
7397         switch (version) {
7398                 /*
7399                  * 9x printer driver - never delete init data
7400                 */
7401                 case 0:
7402                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7403                                 fn, driver_name));
7404                         break;
7405
7406                 /*
7407                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7408                  * there is no 2k/Xp driver init data for this driver name.
7409                 */
7410                 case 2:
7411                 {
7412                         struct spoolss_DriverInfo8 *driver1;
7413
7414                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
7415                                 /*
7416                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7417                                 */
7418                                 if (!del_driver_init(driver_name))
7419                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7420                                                 fn, driver_name));
7421                         } else {
7422                                 /*
7423                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7424                                 */
7425                                 free_a_printer_driver(driver1);
7426                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7427                                         fn, driver_name));
7428                         }
7429                 }
7430                 break;
7431
7432                 /*
7433                  * 2k or Xp printer driver - always delete init data
7434                 */
7435                 case 3:
7436                         if (!del_driver_init(driver_name))
7437                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7438                                         fn, driver_name));
7439                         break;
7440
7441                 default:
7442                         DEBUG(0,("%s: invalid level=%d\n", fn,
7443                                 r->in.info_ctr->level));
7444                         break;
7445         }
7446
7447
7448 done:
7449         return err;
7450 }
7451
7452 /****************************************************************
7453  _spoolss_AddPrinterDriverEx
7454 ****************************************************************/
7455
7456 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7457                                    struct spoolss_AddPrinterDriverEx *r)
7458 {
7459         struct spoolss_AddPrinterDriver a;
7460
7461         /*
7462          * we only support the semantics of AddPrinterDriver()
7463          * i.e. only copy files that are newer than existing ones
7464          */
7465
7466         if (r->in.flags != APD_COPY_NEW_FILES) {
7467                 return WERR_ACCESS_DENIED;
7468         }
7469
7470         a.in.servername         = r->in.servername;
7471         a.in.info_ctr           = r->in.info_ctr;
7472
7473         return _spoolss_AddPrinterDriver(p, &a);
7474 }
7475
7476 /****************************************************************************
7477 ****************************************************************************/
7478
7479 struct _spoolss_paths {
7480         int type;
7481         const char *share;
7482         const char *dir;
7483 };
7484
7485 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7486
7487 static const struct _spoolss_paths spoolss_paths[]= {
7488         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7489         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7490 };
7491
7492 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7493                                           const char *servername,
7494                                           const char *environment,
7495                                           int component,
7496                                           char **path)
7497 {
7498         const char *pservername = NULL;
7499         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7500         const char *short_archi;
7501
7502         *path = NULL;
7503
7504         /* environment may be empty */
7505         if (environment && strlen(environment)) {
7506                 long_archi = environment;
7507         }
7508
7509         /* servername may be empty */
7510         if (servername && strlen(servername)) {
7511                 pservername = canon_servername(servername);
7512
7513                 if (!is_myname_or_ipaddr(pservername)) {
7514                         return WERR_INVALID_PARAM;
7515                 }
7516         }
7517
7518         if (!(short_archi = get_short_archi(long_archi))) {
7519                 return WERR_INVALID_ENVIRONMENT;
7520         }
7521
7522         switch (component) {
7523         case SPOOLSS_PRTPROCS_PATH:
7524         case SPOOLSS_DRIVER_PATH:
7525                 if (pservername) {
7526                         *path = talloc_asprintf(mem_ctx,
7527                                         "\\\\%s\\%s\\%s",
7528                                         pservername,
7529                                         spoolss_paths[component].share,
7530                                         short_archi);
7531                 } else {
7532                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7533                                         SPOOLSS_DEFAULT_SERVER_PATH,
7534                                         spoolss_paths[component].dir,
7535                                         short_archi);
7536                 }
7537                 break;
7538         default:
7539                 return WERR_INVALID_PARAM;
7540         }
7541
7542         if (!*path) {
7543                 return WERR_NOMEM;
7544         }
7545
7546         return WERR_OK;
7547 }
7548
7549 /****************************************************************************
7550 ****************************************************************************/
7551
7552 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7553                                           const char *servername,
7554                                           const char *environment,
7555                                           struct spoolss_DriverDirectoryInfo1 *r)
7556 {
7557         WERROR werr;
7558         char *path = NULL;
7559
7560         werr = compose_spoolss_server_path(mem_ctx,
7561                                            servername,
7562                                            environment,
7563                                            SPOOLSS_DRIVER_PATH,
7564                                            &path);
7565         if (!W_ERROR_IS_OK(werr)) {
7566                 return werr;
7567         }
7568
7569         DEBUG(4,("printer driver directory: [%s]\n", path));
7570
7571         r->directory_name = path;
7572
7573         return WERR_OK;
7574 }
7575
7576 /****************************************************************
7577  _spoolss_GetPrinterDriverDirectory
7578 ****************************************************************/
7579
7580 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7581                                           struct spoolss_GetPrinterDriverDirectory *r)
7582 {
7583         WERROR werror;
7584
7585         /* that's an [in out] buffer */
7586
7587         if (!r->in.buffer && (r->in.offered != 0)) {
7588                 return WERR_INVALID_PARAM;
7589         }
7590
7591         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7592                 r->in.level));
7593
7594         *r->out.needed = 0;
7595
7596         /* r->in.level is ignored */
7597
7598         werror = getprinterdriverdir_level_1(p->mem_ctx,
7599                                              r->in.server,
7600                                              r->in.environment,
7601                                              &r->out.info->info1);
7602         if (!W_ERROR_IS_OK(werror)) {
7603                 TALLOC_FREE(r->out.info);
7604                 return werror;
7605         }
7606
7607         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7608                                                r->out.info, r->in.level);
7609         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7610
7611         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7612 }
7613
7614 /****************************************************************
7615  _spoolss_EnumPrinterData
7616 ****************************************************************/
7617
7618 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7619                                 struct spoolss_EnumPrinterData *r)
7620 {
7621         NT_PRINTER_INFO_LEVEL *printer = NULL;
7622         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7623         int             snum;
7624         WERROR          result;
7625         struct regval_blob      *val = NULL;
7626         NT_PRINTER_DATA *p_data;
7627         int             i, key_index, num_values;
7628         int             name_length;
7629
7630         *r->out.value_needed    = 0;
7631         *r->out.type            = REG_NONE;
7632         *r->out.data_needed     = 0;
7633
7634         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7635
7636         if (!Printer) {
7637                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7638                         OUR_HANDLE(r->in.handle)));
7639                 return WERR_BADFID;
7640         }
7641
7642         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7643                 return WERR_BADFID;
7644         }
7645
7646         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7647         if (!W_ERROR_IS_OK(result)) {
7648                 return result;
7649         }
7650
7651         p_data = printer->info_2->data;
7652         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7653
7654         result = WERR_OK;
7655
7656         /*
7657          * The NT machine wants to know the biggest size of value and data
7658          *
7659          * cf: MSDN EnumPrinterData remark section
7660          */
7661
7662         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7663
7664                 uint32_t biggest_valuesize = 0;
7665                 uint32_t biggest_datasize = 0;
7666
7667                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7668
7669                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7670
7671                 for ( i=0; i<num_values; i++ )
7672                 {
7673                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7674
7675                         name_length = strlen(val->valuename);
7676                         if ( strlen(val->valuename) > biggest_valuesize )
7677                                 biggest_valuesize = name_length;
7678
7679                         if ( val->size > biggest_datasize )
7680                                 biggest_datasize = val->size;
7681
7682                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7683                                 biggest_datasize));
7684                 }
7685
7686                 /* the value is an UNICODE string but real_value_size is the length
7687                    in bytes including the trailing 0 */
7688
7689                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7690                 *r->out.data_needed  = biggest_datasize;
7691
7692                 DEBUG(6,("final values: [%d], [%d]\n",
7693                         *r->out.value_needed, *r->out.data_needed));
7694
7695                 goto done;
7696         }
7697
7698         /*
7699          * the value len is wrong in NT sp3
7700          * that's the number of bytes not the number of unicode chars
7701          */
7702
7703         if (key_index != -1) {
7704                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7705                                                 r->in.enum_index);
7706         }
7707
7708         if (!val) {
7709
7710                 /* out_value should default to "" or else NT4 has
7711                    problems unmarshalling the response */
7712
7713                 if (r->in.value_offered) {
7714                         *r->out.value_needed = 1;
7715                         r->out.value_name = talloc_strdup(r, "");
7716                         if (!r->out.value_name) {
7717                                 result = WERR_NOMEM;
7718                                 goto done;
7719                         }
7720                 } else {
7721                         r->out.value_name = NULL;
7722                         *r->out.value_needed = 0;
7723                 }
7724
7725                 /* the data is counted in bytes */
7726
7727                 *r->out.data_needed = r->in.data_offered;
7728
7729                 result = WERR_NO_MORE_ITEMS;
7730         } else {
7731                 /*
7732                  * the value is:
7733                  * - counted in bytes in the request
7734                  * - counted in UNICODE chars in the max reply
7735                  * - counted in bytes in the real size
7736                  *
7737                  * take a pause *before* coding not *during* coding
7738                  */
7739
7740                 /* name */
7741                 if (r->in.value_offered) {
7742                         r->out.value_name = talloc_strdup(r, regval_name(val));
7743                         if (!r->out.value_name) {
7744                                 result = WERR_NOMEM;
7745                                 goto done;
7746                         }
7747                         *r->out.value_needed = strlen_m(regval_name(val));
7748                 } else {
7749                         r->out.value_name = NULL;
7750                         *r->out.value_needed = 0;
7751                 }
7752
7753                 /* type */
7754
7755                 *r->out.type = regval_type(val);
7756
7757                 /* data - counted in bytes */
7758
7759                 /*
7760                  * See the section "Dynamically Typed Query Parameters"
7761                  * in MS-RPRN.
7762                  */
7763
7764                 if (r->out.data && regval_data_p(val) &&
7765                                 regval_size(val) && r->in.data_offered) {
7766                         memcpy(r->out.data, regval_data_p(val),
7767                                 MIN(regval_size(val),r->in.data_offered));
7768                 }
7769
7770                 *r->out.data_needed = regval_size(val);
7771         }
7772
7773 done:
7774         free_a_printer(&printer, 2);
7775         return result;
7776 }
7777
7778 /****************************************************************
7779  _spoolss_SetPrinterData
7780 ****************************************************************/
7781
7782 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7783                                struct spoolss_SetPrinterData *r)
7784 {
7785         struct spoolss_SetPrinterDataEx r2;
7786
7787         r2.in.handle            = r->in.handle;
7788         r2.in.key_name          = "PrinterDriverData";
7789         r2.in.value_name        = r->in.value_name;
7790         r2.in.type              = r->in.type;
7791         r2.in.data              = r->in.data;
7792         r2.in._offered          = r->in._offered;
7793
7794         return _spoolss_SetPrinterDataEx(p, &r2);
7795 }
7796
7797 /****************************************************************
7798  _spoolss_ResetPrinter
7799 ****************************************************************/
7800
7801 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7802                              struct spoolss_ResetPrinter *r)
7803 {
7804         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7805         int             snum;
7806
7807         DEBUG(5,("_spoolss_ResetPrinter\n"));
7808
7809         /*
7810          * All we do is to check to see if the handle and queue is valid.
7811          * This call really doesn't mean anything to us because we only
7812          * support RAW printing.   --jerry
7813          */
7814
7815         if (!Printer) {
7816                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7817                         OUR_HANDLE(r->in.handle)));
7818                 return WERR_BADFID;
7819         }
7820
7821         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7822                 return WERR_BADFID;
7823
7824
7825         /* blindly return success */
7826         return WERR_OK;
7827 }
7828
7829 /****************************************************************
7830  _spoolss_DeletePrinterData
7831 ****************************************************************/
7832
7833 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7834                                   struct spoolss_DeletePrinterData *r)
7835 {
7836         struct spoolss_DeletePrinterDataEx r2;
7837
7838         r2.in.handle            = r->in.handle;
7839         r2.in.key_name          = "PrinterDriverData";
7840         r2.in.value_name        = r->in.value_name;
7841
7842         return _spoolss_DeletePrinterDataEx(p, &r2);
7843 }
7844
7845 /****************************************************************
7846  _spoolss_AddForm
7847 ****************************************************************/
7848
7849 WERROR _spoolss_AddForm(pipes_struct *p,
7850                         struct spoolss_AddForm *r)
7851 {
7852         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7853         nt_forms_struct tmpForm;
7854         int snum = -1;
7855         WERROR status = WERR_OK;
7856         NT_PRINTER_INFO_LEVEL *printer = NULL;
7857         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7858
7859         int count=0;
7860         nt_forms_struct *list=NULL;
7861         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7862
7863         DEBUG(5,("_spoolss_AddForm\n"));
7864
7865         if (!Printer) {
7866                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7867                         OUR_HANDLE(r->in.handle)));
7868                 return WERR_BADFID;
7869         }
7870
7871
7872         /* forms can be added on printer of on the print server handle */
7873
7874         if ( Printer->printer_type == SPLHND_PRINTER )
7875         {
7876                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7877                         return WERR_BADFID;
7878
7879                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7880                 if (!W_ERROR_IS_OK(status))
7881                         goto done;
7882         }
7883
7884         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7885            and not a printer admin, then fail */
7886
7887         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7888              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7889              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7890                                           NULL, NULL,
7891                                           p->server_info->ptok,
7892                                           lp_printer_admin(snum))) {
7893                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7894                 return WERR_ACCESS_DENIED;
7895         }
7896
7897         /* can't add if builtin */
7898
7899         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7900                 status = WERR_FILE_EXISTS;
7901                 goto done;
7902         }
7903
7904         count = get_ntforms(&list);
7905
7906         if(!add_a_form(&list, form, &count)) {
7907                 status =  WERR_NOMEM;
7908                 goto done;
7909         }
7910
7911         become_root();
7912         write_ntforms(&list, count);
7913         unbecome_root();
7914
7915         /*
7916          * ChangeID must always be set if this is a printer
7917          */
7918
7919         if ( Printer->printer_type == SPLHND_PRINTER )
7920                 status = mod_a_printer(printer, 2);
7921
7922 done:
7923         if ( printer )
7924                 free_a_printer(&printer, 2);
7925         SAFE_FREE(list);
7926
7927         return status;
7928 }
7929
7930 /****************************************************************
7931  _spoolss_DeleteForm
7932 ****************************************************************/
7933
7934 WERROR _spoolss_DeleteForm(pipes_struct *p,
7935                            struct spoolss_DeleteForm *r)
7936 {
7937         const char *form_name = r->in.form_name;
7938         nt_forms_struct tmpForm;
7939         int count=0;
7940         nt_forms_struct *list=NULL;
7941         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7942         int snum = -1;
7943         WERROR status = WERR_OK;
7944         NT_PRINTER_INFO_LEVEL *printer = NULL;
7945         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7946         bool ret = false;
7947
7948         DEBUG(5,("_spoolss_DeleteForm\n"));
7949
7950         if (!Printer) {
7951                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7952                         OUR_HANDLE(r->in.handle)));
7953                 return WERR_BADFID;
7954         }
7955
7956         /* forms can be deleted on printer of on the print server handle */
7957
7958         if ( Printer->printer_type == SPLHND_PRINTER )
7959         {
7960                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7961                         return WERR_BADFID;
7962
7963                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7964                 if (!W_ERROR_IS_OK(status))
7965                         goto done;
7966         }
7967
7968         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7969              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7970              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7971                                           NULL, NULL,
7972                                           p->server_info->ptok,
7973                                           lp_printer_admin(snum))) {
7974                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7975                 return WERR_ACCESS_DENIED;
7976         }
7977
7978
7979         /* can't delete if builtin */
7980
7981         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7982                 status = WERR_INVALID_PARAM;
7983                 goto done;
7984         }
7985
7986         count = get_ntforms(&list);
7987
7988         become_root();
7989         ret = delete_a_form(&list, form_name, &count, &status);
7990         unbecome_root();
7991         if (ret == false) {
7992                 goto done;
7993         }
7994
7995         /*
7996          * ChangeID must always be set if this is a printer
7997          */
7998
7999         if ( Printer->printer_type == SPLHND_PRINTER )
8000                 status = mod_a_printer(printer, 2);
8001
8002 done:
8003         if ( printer )
8004                 free_a_printer(&printer, 2);
8005         SAFE_FREE(list);
8006
8007         return status;
8008 }
8009
8010 /****************************************************************
8011  _spoolss_SetForm
8012 ****************************************************************/
8013
8014 WERROR _spoolss_SetForm(pipes_struct *p,
8015                         struct spoolss_SetForm *r)
8016 {
8017         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8018         nt_forms_struct tmpForm;
8019         int snum = -1;
8020         WERROR status = WERR_OK;
8021         NT_PRINTER_INFO_LEVEL *printer = NULL;
8022         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8023
8024         int count=0;
8025         nt_forms_struct *list=NULL;
8026         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8027
8028         DEBUG(5,("_spoolss_SetForm\n"));
8029
8030         if (!Printer) {
8031                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8032                         OUR_HANDLE(r->in.handle)));
8033                 return WERR_BADFID;
8034         }
8035
8036         /* forms can be modified on printer of on the print server handle */
8037
8038         if ( Printer->printer_type == SPLHND_PRINTER )
8039         {
8040                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8041                         return WERR_BADFID;
8042
8043                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8044                 if (!W_ERROR_IS_OK(status))
8045                         goto done;
8046         }
8047
8048         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8049            and not a printer admin, then fail */
8050
8051         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8052              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8053              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8054                                           NULL, NULL,
8055                                           p->server_info->ptok,
8056                                           lp_printer_admin(snum))) {
8057                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8058                 return WERR_ACCESS_DENIED;
8059         }
8060
8061         /* can't set if builtin */
8062         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8063                 status = WERR_INVALID_PARAM;
8064                 goto done;
8065         }
8066
8067         count = get_ntforms(&list);
8068         update_a_form(&list, form, count);
8069         become_root();
8070         write_ntforms(&list, count);
8071         unbecome_root();
8072
8073         /*
8074          * ChangeID must always be set if this is a printer
8075          */
8076
8077         if ( Printer->printer_type == SPLHND_PRINTER )
8078                 status = mod_a_printer(printer, 2);
8079
8080
8081 done:
8082         if ( printer )
8083                 free_a_printer(&printer, 2);
8084         SAFE_FREE(list);
8085
8086         return status;
8087 }
8088
8089 /****************************************************************************
8090  fill_print_processor1
8091 ****************************************************************************/
8092
8093 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8094                                     struct spoolss_PrintProcessorInfo1 *r,
8095                                     const char *print_processor_name)
8096 {
8097         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8098         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8099
8100         return WERR_OK;
8101 }
8102
8103 /****************************************************************************
8104  enumprintprocessors level 1.
8105 ****************************************************************************/
8106
8107 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8108                                           union spoolss_PrintProcessorInfo **info_p,
8109                                           uint32_t *count)
8110 {
8111         union spoolss_PrintProcessorInfo *info;
8112         WERROR result;
8113
8114         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8115         W_ERROR_HAVE_NO_MEMORY(info);
8116
8117         *count = 1;
8118
8119         result = fill_print_processor1(info, &info[0].info1, "winprint");
8120         if (!W_ERROR_IS_OK(result)) {
8121                 goto out;
8122         }
8123
8124  out:
8125         if (!W_ERROR_IS_OK(result)) {
8126                 TALLOC_FREE(info);
8127                 *count = 0;
8128                 return result;
8129         }
8130
8131         *info_p = info;
8132
8133         return WERR_OK;
8134 }
8135
8136 /****************************************************************
8137  _spoolss_EnumPrintProcessors
8138 ****************************************************************/
8139
8140 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8141                                     struct spoolss_EnumPrintProcessors *r)
8142 {
8143         WERROR result;
8144
8145         /* that's an [in out] buffer */
8146
8147         if (!r->in.buffer && (r->in.offered != 0)) {
8148                 return WERR_INVALID_PARAM;
8149         }
8150
8151         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8152
8153         /*
8154          * Enumerate the print processors ...
8155          *
8156          * Just reply with "winprint", to keep NT happy
8157          * and I can use my nice printer checker.
8158          */
8159
8160         *r->out.count = 0;
8161         *r->out.needed = 0;
8162         *r->out.info = NULL;
8163
8164         switch (r->in.level) {
8165         case 1:
8166                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8167                                                      r->out.count);
8168                 break;
8169         default:
8170                 return WERR_UNKNOWN_LEVEL;
8171         }
8172
8173         if (!W_ERROR_IS_OK(result)) {
8174                 return result;
8175         }
8176
8177         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8178                                                      spoolss_EnumPrintProcessors, NULL,
8179                                                      *r->out.info, r->in.level,
8180                                                      *r->out.count);
8181         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8182         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8183
8184         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8185 }
8186
8187 /****************************************************************************
8188  fill_printprocdatatype1
8189 ****************************************************************************/
8190
8191 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8192                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8193                                       const char *name_array)
8194 {
8195         r->name_array = talloc_strdup(mem_ctx, name_array);
8196         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8197
8198         return WERR_OK;
8199 }
8200
8201 /****************************************************************************
8202  enumprintprocdatatypes level 1.
8203 ****************************************************************************/
8204
8205 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8206                                              union spoolss_PrintProcDataTypesInfo **info_p,
8207                                              uint32_t *count)
8208 {
8209         WERROR result;
8210         union spoolss_PrintProcDataTypesInfo *info;
8211
8212         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8213         W_ERROR_HAVE_NO_MEMORY(info);
8214
8215         *count = 1;
8216
8217         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8218         if (!W_ERROR_IS_OK(result)) {
8219                 goto out;
8220         }
8221
8222  out:
8223         if (!W_ERROR_IS_OK(result)) {
8224                 TALLOC_FREE(info);
8225                 *count = 0;
8226                 return result;
8227         }
8228
8229         *info_p = info;
8230
8231         return WERR_OK;
8232 }
8233
8234 /****************************************************************
8235  _spoolss_EnumPrintProcDataTypes
8236 ****************************************************************/
8237
8238 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8239                                        struct spoolss_EnumPrintProcDataTypes *r)
8240 {
8241         WERROR result;
8242
8243         /* that's an [in out] buffer */
8244
8245         if (!r->in.buffer && (r->in.offered != 0)) {
8246                 return WERR_INVALID_PARAM;
8247         }
8248
8249         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8250
8251         *r->out.count = 0;
8252         *r->out.needed = 0;
8253         *r->out.info = NULL;
8254
8255         switch (r->in.level) {
8256         case 1:
8257                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8258                                                         r->out.count);
8259                 break;
8260         default:
8261                 return WERR_UNKNOWN_LEVEL;
8262         }
8263
8264         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8265                                                      spoolss_EnumPrintProcDataTypes, NULL,
8266                                                      *r->out.info, r->in.level,
8267                                                      *r->out.count);
8268         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8269         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8270
8271         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8272 }
8273
8274 /****************************************************************************
8275  fill_monitor_1
8276 ****************************************************************************/
8277
8278 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8279                              struct spoolss_MonitorInfo1 *r,
8280                              const char *monitor_name)
8281 {
8282         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8283         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8284
8285         return WERR_OK;
8286 }
8287
8288 /****************************************************************************
8289  fill_monitor_2
8290 ****************************************************************************/
8291
8292 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8293                              struct spoolss_MonitorInfo2 *r,
8294                              const char *monitor_name,
8295                              const char *environment,
8296                              const char *dll_name)
8297 {
8298         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8299         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8300         r->environment                  = talloc_strdup(mem_ctx, environment);
8301         W_ERROR_HAVE_NO_MEMORY(r->environment);
8302         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8303         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8304
8305         return WERR_OK;
8306 }
8307
8308 /****************************************************************************
8309  enumprintmonitors level 1.
8310 ****************************************************************************/
8311
8312 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8313                                         union spoolss_MonitorInfo **info_p,
8314                                         uint32_t *count)
8315 {
8316         union spoolss_MonitorInfo *info;
8317         WERROR result = WERR_OK;
8318
8319         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8320         W_ERROR_HAVE_NO_MEMORY(info);
8321
8322         *count = 2;
8323
8324         result = fill_monitor_1(info, &info[0].info1,
8325                                 SPL_LOCAL_PORT);
8326         if (!W_ERROR_IS_OK(result)) {
8327                 goto out;
8328         }
8329
8330         result = fill_monitor_1(info, &info[1].info1,
8331                                 SPL_TCPIP_PORT);
8332         if (!W_ERROR_IS_OK(result)) {
8333                 goto out;
8334         }
8335
8336 out:
8337         if (!W_ERROR_IS_OK(result)) {
8338                 TALLOC_FREE(info);
8339                 *count = 0;
8340                 return result;
8341         }
8342
8343         *info_p = info;
8344
8345         return WERR_OK;
8346 }
8347
8348 /****************************************************************************
8349  enumprintmonitors level 2.
8350 ****************************************************************************/
8351
8352 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8353                                         union spoolss_MonitorInfo **info_p,
8354                                         uint32_t *count)
8355 {
8356         union spoolss_MonitorInfo *info;
8357         WERROR result = WERR_OK;
8358
8359         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8360         W_ERROR_HAVE_NO_MEMORY(info);
8361
8362         *count = 2;
8363
8364         result = fill_monitor_2(info, &info[0].info2,
8365                                 SPL_LOCAL_PORT,
8366                                 "Windows NT X86", /* FIXME */
8367                                 "localmon.dll");
8368         if (!W_ERROR_IS_OK(result)) {
8369                 goto out;
8370         }
8371
8372         result = fill_monitor_2(info, &info[1].info2,
8373                                 SPL_TCPIP_PORT,
8374                                 "Windows NT X86", /* FIXME */
8375                                 "tcpmon.dll");
8376         if (!W_ERROR_IS_OK(result)) {
8377                 goto out;
8378         }
8379
8380 out:
8381         if (!W_ERROR_IS_OK(result)) {
8382                 TALLOC_FREE(info);
8383                 *count = 0;
8384                 return result;
8385         }
8386
8387         *info_p = info;
8388
8389         return WERR_OK;
8390 }
8391
8392 /****************************************************************
8393  _spoolss_EnumMonitors
8394 ****************************************************************/
8395
8396 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8397                              struct spoolss_EnumMonitors *r)
8398 {
8399         WERROR result;
8400
8401         /* that's an [in out] buffer */
8402
8403         if (!r->in.buffer && (r->in.offered != 0)) {
8404                 return WERR_INVALID_PARAM;
8405         }
8406
8407         DEBUG(5,("_spoolss_EnumMonitors\n"));
8408
8409         /*
8410          * Enumerate the print monitors ...
8411          *
8412          * Just reply with "Local Port", to keep NT happy
8413          * and I can use my nice printer checker.
8414          */
8415
8416         *r->out.count = 0;
8417         *r->out.needed = 0;
8418         *r->out.info = NULL;
8419
8420         switch (r->in.level) {
8421         case 1:
8422                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8423                                                    r->out.count);
8424                 break;
8425         case 2:
8426                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8427                                                    r->out.count);
8428                 break;
8429         default:
8430                 return WERR_UNKNOWN_LEVEL;
8431         }
8432
8433         if (!W_ERROR_IS_OK(result)) {
8434                 return result;
8435         }
8436
8437         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8438                                                      spoolss_EnumMonitors, NULL,
8439                                                      *r->out.info, r->in.level,
8440                                                      *r->out.count);
8441         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8442         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8443
8444         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8445 }
8446
8447 /****************************************************************************
8448 ****************************************************************************/
8449
8450 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8451                              const print_queue_struct *queue,
8452                              int count, int snum,
8453                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8454                              uint32_t jobid,
8455                              struct spoolss_JobInfo1 *r)
8456 {
8457         int i = 0;
8458         bool found = false;
8459
8460         for (i=0; i<count && found == false; i++) {
8461                 if (queue[i].job == (int)jobid) {
8462                         found = true;
8463                 }
8464         }
8465
8466         if (found == false) {
8467                 /* NT treats not found as bad param... yet another bad choice */
8468                 return WERR_INVALID_PARAM;
8469         }
8470
8471         return fill_job_info1(mem_ctx,
8472                               r,
8473                               &queue[i-1],
8474                               i,
8475                               snum,
8476                               ntprinter);
8477 }
8478
8479 /****************************************************************************
8480 ****************************************************************************/
8481
8482 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8483                              const print_queue_struct *queue,
8484                              int count, int snum,
8485                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8486                              uint32_t jobid,
8487                              struct spoolss_JobInfo2 *r)
8488 {
8489         int i = 0;
8490         bool found = false;
8491         struct spoolss_DeviceMode *devmode;
8492         NT_DEVICEMODE *nt_devmode;
8493         WERROR result;
8494
8495         for (i=0; i<count && found == false; i++) {
8496                 if (queue[i].job == (int)jobid) {
8497                         found = true;
8498                 }
8499         }
8500
8501         if (found == false) {
8502                 /* NT treats not found as bad param... yet another bad
8503                    choice */
8504                 return WERR_INVALID_PARAM;
8505         }
8506
8507         /*
8508          * if the print job does not have a DEVMODE associated with it,
8509          * just use the one for the printer. A NULL devicemode is not
8510          *  a failure condition
8511          */
8512
8513         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8514         if (nt_devmode) {
8515                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8516                 W_ERROR_HAVE_NO_MEMORY(devmode);
8517                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8518                 if (!W_ERROR_IS_OK(result)) {
8519                         return result;
8520                 }
8521         } else {
8522                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8523                 W_ERROR_HAVE_NO_MEMORY(devmode);
8524         }
8525
8526         return fill_job_info2(mem_ctx,
8527                               r,
8528                               &queue[i-1],
8529                               i,
8530                               snum,
8531                               ntprinter,
8532                               devmode);
8533 }
8534
8535 /****************************************************************
8536  _spoolss_GetJob
8537 ****************************************************************/
8538
8539 WERROR _spoolss_GetJob(pipes_struct *p,
8540                        struct spoolss_GetJob *r)
8541 {
8542         WERROR result = WERR_OK;
8543         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8544         int snum;
8545         int count;
8546         print_queue_struct      *queue = NULL;
8547         print_status_struct prt_status;
8548
8549         /* that's an [in out] buffer */
8550
8551         if (!r->in.buffer && (r->in.offered != 0)) {
8552                 return WERR_INVALID_PARAM;
8553         }
8554
8555         DEBUG(5,("_spoolss_GetJob\n"));
8556
8557         *r->out.needed = 0;
8558
8559         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8560                 return WERR_BADFID;
8561         }
8562
8563         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8564         if (!W_ERROR_IS_OK(result)) {
8565                 return result;
8566         }
8567
8568         count = print_queue_status(snum, &queue, &prt_status);
8569
8570         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8571                      count, prt_status.status, prt_status.message));
8572
8573         switch (r->in.level) {
8574         case 1:
8575                 result = getjob_level_1(p->mem_ctx,
8576                                         queue, count, snum, ntprinter,
8577                                         r->in.job_id, &r->out.info->info1);
8578                 break;
8579         case 2:
8580                 result = getjob_level_2(p->mem_ctx,
8581                                         queue, count, snum, ntprinter,
8582                                         r->in.job_id, &r->out.info->info2);
8583                 break;
8584         default:
8585                 result = WERR_UNKNOWN_LEVEL;
8586                 break;
8587         }
8588
8589         SAFE_FREE(queue);
8590         free_a_printer(&ntprinter, 2);
8591
8592         if (!W_ERROR_IS_OK(result)) {
8593                 TALLOC_FREE(r->out.info);
8594                 return result;
8595         }
8596
8597         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8598                                                r->out.info, r->in.level);
8599         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8600
8601         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8602 }
8603
8604 /****************************************************************
8605  _spoolss_GetPrinterDataEx
8606 ****************************************************************/
8607
8608 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8609                                  struct spoolss_GetPrinterDataEx *r)
8610 {
8611
8612         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8613         struct regval_blob              *val = NULL;
8614         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8615         int                     snum = 0;
8616         WERROR result = WERR_OK;
8617         DATA_BLOB blob;
8618
8619         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8620
8621         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8622                 r->in.key_name, r->in.value_name));
8623
8624         /* in case of problem, return some default values */
8625
8626         *r->out.needed  = 0;
8627         *r->out.type    = REG_NONE;
8628
8629         if (!Printer) {
8630                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8631                         OUR_HANDLE(r->in.handle)));
8632                 result = WERR_BADFID;
8633                 goto done;
8634         }
8635
8636         /* Is the handle to a printer or to the server? */
8637
8638         if (Printer->printer_type == SPLHND_SERVER) {
8639
8640                 result = getprinterdata_printer_server(p->mem_ctx,
8641                                                        r->in.value_name,
8642                                                        r->out.type,
8643                                                        r->out.data);
8644                 goto done;
8645         }
8646
8647         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8648                 result = WERR_BADFID;
8649                 goto done;
8650         }
8651
8652         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8653         if (!W_ERROR_IS_OK(result)) {
8654                 goto done;
8655         }
8656
8657         /* check to see if the keyname is valid */
8658         if (!strlen(r->in.key_name)) {
8659                 result = WERR_INVALID_PARAM;
8660                 goto done;
8661         }
8662
8663         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8664
8665         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8666             strequal(r->in.value_name, "ChangeId")) {
8667                 *r->out.type = REG_DWORD;
8668                 *r->out.needed = 4;
8669                 r->out.data->value = printer->info_2->changeid;
8670                 result = WERR_OK;
8671                 goto done;
8672         }
8673
8674         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8675                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8676                         "Invalid keyname [%s]\n", r->in.key_name ));
8677                 result = WERR_BADFILE;
8678                 goto done;
8679         }
8680
8681         val = get_printer_data(printer->info_2,
8682                                r->in.key_name, r->in.value_name);
8683         if (!val) {
8684                 result = WERR_BADFILE;
8685                 goto done;
8686         }
8687
8688         *r->out.needed = regval_size(val);
8689         *r->out.type = regval_type(val);
8690
8691         blob = data_blob_const(regval_data_p(val), regval_size(val));
8692
8693         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
8694                                           r->out.data,
8695                                           *r->out.type);
8696
8697  done:
8698         if (printer) {
8699                 free_a_printer(&printer, 2);
8700         }
8701
8702         if (!W_ERROR_IS_OK(result)) {
8703                 return result;
8704         }
8705
8706         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
8707         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8708         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8709
8710         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8711 }
8712
8713 /****************************************************************
8714  _spoolss_SetPrinterDataEx
8715 ****************************************************************/
8716
8717 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8718                                  struct spoolss_SetPrinterDataEx *r)
8719 {
8720         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8721         int                     snum = 0;
8722         WERROR                  result = WERR_OK;
8723         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8724         char                    *oid_string;
8725         DATA_BLOB blob;
8726
8727         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8728
8729         /* From MSDN documentation of SetPrinterDataEx: pass request to
8730            SetPrinterData if key is "PrinterDriverData" */
8731
8732         if (!Printer) {
8733                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8734                         OUR_HANDLE(r->in.handle)));
8735                 return WERR_BADFID;
8736         }
8737
8738         if (Printer->printer_type == SPLHND_SERVER) {
8739                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8740                         "Not implemented for server handles yet\n"));
8741                 return WERR_INVALID_PARAM;
8742         }
8743
8744         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8745                 return WERR_BADFID;
8746         }
8747
8748         /*
8749          * Access check : NT returns "access denied" if you make a
8750          * SetPrinterData call without the necessary privildge.
8751          * we were originally returning OK if nothing changed
8752          * which made Win2k issue **a lot** of SetPrinterData
8753          * when connecting to a printer  --jerry
8754          */
8755
8756         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8757                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8758                         "change denied by handle access permissions\n"));
8759                 return WERR_ACCESS_DENIED;
8760         }
8761
8762         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8763         if (!W_ERROR_IS_OK(result)) {
8764                 return result;
8765         }
8766
8767         /* check for OID in valuename */
8768
8769         oid_string = strchr(r->in.value_name, ',');
8770         if (oid_string) {
8771                 *oid_string = '\0';
8772                 oid_string++;
8773         }
8774
8775         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8776                                           r->in.type, &r->in.data);
8777         if (!W_ERROR_IS_OK(result)) {
8778                 goto done;
8779         }
8780
8781         /*
8782          * When client side code sets a magic printer data key, detect it and save
8783          * the current printer data and the magic key's data (its the DEVMODE) for
8784          * future printer/driver initializations.
8785          */
8786         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8787                 /* Set devmode and printer initialization info */
8788                 result = save_driver_init(printer, 2, blob.data, blob.length);
8789
8790                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8791
8792                 goto done;
8793         }
8794
8795         /* save the registry data */
8796
8797         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8798                                     r->in.type, blob.data, blob.length);
8799
8800         if (W_ERROR_IS_OK(result)) {
8801                 /* save the OID if one was specified */
8802                 if (oid_string) {
8803                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8804                                 r->in.key_name, SPOOL_OID_KEY);
8805                         if (!str) {
8806                                 result = WERR_NOMEM;
8807                                 goto done;
8808                         }
8809
8810                         /*
8811                          * I'm not checking the status here on purpose.  Don't know
8812                          * if this is right, but I'm returning the status from the
8813                          * previous set_printer_dataex() call.  I have no idea if
8814                          * this is right.    --jerry
8815                          */
8816
8817                         set_printer_dataex(printer, str, r->in.value_name,
8818                                            REG_SZ, (uint8_t *)oid_string,
8819                                            strlen(oid_string)+1);
8820                 }
8821
8822                 result = mod_a_printer(printer, 2);
8823         }
8824
8825  done:
8826         free_a_printer(&printer, 2);
8827
8828         return result;
8829 }
8830
8831 /****************************************************************
8832  _spoolss_DeletePrinterDataEx
8833 ****************************************************************/
8834
8835 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8836                                     struct spoolss_DeletePrinterDataEx *r)
8837 {
8838         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8839         int             snum=0;
8840         WERROR          status = WERR_OK;
8841         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8842
8843         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8844
8845         if (!Printer) {
8846                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8847                         "Invalid handle (%s:%u:%u).\n",
8848                         OUR_HANDLE(r->in.handle)));
8849                 return WERR_BADFID;
8850         }
8851
8852         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8853                 return WERR_BADFID;
8854
8855         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8856                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8857                         "printer properties change denied by handle\n"));
8858                 return WERR_ACCESS_DENIED;
8859         }
8860
8861         if (!r->in.value_name || !r->in.key_name) {
8862                 return WERR_NOMEM;
8863         }
8864
8865         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8866         if (!W_ERROR_IS_OK(status))
8867                 return status;
8868
8869         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8870
8871         if ( W_ERROR_IS_OK(status) )
8872                 mod_a_printer( printer, 2 );
8873
8874         free_a_printer(&printer, 2);
8875
8876         return status;
8877 }
8878
8879 /****************************************************************
8880  _spoolss_EnumPrinterKey
8881 ****************************************************************/
8882
8883 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8884                                struct spoolss_EnumPrinterKey *r)
8885 {
8886         fstring         *keynames = NULL;
8887         int             num_keys;
8888         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8889         NT_PRINTER_DATA *data;
8890         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8891         int             snum = 0;
8892         WERROR          result = WERR_BADFILE;
8893         int i;
8894         const char **array = NULL;
8895         DATA_BLOB blob;
8896
8897         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8898
8899         if (!Printer) {
8900                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8901                         OUR_HANDLE(r->in.handle)));
8902                 return WERR_BADFID;
8903         }
8904
8905         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8906                 return WERR_BADFID;
8907         }
8908
8909         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8910         if (!W_ERROR_IS_OK(result)) {
8911                 return result;
8912         }
8913
8914         /* get the list of subkey names */
8915
8916         data = printer->info_2->data;
8917
8918         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8919         if (num_keys == -1) {
8920                 result = WERR_BADFILE;
8921                 goto done;
8922         }
8923
8924         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8925         if (!array) {
8926                 result = WERR_NOMEM;
8927                 goto done;
8928         }
8929
8930         if (!num_keys) {
8931                 array[0] = talloc_strdup(array, "");
8932                 if (!array[0]) {
8933                         result = WERR_NOMEM;
8934                         goto done;
8935                 }
8936         }
8937
8938         for (i=0; i < num_keys; i++) {
8939
8940                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8941                         keynames[i]));
8942
8943                 array[i] = talloc_strdup(array, keynames[i]);
8944                 if (!array[i]) {
8945                         result = WERR_NOMEM;
8946                         goto done;
8947                 }
8948         }
8949
8950         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8951                 result = WERR_NOMEM;
8952                 goto done;
8953         }
8954
8955         *r->out._ndr_size = r->in.offered / 2;
8956         *r->out.needed = blob.length;
8957
8958         if (r->in.offered < *r->out.needed) {
8959                 result = WERR_MORE_DATA;
8960         } else {
8961                 result = WERR_OK;
8962                 r->out.key_buffer->string_array = array;
8963         }
8964
8965  done:
8966         if (!W_ERROR_IS_OK(result)) {
8967                 TALLOC_FREE(array);
8968                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8969                         *r->out.needed = 0;
8970                 }
8971         }
8972
8973         free_a_printer(&printer, 2);
8974         SAFE_FREE(keynames);
8975
8976         return result;
8977 }
8978
8979 /****************************************************************
8980  _spoolss_DeletePrinterKey
8981 ****************************************************************/
8982
8983 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8984                                  struct spoolss_DeletePrinterKey *r)
8985 {
8986         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8987         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8988         int                     snum=0;
8989         WERROR                  status;
8990
8991         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8992
8993         if (!Printer) {
8994                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8995                         OUR_HANDLE(r->in.handle)));
8996                 return WERR_BADFID;
8997         }
8998
8999         /* if keyname == NULL, return error */
9000
9001         if ( !r->in.key_name )
9002                 return WERR_INVALID_PARAM;
9003
9004         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9005                 return WERR_BADFID;
9006
9007         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9008                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9009                         "printer properties change denied by handle\n"));
9010                 return WERR_ACCESS_DENIED;
9011         }
9012
9013         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9014         if (!W_ERROR_IS_OK(status))
9015                 return status;
9016
9017         /* delete the key and all subneys */
9018
9019         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9020
9021         if ( W_ERROR_IS_OK(status) )
9022                 status = mod_a_printer(printer, 2);
9023
9024         free_a_printer( &printer, 2 );
9025
9026         return status;
9027 }
9028
9029 /****************************************************************
9030 ****************************************************************/
9031
9032 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9033                                                    struct regval_blob *v,
9034                                                    struct spoolss_PrinterEnumValues *r)
9035 {
9036         WERROR result;
9037
9038         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9039         W_ERROR_HAVE_NO_MEMORY(r->data);
9040
9041         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9042         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9043
9044         r->type         = regval_type(v);
9045         r->data_length  = regval_size(v);
9046
9047         if (r->data_length) {
9048                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9049                                                  regval_size(v));
9050                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9051                                                   r->data,
9052                                                   r->type);
9053                 if (!W_ERROR_IS_OK(result)) {
9054                         return result;
9055                 }
9056         }
9057
9058         return WERR_OK;
9059 }
9060
9061 /****************************************************************
9062  _spoolss_EnumPrinterDataEx
9063 ****************************************************************/
9064
9065 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9066                                   struct spoolss_EnumPrinterDataEx *r)
9067 {
9068         uint32_t        count = 0;
9069         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9070         struct spoolss_PrinterEnumValues *info = NULL;
9071         NT_PRINTER_DATA         *p_data;
9072         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9073         int             snum;
9074         WERROR          result;
9075         int             key_index;
9076         int             i;
9077
9078         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9079
9080         *r->out.count = 0;
9081         *r->out.needed = 0;
9082         *r->out.info = NULL;
9083
9084         if (!Printer) {
9085                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9086                         OUR_HANDLE(r->in.handle)));
9087                 return WERR_BADFID;
9088         }
9089
9090         /*
9091          * first check for a keyname of NULL or "".  Win2k seems to send
9092          * this a lot and we should send back WERR_INVALID_PARAM
9093          * no need to spend time looking up the printer in this case.
9094          * --jerry
9095          */
9096
9097         if (!strlen(r->in.key_name)) {
9098                 result = WERR_INVALID_PARAM;
9099                 goto done;
9100         }
9101
9102         /* get the printer off of disk */
9103
9104         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9105                 return WERR_BADFID;
9106         }
9107
9108         ZERO_STRUCT(printer);
9109         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9110         if (!W_ERROR_IS_OK(result)) {
9111                 return result;
9112         }
9113
9114         /* now look for a match on the key name */
9115
9116         p_data = printer->info_2->data;
9117
9118         key_index = lookup_printerkey(p_data, r->in.key_name);
9119         if (key_index == -1) {
9120                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9121                         r->in.key_name));
9122                 result = WERR_INVALID_PARAM;
9123                 goto done;
9124         }
9125
9126         /* allocate the memory for the array of pointers -- if necessary */
9127
9128         count = regval_ctr_numvals(p_data->keys[key_index].values);
9129         if (!count) {
9130                 result = WERR_OK; /* ??? */
9131                 goto done;
9132         }
9133
9134         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9135                                  struct spoolss_PrinterEnumValues,
9136                                  count);
9137         if (!info) {
9138                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9139                 result = WERR_NOMEM;
9140                 goto done;
9141         }
9142
9143         /*
9144          * loop through all params and build the array to pass
9145          * back to the  client
9146          */
9147
9148         for (i=0; i < count; i++) {
9149
9150                 struct regval_blob      *val;
9151
9152                 /* lookup the registry value */
9153
9154                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9155
9156                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9157
9158                 /* copy the data */
9159
9160                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9161                 if (!W_ERROR_IS_OK(result)) {
9162                         goto done;
9163                 }
9164         }
9165
9166 #if 0 /* FIXME - gd */
9167         /* housekeeping information in the reply */
9168
9169         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9170          * the hand marshalled container size is a multiple
9171          * of 4 bytes for RPC alignment.
9172          */
9173
9174         if (needed % 4) {
9175                 needed += 4-(needed % 4);
9176         }
9177 #endif
9178         *r->out.count   = count;
9179         *r->out.info    = info;
9180
9181  done:
9182
9183         if (printer) {
9184                 free_a_printer(&printer, 2);
9185         }
9186
9187         if (!W_ERROR_IS_OK(result)) {
9188                 return result;
9189         }
9190
9191         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9192                                                spoolss_EnumPrinterDataEx, NULL,
9193                                                *r->out.info,
9194                                                *r->out.count);
9195         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9196         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9197
9198         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9199 }
9200
9201 /****************************************************************************
9202 ****************************************************************************/
9203
9204 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9205                                                  const char *servername,
9206                                                  const char *environment,
9207                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9208 {
9209         WERROR werr;
9210         char *path = NULL;
9211
9212         werr = compose_spoolss_server_path(mem_ctx,
9213                                            servername,
9214                                            environment,
9215                                            SPOOLSS_PRTPROCS_PATH,
9216                                            &path);
9217         if (!W_ERROR_IS_OK(werr)) {
9218                 return werr;
9219         }
9220
9221         DEBUG(4,("print processor directory: [%s]\n", path));
9222
9223         r->directory_name = path;
9224
9225         return WERR_OK;
9226 }
9227
9228 /****************************************************************
9229  _spoolss_GetPrintProcessorDirectory
9230 ****************************************************************/
9231
9232 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9233                                            struct spoolss_GetPrintProcessorDirectory *r)
9234 {
9235         WERROR result;
9236
9237         /* that's an [in out] buffer */
9238
9239         if (!r->in.buffer && (r->in.offered != 0)) {
9240                 return WERR_INVALID_PARAM;
9241         }
9242
9243         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9244                 r->in.level));
9245
9246         *r->out.needed = 0;
9247
9248         /* r->in.level is ignored */
9249
9250         /* We always should reply with a local print processor directory so that
9251          * users are not forced to have a [prnproc$] share on the Samba spoolss
9252          * server - Guenther */
9253
9254         result = getprintprocessordirectory_level_1(p->mem_ctx,
9255                                                     NULL, /* r->in.server */
9256                                                     r->in.environment,
9257                                                     &r->out.info->info1);
9258         if (!W_ERROR_IS_OK(result)) {
9259                 TALLOC_FREE(r->out.info);
9260                 return result;
9261         }
9262
9263         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9264                                                r->out.info, r->in.level);
9265         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9266
9267         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9268 }
9269
9270 /*******************************************************************
9271  ********************************************************************/
9272
9273 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9274                                const char *dllname)
9275 {
9276         enum ndr_err_code ndr_err;
9277         struct spoolss_MonitorUi ui;
9278
9279         ui.dll_name = dllname;
9280
9281         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9282                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9283         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9284                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9285         }
9286         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9287 }
9288
9289 /*******************************************************************
9290  Streams the monitor UI DLL name in UNICODE
9291 *******************************************************************/
9292
9293 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9294                                NT_USER_TOKEN *token, DATA_BLOB *in,
9295                                DATA_BLOB *out, uint32_t *needed)
9296 {
9297         const char *dllname = "tcpmonui.dll";
9298
9299         *needed = (strlen(dllname)+1) * 2;
9300
9301         if (out->length < *needed) {
9302                 return WERR_INSUFFICIENT_BUFFER;
9303         }
9304
9305         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9306                 return WERR_NOMEM;
9307         }
9308
9309         return WERR_OK;
9310 }
9311
9312 /*******************************************************************
9313  ********************************************************************/
9314
9315 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9316                              struct spoolss_PortData1 *port1,
9317                              const DATA_BLOB *buf)
9318 {
9319         enum ndr_err_code ndr_err;
9320         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9321                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9322         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9323                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9324         }
9325         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9326 }
9327
9328 /*******************************************************************
9329  ********************************************************************/
9330
9331 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9332                              struct spoolss_PortData2 *port2,
9333                              const DATA_BLOB *buf)
9334 {
9335         enum ndr_err_code ndr_err;
9336         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9337                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9338         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9339                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9340         }
9341         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9342 }
9343
9344 /*******************************************************************
9345  Create a new TCP/IP port
9346 *******************************************************************/
9347
9348 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9349                              NT_USER_TOKEN *token, DATA_BLOB *in,
9350                              DATA_BLOB *out, uint32_t *needed)
9351 {
9352         struct spoolss_PortData1 port1;
9353         struct spoolss_PortData2 port2;
9354         char *device_uri = NULL;
9355         uint32_t version;
9356
9357         const char *portname;
9358         const char *hostaddress;
9359         const char *queue;
9360         uint32_t port_number;
9361         uint32_t protocol;
9362
9363         /* peek for spoolss_PortData version */
9364
9365         if (!in || (in->length < (128 + 4))) {
9366                 return WERR_GENERAL_FAILURE;
9367         }
9368
9369         version = IVAL(in->data, 128);
9370
9371         switch (version) {
9372                 case 1:
9373                         ZERO_STRUCT(port1);
9374
9375                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9376                                 return WERR_NOMEM;
9377                         }
9378
9379                         portname        = port1.portname;
9380                         hostaddress     = port1.hostaddress;
9381                         queue           = port1.queue;
9382                         protocol        = port1.protocol;
9383                         port_number     = port1.port_number;
9384
9385                         break;
9386                 case 2:
9387                         ZERO_STRUCT(port2);
9388
9389                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9390                                 return WERR_NOMEM;
9391                         }
9392
9393                         portname        = port2.portname;
9394                         hostaddress     = port2.hostaddress;
9395                         queue           = port2.queue;
9396                         protocol        = port2.protocol;
9397                         port_number     = port2.port_number;
9398
9399                         break;
9400                 default:
9401                         DEBUG(1,("xcvtcp_addport: "
9402                                 "unknown version of port_data: %d\n", version));
9403                         return WERR_UNKNOWN_PORT;
9404         }
9405
9406         /* create the device URI and call the add_port_hook() */
9407
9408         switch (protocol) {
9409         case PROTOCOL_RAWTCP_TYPE:
9410                 device_uri = talloc_asprintf(mem_ctx,
9411                                 "socket://%s:%d/", hostaddress,
9412                                 port_number);
9413                 break;
9414
9415         case PROTOCOL_LPR_TYPE:
9416                 device_uri = talloc_asprintf(mem_ctx,
9417                         "lpr://%s/%s", hostaddress, queue );
9418                 break;
9419
9420         default:
9421                 return WERR_UNKNOWN_PORT;
9422         }
9423
9424         if (!device_uri) {
9425                 return WERR_NOMEM;
9426         }
9427
9428         return add_port_hook(mem_ctx, token, portname, device_uri);
9429 }
9430
9431 /*******************************************************************
9432 *******************************************************************/
9433
9434 struct xcv_api_table xcvtcp_cmds[] = {
9435         { "MonitorUI",  xcvtcp_monitorui },
9436         { "AddPort",    xcvtcp_addport},
9437         { NULL,         NULL }
9438 };
9439
9440 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9441                                      NT_USER_TOKEN *token, const char *command,
9442                                      DATA_BLOB *inbuf,
9443                                      DATA_BLOB *outbuf,
9444                                      uint32_t *needed )
9445 {
9446         int i;
9447
9448         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9449
9450         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9451                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9452                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9453         }
9454
9455         return WERR_BADFUNC;
9456 }
9457
9458 /*******************************************************************
9459 *******************************************************************/
9460 #if 0   /* don't support management using the "Local Port" monitor */
9461
9462 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9463                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9464                                  DATA_BLOB *out, uint32_t *needed)
9465 {
9466         const char *dllname = "localui.dll";
9467
9468         *needed = (strlen(dllname)+1) * 2;
9469
9470         if (out->length < *needed) {
9471                 return WERR_INSUFFICIENT_BUFFER;
9472         }
9473
9474         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9475                 return WERR_NOMEM;
9476         }
9477
9478         return WERR_OK;
9479 }
9480
9481 /*******************************************************************
9482 *******************************************************************/
9483
9484 struct xcv_api_table xcvlocal_cmds[] = {
9485         { "MonitorUI",  xcvlocal_monitorui },
9486         { NULL,         NULL }
9487 };
9488 #else
9489 struct xcv_api_table xcvlocal_cmds[] = {
9490         { NULL,         NULL }
9491 };
9492 #endif
9493
9494
9495
9496 /*******************************************************************
9497 *******************************************************************/
9498
9499 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9500                                        NT_USER_TOKEN *token, const char *command,
9501                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9502                                        uint32_t *needed)
9503 {
9504         int i;
9505
9506         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9507
9508         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9509                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9510                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9511         }
9512         return WERR_BADFUNC;
9513 }
9514
9515 /****************************************************************
9516  _spoolss_XcvData
9517 ****************************************************************/
9518
9519 WERROR _spoolss_XcvData(pipes_struct *p,
9520                         struct spoolss_XcvData *r)
9521 {
9522         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9523         DATA_BLOB out_data = data_blob_null;
9524         WERROR werror;
9525
9526         if (!Printer) {
9527                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9528                         OUR_HANDLE(r->in.handle)));
9529                 return WERR_BADFID;
9530         }
9531
9532         /* Has to be a handle to the TCP/IP port monitor */
9533
9534         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9535                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9536                 return WERR_BADFID;
9537         }
9538
9539         /* requires administrative access to the server */
9540
9541         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9542                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9543                 return WERR_ACCESS_DENIED;
9544         }
9545
9546         /* Allocate the outgoing buffer */
9547
9548         if (r->in.out_data_size) {
9549                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9550                 if (out_data.data == NULL) {
9551                         return WERR_NOMEM;
9552                 }
9553         }
9554
9555         switch ( Printer->printer_type ) {
9556         case SPLHND_PORTMON_TCP:
9557                 werror = process_xcvtcp_command(p->mem_ctx,
9558                                                 p->server_info->ptok,
9559                                                 r->in.function_name,
9560                                                 &r->in.in_data, &out_data,
9561                                                 r->out.needed);
9562                 break;
9563         case SPLHND_PORTMON_LOCAL:
9564                 werror = process_xcvlocal_command(p->mem_ctx,
9565                                                   p->server_info->ptok,
9566                                                   r->in.function_name,
9567                                                   &r->in.in_data, &out_data,
9568                                                   r->out.needed);
9569                 break;
9570         default:
9571                 werror = WERR_INVALID_PRINT_MONITOR;
9572         }
9573
9574         if (!W_ERROR_IS_OK(werror)) {
9575                 return werror;
9576         }
9577
9578         *r->out.status_code = 0;
9579
9580         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9581                 memcpy(r->out.out_data, out_data.data,
9582                         MIN(r->in.out_data_size, out_data.length));
9583         }
9584
9585         return WERR_OK;
9586 }
9587
9588 /****************************************************************
9589  _spoolss_AddPrintProcessor
9590 ****************************************************************/
9591
9592 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9593                                   struct spoolss_AddPrintProcessor *r)
9594 {
9595         /* for now, just indicate success and ignore the add.  We'll
9596            automatically set the winprint processor for printer
9597            entries later.  Used to debug the LexMark Optra S 1855 PCL
9598            driver --jerry */
9599
9600         return WERR_OK;
9601 }
9602
9603 /****************************************************************
9604  _spoolss_AddPort
9605 ****************************************************************/
9606
9607 WERROR _spoolss_AddPort(pipes_struct *p,
9608                         struct spoolss_AddPort *r)
9609 {
9610         /* do what w2k3 does */
9611
9612         return WERR_NOT_SUPPORTED;
9613 }
9614
9615 /****************************************************************
9616  _spoolss_GetPrinterDriver
9617 ****************************************************************/
9618
9619 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9620                                  struct spoolss_GetPrinterDriver *r)
9621 {
9622         p->rng_fault_state = true;
9623         return WERR_NOT_SUPPORTED;
9624 }
9625
9626 /****************************************************************
9627  _spoolss_ReadPrinter
9628 ****************************************************************/
9629
9630 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9631                             struct spoolss_ReadPrinter *r)
9632 {
9633         p->rng_fault_state = true;
9634         return WERR_NOT_SUPPORTED;
9635 }
9636
9637 /****************************************************************
9638  _spoolss_WaitForPrinterChange
9639 ****************************************************************/
9640
9641 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9642                                      struct spoolss_WaitForPrinterChange *r)
9643 {
9644         p->rng_fault_state = true;
9645         return WERR_NOT_SUPPORTED;
9646 }
9647
9648 /****************************************************************
9649  _spoolss_ConfigurePort
9650 ****************************************************************/
9651
9652 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9653                               struct spoolss_ConfigurePort *r)
9654 {
9655         p->rng_fault_state = true;
9656         return WERR_NOT_SUPPORTED;
9657 }
9658
9659 /****************************************************************
9660  _spoolss_DeletePort
9661 ****************************************************************/
9662
9663 WERROR _spoolss_DeletePort(pipes_struct *p,
9664                            struct spoolss_DeletePort *r)
9665 {
9666         p->rng_fault_state = true;
9667         return WERR_NOT_SUPPORTED;
9668 }
9669
9670 /****************************************************************
9671  _spoolss_CreatePrinterIC
9672 ****************************************************************/
9673
9674 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9675                                 struct spoolss_CreatePrinterIC *r)
9676 {
9677         p->rng_fault_state = true;
9678         return WERR_NOT_SUPPORTED;
9679 }
9680
9681 /****************************************************************
9682  _spoolss_PlayGDIScriptOnPrinterIC
9683 ****************************************************************/
9684
9685 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9686                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9687 {
9688         p->rng_fault_state = true;
9689         return WERR_NOT_SUPPORTED;
9690 }
9691
9692 /****************************************************************
9693  _spoolss_DeletePrinterIC
9694 ****************************************************************/
9695
9696 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9697                                 struct spoolss_DeletePrinterIC *r)
9698 {
9699         p->rng_fault_state = true;
9700         return WERR_NOT_SUPPORTED;
9701 }
9702
9703 /****************************************************************
9704  _spoolss_AddPrinterConnection
9705 ****************************************************************/
9706
9707 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9708                                      struct spoolss_AddPrinterConnection *r)
9709 {
9710         p->rng_fault_state = true;
9711         return WERR_NOT_SUPPORTED;
9712 }
9713
9714 /****************************************************************
9715  _spoolss_DeletePrinterConnection
9716 ****************************************************************/
9717
9718 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9719                                         struct spoolss_DeletePrinterConnection *r)
9720 {
9721         p->rng_fault_state = true;
9722         return WERR_NOT_SUPPORTED;
9723 }
9724
9725 /****************************************************************
9726  _spoolss_PrinterMessageBox
9727 ****************************************************************/
9728
9729 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9730                                   struct spoolss_PrinterMessageBox *r)
9731 {
9732         p->rng_fault_state = true;
9733         return WERR_NOT_SUPPORTED;
9734 }
9735
9736 /****************************************************************
9737  _spoolss_AddMonitor
9738 ****************************************************************/
9739
9740 WERROR _spoolss_AddMonitor(pipes_struct *p,
9741                            struct spoolss_AddMonitor *r)
9742 {
9743         p->rng_fault_state = true;
9744         return WERR_NOT_SUPPORTED;
9745 }
9746
9747 /****************************************************************
9748  _spoolss_DeleteMonitor
9749 ****************************************************************/
9750
9751 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9752                               struct spoolss_DeleteMonitor *r)
9753 {
9754         p->rng_fault_state = true;
9755         return WERR_NOT_SUPPORTED;
9756 }
9757
9758 /****************************************************************
9759  _spoolss_DeletePrintProcessor
9760 ****************************************************************/
9761
9762 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9763                                      struct spoolss_DeletePrintProcessor *r)
9764 {
9765         p->rng_fault_state = true;
9766         return WERR_NOT_SUPPORTED;
9767 }
9768
9769 /****************************************************************
9770  _spoolss_AddPrintProvidor
9771 ****************************************************************/
9772
9773 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9774                                  struct spoolss_AddPrintProvidor *r)
9775 {
9776         p->rng_fault_state = true;
9777         return WERR_NOT_SUPPORTED;
9778 }
9779
9780 /****************************************************************
9781  _spoolss_DeletePrintProvidor
9782 ****************************************************************/
9783
9784 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9785                                     struct spoolss_DeletePrintProvidor *r)
9786 {
9787         p->rng_fault_state = true;
9788         return WERR_NOT_SUPPORTED;
9789 }
9790
9791 /****************************************************************
9792  _spoolss_FindFirstPrinterChangeNotification
9793 ****************************************************************/
9794
9795 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9796                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9797 {
9798         p->rng_fault_state = true;
9799         return WERR_NOT_SUPPORTED;
9800 }
9801
9802 /****************************************************************
9803  _spoolss_FindNextPrinterChangeNotification
9804 ****************************************************************/
9805
9806 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9807                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9808 {
9809         p->rng_fault_state = true;
9810         return WERR_NOT_SUPPORTED;
9811 }
9812
9813 /****************************************************************
9814  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9815 ****************************************************************/
9816
9817 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9818                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9819 {
9820         p->rng_fault_state = true;
9821         return WERR_NOT_SUPPORTED;
9822 }
9823
9824 /****************************************************************
9825  _spoolss_ReplyOpenPrinter
9826 ****************************************************************/
9827
9828 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9829                                  struct spoolss_ReplyOpenPrinter *r)
9830 {
9831         p->rng_fault_state = true;
9832         return WERR_NOT_SUPPORTED;
9833 }
9834
9835 /****************************************************************
9836  _spoolss_RouterReplyPrinter
9837 ****************************************************************/
9838
9839 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9840                                    struct spoolss_RouterReplyPrinter *r)
9841 {
9842         p->rng_fault_state = true;
9843         return WERR_NOT_SUPPORTED;
9844 }
9845
9846 /****************************************************************
9847  _spoolss_ReplyClosePrinter
9848 ****************************************************************/
9849
9850 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9851                                   struct spoolss_ReplyClosePrinter *r)
9852 {
9853         p->rng_fault_state = true;
9854         return WERR_NOT_SUPPORTED;
9855 }
9856
9857 /****************************************************************
9858  _spoolss_AddPortEx
9859 ****************************************************************/
9860
9861 WERROR _spoolss_AddPortEx(pipes_struct *p,
9862                           struct spoolss_AddPortEx *r)
9863 {
9864         p->rng_fault_state = true;
9865         return WERR_NOT_SUPPORTED;
9866 }
9867
9868 /****************************************************************
9869  _spoolss_RouterFindFirstPrinterChangeNotification
9870 ****************************************************************/
9871
9872 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9873                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9874 {
9875         p->rng_fault_state = true;
9876         return WERR_NOT_SUPPORTED;
9877 }
9878
9879 /****************************************************************
9880  _spoolss_SpoolerInit
9881 ****************************************************************/
9882
9883 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9884                             struct spoolss_SpoolerInit *r)
9885 {
9886         p->rng_fault_state = true;
9887         return WERR_NOT_SUPPORTED;
9888 }
9889
9890 /****************************************************************
9891  _spoolss_ResetPrinterEx
9892 ****************************************************************/
9893
9894 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9895                                struct spoolss_ResetPrinterEx *r)
9896 {
9897         p->rng_fault_state = true;
9898         return WERR_NOT_SUPPORTED;
9899 }
9900
9901 /****************************************************************
9902  _spoolss_RouterReplyPrinterEx
9903 ****************************************************************/
9904
9905 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9906                                      struct spoolss_RouterReplyPrinterEx *r)
9907 {
9908         p->rng_fault_state = true;
9909         return WERR_NOT_SUPPORTED;
9910 }
9911
9912 /****************************************************************
9913  _spoolss_44
9914 ****************************************************************/
9915
9916 WERROR _spoolss_44(pipes_struct *p,
9917                    struct spoolss_44 *r)
9918 {
9919         p->rng_fault_state = true;
9920         return WERR_NOT_SUPPORTED;
9921 }
9922
9923 /****************************************************************
9924  _spoolss_47
9925 ****************************************************************/
9926
9927 WERROR _spoolss_47(pipes_struct *p,
9928                    struct spoolss_47 *r)
9929 {
9930         p->rng_fault_state = true;
9931         return WERR_NOT_SUPPORTED;
9932 }
9933
9934 /****************************************************************
9935  _spoolss_4a
9936 ****************************************************************/
9937
9938 WERROR _spoolss_4a(pipes_struct *p,
9939                    struct spoolss_4a *r)
9940 {
9941         p->rng_fault_state = true;
9942         return WERR_NOT_SUPPORTED;
9943 }
9944
9945 /****************************************************************
9946  _spoolss_4b
9947 ****************************************************************/
9948
9949 WERROR _spoolss_4b(pipes_struct *p,
9950                    struct spoolss_4b *r)
9951 {
9952         p->rng_fault_state = true;
9953         return WERR_NOT_SUPPORTED;
9954 }
9955
9956 /****************************************************************
9957  _spoolss_4c
9958 ****************************************************************/
9959
9960 WERROR _spoolss_4c(pipes_struct *p,
9961                    struct spoolss_4c *r)
9962 {
9963         p->rng_fault_state = true;
9964         return WERR_NOT_SUPPORTED;
9965 }
9966
9967 /****************************************************************
9968  _spoolss_53
9969 ****************************************************************/
9970
9971 WERROR _spoolss_53(pipes_struct *p,
9972                    struct spoolss_53 *r)
9973 {
9974         p->rng_fault_state = true;
9975         return WERR_NOT_SUPPORTED;
9976 }
9977
9978 /****************************************************************
9979  _spoolss_55
9980 ****************************************************************/
9981
9982 WERROR _spoolss_55(pipes_struct *p,
9983                    struct spoolss_55 *r)
9984 {
9985         p->rng_fault_state = true;
9986         return WERR_NOT_SUPPORTED;
9987 }
9988
9989 /****************************************************************
9990  _spoolss_56
9991 ****************************************************************/
9992
9993 WERROR _spoolss_56(pipes_struct *p,
9994                    struct spoolss_56 *r)
9995 {
9996         p->rng_fault_state = true;
9997         return WERR_NOT_SUPPORTED;
9998 }
9999
10000 /****************************************************************
10001  _spoolss_57
10002 ****************************************************************/
10003
10004 WERROR _spoolss_57(pipes_struct *p,
10005                    struct spoolss_57 *r)
10006 {
10007         p->rng_fault_state = true;
10008         return WERR_NOT_SUPPORTED;
10009 }
10010
10011 /****************************************************************
10012  _spoolss_5a
10013 ****************************************************************/
10014
10015 WERROR _spoolss_5a(pipes_struct *p,
10016                    struct spoolss_5a *r)
10017 {
10018         p->rng_fault_state = true;
10019         return WERR_NOT_SUPPORTED;
10020 }
10021
10022 /****************************************************************
10023  _spoolss_5b
10024 ****************************************************************/
10025
10026 WERROR _spoolss_5b(pipes_struct *p,
10027                    struct spoolss_5b *r)
10028 {
10029         p->rng_fault_state = true;
10030         return WERR_NOT_SUPPORTED;
10031 }
10032
10033 /****************************************************************
10034  _spoolss_5c
10035 ****************************************************************/
10036
10037 WERROR _spoolss_5c(pipes_struct *p,
10038                    struct spoolss_5c *r)
10039 {
10040         p->rng_fault_state = true;
10041         return WERR_NOT_SUPPORTED;
10042 }
10043
10044 /****************************************************************
10045  _spoolss_5d
10046 ****************************************************************/
10047
10048 WERROR _spoolss_5d(pipes_struct *p,
10049                    struct spoolss_5d *r)
10050 {
10051         p->rng_fault_state = true;
10052         return WERR_NOT_SUPPORTED;
10053 }
10054
10055 /****************************************************************
10056  _spoolss_5e
10057 ****************************************************************/
10058
10059 WERROR _spoolss_5e(pipes_struct *p,
10060                    struct spoolss_5e *r)
10061 {
10062         p->rng_fault_state = true;
10063         return WERR_NOT_SUPPORTED;
10064 }
10065
10066 /****************************************************************
10067  _spoolss_5f
10068 ****************************************************************/
10069
10070 WERROR _spoolss_5f(pipes_struct *p,
10071                    struct spoolss_5f *r)
10072 {
10073         p->rng_fault_state = true;
10074         return WERR_NOT_SUPPORTED;
10075 }
10076
10077 /****************************************************************
10078  _spoolss_60
10079 ****************************************************************/
10080
10081 WERROR _spoolss_60(pipes_struct *p,
10082                    struct spoolss_60 *r)
10083 {
10084         p->rng_fault_state = true;
10085         return WERR_NOT_SUPPORTED;
10086 }
10087
10088 /****************************************************************
10089  _spoolss_61
10090 ****************************************************************/
10091
10092 WERROR _spoolss_61(pipes_struct *p,
10093                    struct spoolss_61 *r)
10094 {
10095         p->rng_fault_state = true;
10096         return WERR_NOT_SUPPORTED;
10097 }
10098
10099 /****************************************************************
10100  _spoolss_62
10101 ****************************************************************/
10102
10103 WERROR _spoolss_62(pipes_struct *p,
10104                    struct spoolss_62 *r)
10105 {
10106         p->rng_fault_state = true;
10107         return WERR_NOT_SUPPORTED;
10108 }
10109
10110 /****************************************************************
10111  _spoolss_63
10112 ****************************************************************/
10113
10114 WERROR _spoolss_63(pipes_struct *p,
10115                    struct spoolss_63 *r)
10116 {
10117         p->rng_fault_state = true;
10118         return WERR_NOT_SUPPORTED;
10119 }
10120
10121 /****************************************************************
10122  _spoolss_64
10123 ****************************************************************/
10124
10125 WERROR _spoolss_64(pipes_struct *p,
10126                    struct spoolss_64 *r)
10127 {
10128         p->rng_fault_state = true;
10129         return WERR_NOT_SUPPORTED;
10130 }
10131
10132 /****************************************************************
10133  _spoolss_65
10134 ****************************************************************/
10135
10136 WERROR _spoolss_65(pipes_struct *p,
10137                    struct spoolss_65 *r)
10138 {
10139         p->rng_fault_state = true;
10140         return WERR_NOT_SUPPORTED;
10141 }
10142
10143 /****************************************************************
10144  _spoolss_GetCorePrinterDrivers
10145 ****************************************************************/
10146
10147 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10148                                       struct spoolss_GetCorePrinterDrivers *r)
10149 {
10150         p->rng_fault_state = true;
10151         return WERR_NOT_SUPPORTED;
10152 }
10153
10154 /****************************************************************
10155  _spoolss_67
10156 ****************************************************************/
10157
10158 WERROR _spoolss_67(pipes_struct *p,
10159                    struct spoolss_67 *r)
10160 {
10161         p->rng_fault_state = true;
10162         return WERR_NOT_SUPPORTED;
10163 }
10164
10165 /****************************************************************
10166  _spoolss_GetPrinterDriverPackagePath
10167 ****************************************************************/
10168
10169 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10170                                             struct spoolss_GetPrinterDriverPackagePath *r)
10171 {
10172         p->rng_fault_state = true;
10173         return WERR_NOT_SUPPORTED;
10174 }
10175
10176 /****************************************************************
10177  _spoolss_69
10178 ****************************************************************/
10179
10180 WERROR _spoolss_69(pipes_struct *p,
10181                    struct spoolss_69 *r)
10182 {
10183         p->rng_fault_state = true;
10184         return WERR_NOT_SUPPORTED;
10185 }
10186
10187 /****************************************************************
10188  _spoolss_6a
10189 ****************************************************************/
10190
10191 WERROR _spoolss_6a(pipes_struct *p,
10192                    struct spoolss_6a *r)
10193 {
10194         p->rng_fault_state = true;
10195         return WERR_NOT_SUPPORTED;
10196 }
10197
10198 /****************************************************************
10199  _spoolss_6b
10200 ****************************************************************/
10201
10202 WERROR _spoolss_6b(pipes_struct *p,
10203                    struct spoolss_6b *r)
10204 {
10205         p->rng_fault_state = true;
10206         return WERR_NOT_SUPPORTED;
10207 }
10208
10209 /****************************************************************
10210  _spoolss_6c
10211 ****************************************************************/
10212
10213 WERROR _spoolss_6c(pipes_struct *p,
10214                    struct spoolss_6c *r)
10215 {
10216         p->rng_fault_state = true;
10217         return WERR_NOT_SUPPORTED;
10218 }
10219
10220 /****************************************************************
10221  _spoolss_6d
10222 ****************************************************************/
10223
10224 WERROR _spoolss_6d(pipes_struct *p,
10225                    struct spoolss_6d *r)
10226 {
10227         p->rng_fault_state = true;
10228         return WERR_NOT_SUPPORTED;
10229 }