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