s3-spoolss: add support for SetJobInfo level 1 (for jobfile rename).
[amitay/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35         ((info)?ndr_size_##fn(info, level, ic, 0):0)
36
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
39
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
42
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44
45
46 extern userdom_struct current_user_info;
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_RPC_SRV
50
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
53 #endif
54
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32_t counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected == true) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected = false;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231                                                 struct policy_handle *hnd)
232 {
233         Printer_entry *find_printer = NULL;
234
235         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
237                 return NULL;
238         }
239
240         return find_printer;
241 }
242
243 /****************************************************************************
244  Close printer index by handle.
245 ****************************************************************************/
246
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
248 {
249         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250
251         if (!Printer) {
252                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
253                         OUR_HANDLE(hnd)));
254                 return false;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return true;
260 }
261
262 /****************************************************************************
263  Delete a printer given a handle.
264 ****************************************************************************/
265
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
267 {
268         char *cmd = lp_deleteprinter_cmd();
269         char *command = NULL;
270         int ret;
271         SE_PRIV se_printop = SE_PRINT_OPERATOR;
272         bool is_print_op = false;
273
274         /* can't fail if we don't try */
275
276         if ( !*cmd )
277                 return WERR_OK;
278
279         command = talloc_asprintf(ctx,
280                         "%s \"%s\"",
281                         cmd, sharename);
282         if (!command) {
283                 return WERR_NOMEM;
284         }
285         if ( token )
286                 is_print_op = user_has_privileges( token, &se_printop );
287
288         DEBUG(10,("Running [%s]\n", command));
289
290         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
291
292         if ( is_print_op )
293                 become_root();
294
295         if ( (ret = smbrun(command, NULL)) == 0 ) {
296                 /* Tell everyone we updated smb.conf. */
297                 message_send_all(smbd_messaging_context(),
298                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299         }
300
301         if ( is_print_op )
302                 unbecome_root();
303
304         /********** END SePrintOperatorPrivlege BLOCK **********/
305
306         DEBUGADD(10,("returned [%d]\n", ret));
307
308         TALLOC_FREE(command);
309
310         if (ret != 0)
311                 return WERR_BADFID; /* What to return here? */
312
313         /* go ahead and re-read the services immediately */
314         become_root();
315         reload_services(false);
316         unbecome_root();
317
318         if ( lp_servicenumber( sharename )  > 0 )
319                 return WERR_ACCESS_DENIED;
320
321         return WERR_OK;
322 }
323
324 /****************************************************************************
325  Delete a printer given a handle.
326 ****************************************************************************/
327
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
329 {
330         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331
332         if (!Printer) {
333                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
334                         OUR_HANDLE(hnd)));
335                 return WERR_BADFID;
336         }
337
338         /*
339          * It turns out that Windows allows delete printer on a handle
340          * opened by an admin user, then used on a pipe handle created
341          * by an anonymous user..... but they're working on security.... riiight !
342          * JRA.
343          */
344
345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347                 return WERR_ACCESS_DENIED;
348         }
349
350         /* this does not need a become root since the access check has been
351            done on the handle already */
352
353         if (del_a_printer( Printer->sharename ) != 0) {
354                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
355                 return WERR_BADFID;
356         }
357
358         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359                                    Printer->sharename );
360 }
361
362 /****************************************************************************
363  Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
365
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367                              int *number, struct share_params **params)
368 {
369         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370
371         if (!Printer) {
372                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
373                         OUR_HANDLE(hnd)));
374                 return false;
375         }
376
377         switch (Printer->printer_type) {
378                 case SPLHND_PRINTER:
379                         DEBUG(4,("short name:%s\n", Printer->sharename));
380                         *number = print_queue_snum(Printer->sharename);
381                         return (*number != -1);
382                 case SPLHND_SERVER:
383                         return false;
384                 default:
385                         return false;
386         }
387 }
388
389 /****************************************************************************
390  Set printer handle type.
391  Check if it's \\server or \\server\printer
392 ****************************************************************************/
393
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
395 {
396         DEBUG(3,("Setting printer type=%s\n", handlename));
397
398         if ( strlen(handlename) < 3 ) {
399                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
400                 return false;
401         }
402
403         /* it's a print server */
404         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405                 DEBUGADD(4,("Printer is a print server\n"));
406                 Printer->printer_type = SPLHND_SERVER;
407         }
408         /* it's a printer (set_printer_hnd_name() will handle port monitors */
409         else {
410                 DEBUGADD(4,("Printer is a printer\n"));
411                 Printer->printer_type = SPLHND_PRINTER;
412         }
413
414         return true;
415 }
416
417 /****************************************************************************
418  Set printer handle name..  Accept names like \\server, \\server\printer,
419  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
420  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421  XcvDataPort() interface.
422 ****************************************************************************/
423
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 {
426         int snum;
427         int n_services=lp_numservices();
428         char *aprinter, *printername;
429         const char *servername;
430         fstring sname;
431         bool found = false;
432         NT_PRINTER_INFO_LEVEL *printer = NULL;
433         WERROR result;
434
435         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436                 (unsigned long)strlen(handlename)));
437
438         aprinter = CONST_DISCARD(char *, handlename);
439         if ( *handlename == '\\' ) {
440                 servername = canon_servername(handlename);
441                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
442                         *aprinter = '\0';
443                         aprinter++;
444                 }
445         } else {
446                 servername = global_myname();
447         }
448
449         /* save the servername to fill in replies on this handle */
450
451         if ( !is_myname_or_ipaddr( servername ) )
452                 return false;
453
454         fstrcpy( Printer->servername, servername );
455
456         if ( Printer->printer_type == SPLHND_SERVER )
457                 return true;
458
459         if ( Printer->printer_type != SPLHND_PRINTER )
460                 return false;
461
462         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
463
464         /* check for the Port Monitor Interface */
465
466         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467                 Printer->printer_type = SPLHND_PORTMON_TCP;
468                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469                 found = true;
470         }
471         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474                 found = true;
475         }
476
477         /* Search all sharenames first as this is easier than pulling
478            the printer_info_2 off of disk. Don't use find_service() since
479            that calls out to map_username() */
480
481         /* do another loop to look for printernames */
482
483         for (snum=0; !found && snum<n_services; snum++) {
484
485                 /* no point going on if this is not a printer */
486
487                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488                         continue;
489
490                 fstrcpy(sname, lp_servicename(snum));
491                 if ( strequal( aprinter, sname ) ) {
492                         found = true;
493                         break;
494                 }
495
496                 /* no point looking up the printer object if
497                    we aren't allowing printername != sharename */
498
499                 if ( lp_force_printername(snum) )
500                         continue;
501
502                 fstrcpy(sname, lp_servicename(snum));
503
504                 printer = NULL;
505
506                 /* This call doesn't fill in the location or comment from
507                  * a CUPS server for efficiency with large numbers of printers.
508                  * JRA.
509                  */
510
511                 result = get_a_printer_search( NULL, &printer, 2, sname );
512                 if ( !W_ERROR_IS_OK(result) ) {
513                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514                                 sname, win_errstr(result)));
515                         continue;
516                 }
517
518                 /* printername is always returned as \\server\printername */
519                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521                                 printer->info_2->printername));
522                         free_a_printer( &printer, 2);
523                         continue;
524                 }
525
526                 printername++;
527
528                 if ( strequal(printername, aprinter) ) {
529                         free_a_printer( &printer, 2);
530                         found = true;
531                         break;
532                 }
533
534                 DEBUGADD(10, ("printername: %s\n", printername));
535
536                 free_a_printer( &printer, 2);
537         }
538
539         free_a_printer( &printer, 2);
540
541         if ( !found ) {
542                 DEBUGADD(4,("Printer not found\n"));
543                 return false;
544         }
545
546         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
547
548         fstrcpy(Printer->sharename, sname);
549
550         return true;
551 }
552
553 /****************************************************************************
554  Find first available printer slot. creates a printer handle for you.
555  ****************************************************************************/
556
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558                              const char *name, uint32_t access_granted)
559 {
560         Printer_entry *new_printer;
561
562         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
563
564         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565         if (new_printer == NULL) {
566                 return false;
567         }
568         talloc_set_destructor(new_printer, printer_entry_destructor);
569
570         if (!create_policy_hnd(p, hnd, new_printer)) {
571                 TALLOC_FREE(new_printer);
572                 return false;
573         }
574
575         /* Add to the internal list. */
576         DLIST_ADD(printers_list, new_printer);
577
578         new_printer->notify.option=NULL;
579
580         if (!set_printer_hnd_printertype(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return false;
583         }
584
585         if (!set_printer_hnd_name(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         new_printer->access_granted = access_granted;
591
592         DEBUG(5, ("%d printer handles active\n",
593                   (int)num_pipe_handles(p->pipe_handles)));
594
595         return true;
596 }
597
598 /***************************************************************************
599  check to see if the client motify handle is monitoring the notification
600  given by (notify_type, notify_field).
601  **************************************************************************/
602
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604                                       uint16_t notify_field)
605 {
606         return true;
607 }
608
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610                                 uint16_t notify_field)
611 {
612         struct spoolss_NotifyOption *option = p->notify.option;
613         uint32_t i, j;
614
615         /*
616          * Flags should always be zero when the change notify
617          * is registered by the client's spooler.  A user Win32 app
618          * might use the flags though instead of the NOTIFY_OPTION_INFO
619          * --jerry
620          */
621
622         if (!option) {
623                 return false;
624         }
625
626         if (p->notify.flags)
627                 return is_monitoring_event_flags(
628                         p->notify.flags, notify_type, notify_field);
629
630         for (i = 0; i < option->count; i++) {
631
632                 /* Check match for notify_type */
633
634                 if (option->types[i].type != notify_type)
635                         continue;
636
637                 /* Check match for field */
638
639                 for (j = 0; j < option->types[i].count; j++) {
640                         if (option->types[i].fields[j].field == notify_field) {
641                                 return true;
642                         }
643                 }
644         }
645
646         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647                    p->servername, p->sharename, notify_type, notify_field));
648
649         return false;
650 }
651
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653         _data->data.integer[0] = _integer; \
654         _data->data.integer[1] = 0;
655
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659         if (!_data->data.string.string) {\
660                 _data->data.string.size = 0; \
661         } \
662         _data->data.string.size = strlen_m_term(_p) * 2;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665         _data->data.devmode.devmode = _devmode;
666
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669         if (!_data->data.sd.sd) { \
670                 _data->data.sd.sd_size = 0; \
671         } \
672         _data->data.sd.sd_size = _size;
673
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
675                                    struct tm *t,
676                                    const char **pp,
677                                    uint32_t *plen)
678 {
679         struct spoolss_Time st;
680         uint32_t len = 16;
681         char *p;
682
683         if (!init_systemtime(&st, t)) {
684                 return;
685         }
686
687         p = talloc_array(mem_ctx, char, len);
688         if (!p) {
689                 return;
690         }
691
692         /*
693          * Systemtime must be linearized as a set of UINT16's.
694          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695          */
696
697         SSVAL(p, 0, st.year);
698         SSVAL(p, 2, st.month);
699         SSVAL(p, 4, st.day_of_week);
700         SSVAL(p, 6, st.day);
701         SSVAL(p, 8, st.hour);
702         SSVAL(p, 10, st.minute);
703         SSVAL(p, 12, st.second);
704         SSVAL(p, 14, st.millisecond);
705
706         *pp = p;
707         *plen = len;
708 }
709
710 /* Convert a notification message to a struct spoolss_Notify */
711
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713                              struct spoolss_Notify *data,
714                              TALLOC_CTX *mem_ctx)
715 {
716         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 }
718
719 static void notify_string(struct spoolss_notify_msg *msg,
720                           struct spoolss_Notify *data,
721                           TALLOC_CTX *mem_ctx)
722 {
723         /* The length of the message includes the trailing \0 */
724
725         data->data.string.size = msg->len * 2;
726         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727         if (!data->data.string.string) {
728                 data->data.string.size = 0;
729                 return;
730         }
731 }
732
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734                                struct spoolss_Notify *data,
735                                TALLOC_CTX *mem_ctx)
736 {
737         data->data.string.string = NULL;
738         data->data.string.size = 0;
739
740         if (msg->len != sizeof(time_t)) {
741                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
742                           msg->len));
743                 return;
744         }
745
746         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747                                &data->data.string.string,
748                                &data->data.string.size);
749 }
750
751 struct notify2_message_table {
752         const char *name;
753         void (*fn)(struct spoolss_notify_msg *msg,
754                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 };
756
757 static struct notify2_message_table printer_notify_table[] = {
758         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 };
778
779 static struct notify2_message_table job_notify_table[] = {
780         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 };
805
806
807 /***********************************************************************
808  Allocate talloc context for container object
809  **********************************************************************/
810
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 {
813         if ( !ctr )
814                 return;
815
816         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817
818         return;
819 }
820
821 /***********************************************************************
822  release all allocated memory and zero out structure
823  **********************************************************************/
824
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 {
827         if ( !ctr )
828                 return;
829
830         if ( ctr->ctx )
831                 talloc_destroy(ctr->ctx);
832
833         ZERO_STRUCTP(ctr);
834
835         return;
836 }
837
838 /***********************************************************************
839  **********************************************************************/
840
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 {
843         if ( !ctr )
844                 return NULL;
845
846         return ctr->ctx;
847 }
848
849 /***********************************************************************
850  **********************************************************************/
851
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
853 {
854         if ( !ctr || !ctr->msg_groups )
855                 return NULL;
856
857         if ( idx >= ctr->num_groups )
858                 return NULL;
859
860         return &ctr->msg_groups[idx];
861
862 }
863
864 /***********************************************************************
865  How many groups of change messages do we have ?
866  **********************************************************************/
867
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 {
870         if ( !ctr )
871                 return 0;
872
873         return ctr->num_groups;
874 }
875
876 /***********************************************************************
877  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878  **********************************************************************/
879
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 {
882         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
883         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
884         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
885         int                             i, new_slot;
886
887         if ( !ctr || !msg )
888                 return 0;
889
890         /* loop over all groups looking for a matching printer name */
891
892         for ( i=0; i<ctr->num_groups; i++ ) {
893                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894                         break;
895         }
896
897         /* add a new group? */
898
899         if ( i == ctr->num_groups ) {
900                 ctr->num_groups++;
901
902                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904                         return 0;
905                 }
906                 ctr->msg_groups = groups;
907
908                 /* clear the new entry and set the printer name */
909
910                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912         }
913
914         /* add the change messages; 'i' is the correct index now regardless */
915
916         msg_grp = &ctr->msg_groups[i];
917
918         msg_grp->num_msgs++;
919
920         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922                 return 0;
923         }
924         msg_grp->msgs = msg_list;
925
926         new_slot = msg_grp->num_msgs-1;
927         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928
929         /* need to allocate own copy of data */
930
931         if ( msg->len != 0 )
932                 msg_grp->msgs[new_slot].notify.data = (char *)
933                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934
935         return ctr->num_groups;
936 }
937
938 /***********************************************************************
939  Send a change notication message on all handles which have a call
940  back registered
941  **********************************************************************/
942
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 {
945         Printer_entry            *p;
946         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
947         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948         SPOOLSS_NOTIFY_MSG       *messages;
949         int                      sending_msg_count;
950
951         if ( !msg_group ) {
952                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953                 return;
954         }
955
956         messages = msg_group->msgs;
957
958         if ( !messages ) {
959                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960                 return;
961         }
962
963         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964
965         /* loop over all printers */
966
967         for (p = printers_list; p; p = p->next) {
968                 struct spoolss_Notify *notifies;
969                 uint32_t count = 0;
970                 uint32_t id;
971                 int     i;
972
973                 /* Is there notification on this handle? */
974
975                 if ( !p->notify.client_connected )
976                         continue;
977
978                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979
980                 /* For this printer?  Print servers always receive
981                    notifications. */
982
983                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
984                     ( !strequal(msg_group->printername, p->sharename) ) )
985                         continue;
986
987                 DEBUG(10,("Our printer\n"));
988
989                 /* allocate the max entries possible */
990
991                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
992                 if (!notifies) {
993                         return;
994                 }
995
996                 /* build the array of change notifications */
997
998                 sending_msg_count = 0;
999
1000                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1002
1003                         /* Are we monitoring this event? */
1004
1005                         if (!is_monitoring_event(p, msg->type, msg->field))
1006                                 continue;
1007
1008                         sending_msg_count++;
1009
1010
1011                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012                                 msg->type, msg->field, p->sharename));
1013
1014                         /*
1015                          * if the is a printer notification handle and not a job notification
1016                          * type, then set the id to 0.  Other wise just use what was specified
1017                          * in the message.
1018                          *
1019                          * When registering change notification on a print server handle
1020                          * we always need to send back the id (snum) matching the printer
1021                          * for which the change took place.  For change notify registered
1022                          * on a printer handle, this does not matter and the id should be 0.
1023                          *
1024                          * --jerry
1025                          */
1026
1027                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028                                 id = 0;
1029                         else
1030                                 id = msg->id;
1031
1032
1033                         /* Convert unix jobid to smb jobid */
1034
1035                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036                                 id = sysjob_to_jobid(msg->id);
1037
1038                                 if (id == -1) {
1039                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040                                         goto done;
1041                                 }
1042                         }
1043
1044                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1045
1046                         switch(msg->type) {
1047                         case PRINTER_NOTIFY_TYPE:
1048                                 if ( printer_notify_table[msg->field].fn )
1049                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1050                                 break;
1051
1052                         case JOB_NOTIFY_TYPE:
1053                                 if ( job_notify_table[msg->field].fn )
1054                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1055                                 break;
1056
1057                         default:
1058                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059                                 goto done;
1060                         }
1061
1062                         count++;
1063                 }
1064
1065                 if ( sending_msg_count ) {
1066                         NTSTATUS status;
1067                         WERROR werr;
1068                         union spoolss_ReplyPrinterInfo info;
1069                         struct spoolss_NotifyInfo info0;
1070                         uint32_t reply_result;
1071
1072                         info0.version   = 0x2;
1073                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074                         info0.count     = count;
1075                         info0.notifies  = notifies;
1076
1077                         info.info0 = &info0;
1078
1079                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080                                                                      &p->notify.client_hnd,
1081                                                                      p->notify.change, /* color */
1082                                                                      p->notify.flags,
1083                                                                      &reply_result,
1084                                                                      0, /* reply_type, must be 0 */
1085                                                                      info,
1086                                                                      &werr);
1087                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089                                         notify_cli_pipe->srv_name_slash,
1090                                         win_errstr(werr)));
1091                         }
1092                         switch (reply_result) {
1093                                 case 0:
1094                                         break;
1095                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1096                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1098                                         break;
1099                                 default:
1100                                         break;
1101                         }
1102                 }
1103         }
1104
1105 done:
1106         DEBUG(8,("send_notify2_changes: Exit...\n"));
1107         return;
1108 }
1109
1110 /***********************************************************************
1111  **********************************************************************/
1112
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 {
1115
1116         uint32_t tv_sec, tv_usec;
1117         size_t offset = 0;
1118
1119         /* Unpack message */
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122                              msg->printer);
1123
1124         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1125                                 &tv_sec, &tv_usec,
1126                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127
1128         if (msg->len == 0)
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130                            &msg->notify.value[0], &msg->notify.value[1]);
1131         else
1132                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133                            &msg->len, &msg->notify.data);
1134
1135         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1137
1138         tv->tv_sec = tv_sec;
1139         tv->tv_usec = tv_usec;
1140
1141         if (msg->len == 0)
1142                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143                           msg->notify.value[1]));
1144         else
1145                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1146
1147         return true;
1148 }
1149
1150 /********************************************************************
1151  Receive a notify2 message list
1152  ********************************************************************/
1153
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1155                                          void *private_data,
1156                                          uint32_t msg_type,
1157                                          struct server_id server_id,
1158                                          DATA_BLOB *data)
1159 {
1160         size_t                  msg_count, i;
1161         char                    *buf = (char *)data->data;
1162         char                    *msg_ptr;
1163         size_t                  msg_len;
1164         SPOOLSS_NOTIFY_MSG      notify;
1165         SPOOLSS_NOTIFY_MSG_CTR  messages;
1166         int                     num_groups;
1167
1168         if (data->length < 4) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170                 return;
1171         }
1172
1173         msg_count = IVAL(buf, 0);
1174         msg_ptr = buf + 4;
1175
1176         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1177
1178         if (msg_count == 0) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180                 return;
1181         }
1182
1183         /* initialize the container */
1184
1185         ZERO_STRUCT( messages );
1186         notify_msg_ctr_init( &messages );
1187
1188         /*
1189          * build message groups for each printer identified
1190          * in a change_notify msg.  Remember that a PCN message
1191          * includes the handle returned for the srv_spoolss_replyopenprinter()
1192          * call.  Therefore messages are grouped according to printer handle.
1193          */
1194
1195         for ( i=0; i<msg_count; i++ ) {
1196                 struct timeval msg_tv;
1197
1198                 if (msg_ptr + 4 - buf > data->length) {
1199                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200                         return;
1201                 }
1202
1203                 msg_len = IVAL(msg_ptr,0);
1204                 msg_ptr += 4;
1205
1206                 if (msg_ptr + msg_len - buf > data->length) {
1207                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208                         return;
1209                 }
1210
1211                 /* unpack messages */
1212
1213                 ZERO_STRUCT( notify );
1214                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215                 msg_ptr += msg_len;
1216
1217                 /* add to correct list in container */
1218
1219                 notify_msg_ctr_addmsg( &messages, &notify );
1220
1221                 /* free memory that might have been allocated by notify2_unpack_msg() */
1222
1223                 if ( notify.len != 0 )
1224                         SAFE_FREE( notify.notify.data );
1225         }
1226
1227         /* process each group of messages */
1228
1229         num_groups = notify_msg_ctr_numgroups( &messages );
1230         for ( i=0; i<num_groups; i++ )
1231                 send_notify2_changes( &messages, i );
1232
1233
1234         /* cleanup */
1235
1236         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237                 (uint32_t)msg_count ));
1238
1239         notify_msg_ctr_destroy( &messages );
1240
1241         return;
1242 }
1243
1244 /********************************************************************
1245  Send a message to ourself about new driver being installed
1246  so we can upgrade the information for each printer bound to this
1247  driver
1248  ********************************************************************/
1249
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1251 {
1252         int len = strlen(drivername);
1253
1254         if (!len)
1255                 return false;
1256
1257         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258                 drivername));
1259
1260         messaging_send_buf(smbd_messaging_context(), procid_self(),
1261                            MSG_PRINTER_DRVUPGRADE,
1262                            (uint8_t *)drivername, len+1);
1263
1264         return true;
1265 }
1266
1267 /**********************************************************************
1268  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269  over all printers, upgrading ones as necessary
1270  **********************************************************************/
1271
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1273                             void *private_data,
1274                             uint32_t msg_type,
1275                             struct server_id server_id,
1276                             DATA_BLOB *data)
1277 {
1278         fstring drivername;
1279         int snum;
1280         int n_services = lp_numservices();
1281         size_t len;
1282
1283         len = MIN(data->length,sizeof(drivername)-1);
1284         strncpy(drivername, (const char *)data->data, len);
1285
1286         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287
1288         /* Iterate the printer list */
1289
1290         for (snum=0; snum<n_services; snum++)
1291         {
1292                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293                 {
1294                         WERROR result;
1295                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1296
1297                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298                         if (!W_ERROR_IS_OK(result))
1299                                 continue;
1300
1301                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302                         {
1303                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304
1305                                 /* all we care about currently is the change_id */
1306
1307                                 result = mod_a_printer(printer, 2);
1308                                 if (!W_ERROR_IS_OK(result)) {
1309                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310                                                 win_errstr(result)));
1311                                 }
1312                         }
1313
1314                         free_a_printer(&printer, 2);
1315                 }
1316         }
1317
1318         /* all done */
1319 }
1320
1321 /********************************************************************
1322  Update the cache for all printq's with a registered client
1323  connection
1324  ********************************************************************/
1325
1326 void update_monitored_printq_cache( void )
1327 {
1328         Printer_entry *printer = printers_list;
1329         int snum;
1330
1331         /* loop through all printers and update the cache where
1332            client_connected == true */
1333         while ( printer )
1334         {
1335                 if ( (printer->printer_type == SPLHND_PRINTER)
1336                         && printer->notify.client_connected )
1337                 {
1338                         snum = print_queue_snum(printer->sharename);
1339                         print_queue_status( snum, NULL, NULL );
1340                 }
1341
1342                 printer = printer->next;
1343         }
1344
1345         return;
1346 }
1347 /********************************************************************
1348  Send a message to ourself about new driver being installed
1349  so we can upgrade the information for each printer bound to this
1350  driver
1351  ********************************************************************/
1352
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 {
1355         int len = strlen(drivername);
1356
1357         if (!len)
1358                 return false;
1359
1360         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361                 drivername));
1362
1363         messaging_send_buf(smbd_messaging_context(), procid_self(),
1364                            MSG_PRINTERDATA_INIT_RESET,
1365                            (uint8_t *)drivername, len+1);
1366
1367         return true;
1368 }
1369
1370 /**********************************************************************
1371  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372  over all printers, resetting printer data as neessary
1373  **********************************************************************/
1374
1375 void reset_all_printerdata(struct messaging_context *msg,
1376                            void *private_data,
1377                            uint32_t msg_type,
1378                            struct server_id server_id,
1379                            DATA_BLOB *data)
1380 {
1381         fstring drivername;
1382         int snum;
1383         int n_services = lp_numservices();
1384         size_t len;
1385
1386         len = MIN( data->length, sizeof(drivername)-1 );
1387         strncpy( drivername, (const char *)data->data, len );
1388
1389         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390
1391         /* Iterate the printer list */
1392
1393         for ( snum=0; snum<n_services; snum++ )
1394         {
1395                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396                 {
1397                         WERROR result;
1398                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1399
1400                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401                         if ( !W_ERROR_IS_OK(result) )
1402                                 continue;
1403
1404                         /*
1405                          * if the printer is bound to the driver,
1406                          * then reset to the new driver initdata
1407                          */
1408
1409                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410                         {
1411                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412
1413                                 if ( !set_driver_init(printer, 2) ) {
1414                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415                                                 printer->info_2->printername, printer->info_2->drivername));
1416                                 }
1417
1418                                 result = mod_a_printer( printer, 2 );
1419                                 if ( !W_ERROR_IS_OK(result) ) {
1420                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1421                                                 get_dos_error_msg(result)));
1422                                 }
1423                         }
1424
1425                         free_a_printer( &printer, 2 );
1426                 }
1427         }
1428
1429         /* all done */
1430
1431         return;
1432 }
1433
1434 /****************************************************************
1435  _spoolss_OpenPrinter
1436 ****************************************************************/
1437
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439                             struct spoolss_OpenPrinter *r)
1440 {
1441         struct spoolss_OpenPrinterEx e;
1442         WERROR werr;
1443
1444         ZERO_STRUCT(e.in.userlevel);
1445
1446         e.in.printername        = r->in.printername;
1447         e.in.datatype           = r->in.datatype;
1448         e.in.devmode_ctr        = r->in.devmode_ctr;
1449         e.in.access_mask        = r->in.access_mask;
1450         e.in.level              = 0;
1451
1452         e.out.handle            = r->out.handle;
1453
1454         werr = _spoolss_OpenPrinterEx(p, &e);
1455
1456         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457                 /* OpenPrinterEx returns this for a bad
1458                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1459                  * instead.
1460                  */
1461                 werr = WERR_INVALID_PRINTER_NAME;
1462         }
1463
1464         return werr;
1465 }
1466
1467 /********************************************************************
1468  ********************************************************************/
1469
1470 bool convert_devicemode(const char *printername,
1471                         const struct spoolss_DeviceMode *devmode,
1472                         NT_DEVICEMODE **pp_nt_devmode)
1473 {
1474         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475
1476         /*
1477          * Ensure nt_devmode is a valid pointer
1478          * as we will be overwriting it.
1479          */
1480
1481         if (nt_devmode == NULL) {
1482                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484                         return false;
1485         }
1486
1487         fstrcpy(nt_devmode->devicename, devmode->devicename);
1488         fstrcpy(nt_devmode->formname, devmode->formname);
1489
1490         nt_devmode->devicename[31] = '\0';
1491         nt_devmode->formname[31] = '\0';
1492
1493         nt_devmode->specversion         = devmode->specversion;
1494         nt_devmode->driverversion       = devmode->driverversion;
1495         nt_devmode->size                = devmode->size;
1496         nt_devmode->fields              = devmode->fields;
1497         nt_devmode->orientation         = devmode->orientation;
1498         nt_devmode->papersize           = devmode->papersize;
1499         nt_devmode->paperlength         = devmode->paperlength;
1500         nt_devmode->paperwidth          = devmode->paperwidth;
1501         nt_devmode->scale               = devmode->scale;
1502         nt_devmode->copies              = devmode->copies;
1503         nt_devmode->defaultsource       = devmode->defaultsource;
1504         nt_devmode->printquality        = devmode->printquality;
1505         nt_devmode->color               = devmode->color;
1506         nt_devmode->duplex              = devmode->duplex;
1507         nt_devmode->yresolution         = devmode->yresolution;
1508         nt_devmode->ttoption            = devmode->ttoption;
1509         nt_devmode->collate             = devmode->collate;
1510
1511         nt_devmode->logpixels           = devmode->logpixels;
1512         nt_devmode->bitsperpel          = devmode->bitsperpel;
1513         nt_devmode->pelswidth           = devmode->pelswidth;
1514         nt_devmode->pelsheight          = devmode->pelsheight;
1515         nt_devmode->displayflags        = devmode->displayflags;
1516         nt_devmode->displayfrequency    = devmode->displayfrequency;
1517         nt_devmode->icmmethod           = devmode->icmmethod;
1518         nt_devmode->icmintent           = devmode->icmintent;
1519         nt_devmode->mediatype           = devmode->mediatype;
1520         nt_devmode->dithertype          = devmode->dithertype;
1521         nt_devmode->reserved1           = devmode->reserved1;
1522         nt_devmode->reserved2           = devmode->reserved2;
1523         nt_devmode->panningwidth        = devmode->panningwidth;
1524         nt_devmode->panningheight       = devmode->panningheight;
1525
1526         /*
1527          * Only change private and driverextra if the incoming devmode
1528          * has a new one. JRA.
1529          */
1530
1531         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532                 SAFE_FREE(nt_devmode->nt_dev_private);
1533                 nt_devmode->driverextra = devmode->__driverextra_length;
1534                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1535                         return false;
1536                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1537         }
1538
1539         *pp_nt_devmode = nt_devmode;
1540
1541         return true;
1542 }
1543
1544 /****************************************************************
1545  _spoolss_OpenPrinterEx
1546 ****************************************************************/
1547
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549                               struct spoolss_OpenPrinterEx *r)
1550 {
1551         int snum;
1552         Printer_entry *Printer=NULL;
1553
1554         if (!r->in.printername) {
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         /* some sanity check because you can open a printer or a print server */
1559         /* aka: \\server\printer or \\server */
1560
1561         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1562
1563         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564                 ZERO_STRUCTP(r->out.handle);
1565                 return WERR_INVALID_PARAM;
1566         }
1567
1568         Printer = find_printer_index_by_hnd(p, r->out.handle);
1569         if ( !Printer ) {
1570                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1571                         "handle we created for printer %s\n", r->in.printername));
1572                 close_printer_handle(p, r->out.handle);
1573                 ZERO_STRUCTP(r->out.handle);
1574                 return WERR_INVALID_PARAM;
1575         }
1576
1577         /*
1578          * First case: the user is opening the print server:
1579          *
1580          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1582          *
1583          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585          * or if the user is listed in the smb.conf printer admin parameter.
1586          *
1587          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588          * client view printer folder, but does not show the MSAPW.
1589          *
1590          * Note: this test needs code to check access rights here too. Jeremy
1591          * could you look at this?
1592          *
1593          * Second case: the user is opening a printer:
1594          * NT doesn't let us connect to a printer if the connecting user
1595          * doesn't have print permission.
1596          *
1597          * Third case: user is opening a Port Monitor
1598          * access checks same as opening a handle to the print server.
1599          */
1600
1601         switch (Printer->printer_type )
1602         {
1603         case SPLHND_SERVER:
1604         case SPLHND_PORTMON_TCP:
1605         case SPLHND_PORTMON_LOCAL:
1606                 /* Printserver handles use global struct... */
1607
1608                 snum = -1;
1609
1610                 /* Map standard access rights to object specific access rights */
1611
1612                 se_map_standard(&r->in.access_mask,
1613                                 &printserver_std_mapping);
1614
1615                 /* Deny any object specific bits that don't apply to print
1616                    servers (i.e printer and job specific bits) */
1617
1618                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1619
1620                 if (r->in.access_mask &
1621                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623                         close_printer_handle(p, r->out.handle);
1624                         ZERO_STRUCTP(r->out.handle);
1625                         return WERR_ACCESS_DENIED;
1626                 }
1627
1628                 /* Allow admin access */
1629
1630                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1631                 {
1632                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1633
1634                         if (!lp_ms_add_printer_wizard()) {
1635                                 close_printer_handle(p, r->out.handle);
1636                                 ZERO_STRUCTP(r->out.handle);
1637                                 return WERR_ACCESS_DENIED;
1638                         }
1639
1640                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641                            and not a printer admin, then fail */
1642
1643                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644                             !user_has_privileges(p->server_info->ptok,
1645                                                  &se_printop ) &&
1646                             !token_contains_name_in_list(
1647                                     uidtoname(p->server_info->utok.uid),
1648                                     NULL, NULL,
1649                                     p->server_info->ptok,
1650                                     lp_printer_admin(snum))) {
1651                                 close_printer_handle(p, r->out.handle);
1652                                 ZERO_STRUCTP(r->out.handle);
1653                                 return WERR_ACCESS_DENIED;
1654                         }
1655
1656                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657                 }
1658                 else
1659                 {
1660                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661                 }
1662
1663                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1665
1666                 /* We fall through to return WERR_OK */
1667                 break;
1668
1669         case SPLHND_PRINTER:
1670                 /* NT doesn't let us connect to a printer if the connecting user
1671                    doesn't have print permission.  */
1672
1673                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674                         close_printer_handle(p, r->out.handle);
1675                         ZERO_STRUCTP(r->out.handle);
1676                         return WERR_BADFID;
1677                 }
1678
1679                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681                 }
1682
1683                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1684
1685                 /* map an empty access mask to the minimum access mask */
1686                 if (r->in.access_mask == 0x0)
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688
1689                 /*
1690                  * If we are not serving the printer driver for this printer,
1691                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1692                  * will keep NT clients happy  --jerry
1693                  */
1694
1695                 if (lp_use_client_driver(snum)
1696                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1697                 {
1698                         r->in.access_mask = PRINTER_ACCESS_USE;
1699                 }
1700
1701                 /* check smb.conf parameters and the the sec_desc */
1702
1703                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708
1709                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710                                    p->server_info->ptok, snum) ||
1711                     !print_access_check(p->server_info, snum,
1712                                         r->in.access_mask)) {
1713                         DEBUG(3, ("access DENIED for printer open\n"));
1714                         close_printer_handle(p, r->out.handle);
1715                         ZERO_STRUCTP(r->out.handle);
1716                         return WERR_ACCESS_DENIED;
1717                 }
1718
1719                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721                         close_printer_handle(p, r->out.handle);
1722                         ZERO_STRUCTP(r->out.handle);
1723                         return WERR_ACCESS_DENIED;
1724                 }
1725
1726                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1728                 else
1729                         r->in.access_mask = PRINTER_ACCESS_USE;
1730
1731                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1733
1734                 break;
1735
1736         default:
1737                 /* sanity check to prevent programmer error */
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_BADFID;
1740         }
1741
1742         Printer->access_granted = r->in.access_mask;
1743
1744         /*
1745          * If the client sent a devmode in the OpenPrinter() call, then
1746          * save it here in case we get a job submission on this handle
1747          */
1748
1749          if ((Printer->printer_type != SPLHND_SERVER) &&
1750              r->in.devmode_ctr.devmode) {
1751                 convert_devicemode(Printer->sharename,
1752                                    r->in.devmode_ctr.devmode,
1753                                    &Printer->nt_devmode);
1754          }
1755
1756 #if 0   /* JERRY -- I'm doubtful this is really effective */
1757         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758            optimization in Windows 2000 clients  --jerry */
1759
1760         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761                 && (RA_WIN2K == get_remote_arch()) )
1762         {
1763                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764                 sys_usleep( 500000 );
1765         }
1766 #endif
1767
1768         return WERR_OK;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775                                               NT_PRINTER_INFO_LEVEL_2 *d)
1776 {
1777         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1778
1779         if (!r || !d) {
1780                 return false;
1781         }
1782
1783         d->attributes           = r->attributes;
1784         d->priority             = r->priority;
1785         d->default_priority     = r->defaultpriority;
1786         d->starttime            = r->starttime;
1787         d->untiltime            = r->untiltime;
1788         d->status               = r->status;
1789         d->cjobs                = r->cjobs;
1790
1791         fstrcpy(d->servername,  r->servername);
1792         fstrcpy(d->printername, r->printername);
1793         fstrcpy(d->sharename,   r->sharename);
1794         fstrcpy(d->portname,    r->portname);
1795         fstrcpy(d->drivername,  r->drivername);
1796         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797         fstrcpy(d->location,    r->location);
1798         fstrcpy(d->sepfile,     r->sepfile);
1799         fstrcpy(d->printprocessor, r->printprocessor);
1800         fstrcpy(d->datatype,    r->datatype);
1801         fstrcpy(d->parameters,  r->parameters);
1802
1803         return true;
1804 }
1805
1806 /****************************************************************************
1807 ****************************************************************************/
1808
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810                                  NT_PRINTER_INFO_LEVEL *printer)
1811 {
1812         bool ret;
1813
1814         switch (info_ctr->level) {
1815         case 2:
1816                 /* allocate memory if needed.  Messy because
1817                    convert_printer_info is used to update an existing
1818                    printer or build a new one */
1819
1820                 if (!printer->info_2) {
1821                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822                         if (!printer->info_2) {
1823                                 DEBUG(0,("convert_printer_info: "
1824                                         "talloc() failed!\n"));
1825                                 return false;
1826                         }
1827                 }
1828
1829                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1830                                                         printer->info_2);
1831                 printer->info_2->setuptime = time(NULL);
1832                 return ret;
1833         }
1834
1835         return false;
1836 }
1837
1838 /****************************************************************
1839  _spoolss_ClosePrinter
1840 ****************************************************************/
1841
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843                              struct spoolss_ClosePrinter *r)
1844 {
1845         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1846
1847         if (Printer && Printer->document_started) {
1848                 struct spoolss_EndDocPrinter e;
1849
1850                 e.in.handle = r->in.handle;
1851
1852                 _spoolss_EndDocPrinter(p, &e);
1853         }
1854
1855         if (!close_printer_handle(p, r->in.handle))
1856                 return WERR_BADFID;
1857
1858         /* clear the returned printer handle.  Observed behavior
1859            from Win2k server.  Don't think this really matters.
1860            Previous code just copied the value of the closed
1861            handle.    --jerry */
1862
1863         ZERO_STRUCTP(r->out.handle);
1864
1865         return WERR_OK;
1866 }
1867
1868 /****************************************************************
1869  _spoolss_DeletePrinter
1870 ****************************************************************/
1871
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873                               struct spoolss_DeletePrinter *r)
1874 {
1875         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1876         WERROR result;
1877
1878         if (Printer && Printer->document_started) {
1879                 struct spoolss_EndDocPrinter e;
1880
1881                 e.in.handle = r->in.handle;
1882
1883                 _spoolss_EndDocPrinter(p, &e);
1884         }
1885
1886         result = delete_printer_handle(p, r->in.handle);
1887
1888         update_c_setprinter(false);
1889
1890         return result;
1891 }
1892
1893 /*******************************************************************
1894  * static function to lookup the version id corresponding to an
1895  * long architecture string
1896  ******************************************************************/
1897
1898 static const struct print_architecture_table_node archi_table[]= {
1899
1900         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1901         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1902         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1903         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1904         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1905         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1906         {"Windows x64",          SPL_ARCH_X64,          3 },
1907         {NULL,                   "",            -1 }
1908 };
1909
1910 static int get_version_id(const char *arch)
1911 {
1912         int i;
1913
1914         for (i=0; archi_table[i].long_archi != NULL; i++)
1915         {
1916                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917                         return (archi_table[i].version);
1918         }
1919
1920         return -1;
1921 }
1922
1923 /****************************************************************
1924  _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1926
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928                                     struct spoolss_DeletePrinterDriver *r)
1929 {
1930
1931         struct spoolss_DriverInfo8 *info = NULL;
1932         struct spoolss_DriverInfo8 *info_win2k = NULL;
1933         int                             version;
1934         WERROR                          status;
1935         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1936         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1937
1938         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1939            and not a printer admin, then fail */
1940
1941         if ( (p->server_info->utok.uid != sec_initial_uid())
1942                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1943                 && !token_contains_name_in_list(
1944                         uidtoname(p->server_info->utok.uid), NULL,
1945                         NULL, p->server_info->ptok,
1946                         lp_printer_admin(-1)) )
1947         {
1948                 return WERR_ACCESS_DENIED;
1949         }
1950
1951         /* check that we have a valid driver name first */
1952
1953         if ((version = get_version_id(r->in.architecture)) == -1)
1954                 return WERR_INVALID_ENVIRONMENT;
1955
1956         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1957                                                 r->in.architecture,
1958                                                 version)))
1959         {
1960                 /* try for Win2k driver if "Windows NT x86" */
1961
1962                 if ( version == 2 ) {
1963                         version = 3;
1964                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1965                                                                 &info,
1966                                                                 r->in.driver,
1967                                                                 r->in.architecture,
1968                                                                 version))) {
1969                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970                                 goto done;
1971                         }
1972                 }
1973                 /* otherwise it was a failure */
1974                 else {
1975                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1976                         goto done;
1977                 }
1978
1979         }
1980
1981         if (printer_driver_in_use(info)) {
1982                 status = WERR_PRINTER_DRIVER_IN_USE;
1983                 goto done;
1984         }
1985
1986         if ( version == 2 )
1987         {
1988                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1989                                                        &info_win2k,
1990                                                        r->in.driver,
1991                                                        r->in.architecture, 3)))
1992                 {
1993                         /* if we get to here, we now have 2 driver info structures to remove */
1994                         /* remove the Win2k driver first*/
1995
1996                         status_win2k = delete_printer_driver(
1997                                 p, info_win2k, 3, false);
1998                         free_a_printer_driver(info_win2k);
1999
2000                         /* this should not have failed---if it did, report to client */
2001                         if ( !W_ERROR_IS_OK(status_win2k) )
2002                         {
2003                                 status = status_win2k;
2004                                 goto done;
2005                         }
2006                 }
2007         }
2008
2009         status = delete_printer_driver(p, info, version, false);
2010
2011         /* if at least one of the deletes succeeded return OK */
2012
2013         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2014                 status = WERR_OK;
2015
2016 done:
2017         free_a_printer_driver(info);
2018
2019         return status;
2020 }
2021
2022 /****************************************************************
2023  _spoolss_DeletePrinterDriverEx
2024 ****************************************************************/
2025
2026 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2027                                       struct spoolss_DeletePrinterDriverEx *r)
2028 {
2029         struct spoolss_DriverInfo8      *info = NULL;
2030         struct spoolss_DriverInfo8      *info_win2k = NULL;
2031         int                             version;
2032         bool                            delete_files;
2033         WERROR                          status;
2034         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2035         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2036
2037         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038            and not a printer admin, then fail */
2039
2040         if ( (p->server_info->utok.uid != sec_initial_uid())
2041                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2042                 && !token_contains_name_in_list(
2043                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2044                         p->server_info->ptok, lp_printer_admin(-1)) )
2045         {
2046                 return WERR_ACCESS_DENIED;
2047         }
2048
2049         /* check that we have a valid driver name first */
2050         if ((version = get_version_id(r->in.architecture)) == -1) {
2051                 /* this is what NT returns */
2052                 return WERR_INVALID_ENVIRONMENT;
2053         }
2054
2055         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2056                 version = r->in.version;
2057
2058         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2059                                       r->in.architecture, version);
2060
2061         if ( !W_ERROR_IS_OK(status) )
2062         {
2063                 /*
2064                  * if the client asked for a specific version,
2065                  * or this is something other than Windows NT x86,
2066                  * then we've failed
2067                  */
2068
2069                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2070                         goto done;
2071
2072                 /* try for Win2k driver if "Windows NT x86" */
2073
2074                 version = 3;
2075                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2076                                                         r->in.architecture,
2077                                                         version))) {
2078                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2079                         goto done;
2080                 }
2081         }
2082
2083         if (printer_driver_in_use(info)) {
2084                 status = WERR_PRINTER_DRIVER_IN_USE;
2085                 goto done;
2086         }
2087
2088         /*
2089          * we have a couple of cases to consider.
2090          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2091          *     then the delete should fail if **any** files overlap with
2092          *     other drivers
2093          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094          *     non-overlapping files
2095          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096          *     is set, the do not delete any files
2097          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2098          */
2099
2100         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2101
2102         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2103
2104         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2105                 /* no idea of the correct error here */
2106                 status = WERR_ACCESS_DENIED;
2107                 goto done;
2108         }
2109
2110
2111         /* also check for W32X86/3 if necessary; maybe we already have? */
2112
2113         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2114                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2115                                                        r->in.driver,
2116                                                        r->in.architecture, 3)))
2117                 {
2118
2119                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2120                                 /* no idea of the correct error here */
2121                                 free_a_printer_driver(info_win2k);
2122                                 status = WERR_ACCESS_DENIED;
2123                                 goto done;
2124                         }
2125
2126                         /* if we get to here, we now have 2 driver info structures to remove */
2127                         /* remove the Win2k driver first*/
2128
2129                         status_win2k = delete_printer_driver(
2130                                 p, info_win2k, 3, delete_files);
2131                         free_a_printer_driver(info_win2k);
2132
2133                         /* this should not have failed---if it did, report to client */
2134
2135                         if ( !W_ERROR_IS_OK(status_win2k) )
2136                                 goto done;
2137                 }
2138         }
2139
2140         status = delete_printer_driver(p, info, version, delete_files);
2141
2142         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2143                 status = WERR_OK;
2144 done:
2145         free_a_printer_driver(info);
2146
2147         return status;
2148 }
2149
2150
2151 /****************************************************************************
2152  Internal routine for removing printerdata
2153  ***************************************************************************/
2154
2155 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2156 {
2157         return delete_printer_data( printer->info_2, key, value );
2158 }
2159
2160 /****************************************************************************
2161  Internal routine for storing printerdata
2162  ***************************************************************************/
2163
2164 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2165                           const char *key, const char *value,
2166                           uint32_t type, uint8_t *data, int real_len)
2167 {
2168         /* the registry objects enforce uniqueness based on value name */
2169
2170         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2171 }
2172
2173 /********************************************************************
2174  GetPrinterData on a printer server Handle.
2175 ********************************************************************/
2176
2177 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2178                                             const char *value,
2179                                             enum winreg_Type *type,
2180                                             union spoolss_PrinterData *data)
2181 {
2182         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2183
2184         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2185                 *type = REG_DWORD;
2186                 data->value = 0x00;
2187                 return WERR_OK;
2188         }
2189
2190         if (!StrCaseCmp(value, "BeepEnabled")) {
2191                 *type = REG_DWORD;
2192                 data->value = 0x00;
2193                 return WERR_OK;
2194         }
2195
2196         if (!StrCaseCmp(value, "EventLog")) {
2197                 *type = REG_DWORD;
2198                 /* formally was 0x1b */
2199                 data->value = 0x00;
2200                 return WERR_OK;
2201         }
2202
2203         if (!StrCaseCmp(value, "NetPopup")) {
2204                 *type = REG_DWORD;
2205                 data->value = 0x00;
2206                 return WERR_OK;
2207         }
2208
2209         if (!StrCaseCmp(value, "MajorVersion")) {
2210                 *type = REG_DWORD;
2211
2212                 /* Windows NT 4.0 seems to not allow uploading of drivers
2213                    to a server that reports 0x3 as the MajorVersion.
2214                    need to investigate more how Win2k gets around this .
2215                    -- jerry */
2216
2217                 if (RA_WINNT == get_remote_arch()) {
2218                         data->value = 0x02;
2219                 } else {
2220                         data->value = 0x03;
2221                 }
2222
2223                 return WERR_OK;
2224         }
2225
2226         if (!StrCaseCmp(value, "MinorVersion")) {
2227                 *type = REG_DWORD;
2228                 data->value = 0x00;
2229                 return WERR_OK;
2230         }
2231
2232         /* REG_BINARY
2233          *  uint32_t size        = 0x114
2234          *  uint32_t major       = 5
2235          *  uint32_t minor       = [0|1]
2236          *  uint32_t build       = [2195|2600]
2237          *  extra unicode string = e.g. "Service Pack 3"
2238          */
2239         if (!StrCaseCmp(value, "OSVersion")) {
2240                 DATA_BLOB blob;
2241                 enum ndr_err_code ndr_err;
2242                 struct spoolss_OSVersion os;
2243
2244                 os.major                = 5;    /* Windows 2000 == 5.0 */
2245                 os.minor                = 0;
2246                 os.build                = 2195; /* build */
2247                 os.extra_string         = "";   /* leave extra string empty */
2248
2249                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2250                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2251                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2252                         return WERR_GENERAL_FAILURE;
2253                 }
2254
2255                 *type = REG_BINARY;
2256                 data->binary = blob;
2257
2258                 return WERR_OK;
2259         }
2260
2261
2262         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2263                 *type = REG_SZ;
2264
2265                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2266                 W_ERROR_HAVE_NO_MEMORY(data->string);
2267
2268                 return WERR_OK;
2269         }
2270
2271         if (!StrCaseCmp(value, "Architecture")) {
2272                 *type = REG_SZ;
2273                 data->string = talloc_strdup(mem_ctx,
2274                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2275                 W_ERROR_HAVE_NO_MEMORY(data->string);
2276
2277                 return WERR_OK;
2278         }
2279
2280         if (!StrCaseCmp(value, "DsPresent")) {
2281                 *type = REG_DWORD;
2282
2283                 /* only show the publish check box if we are a
2284                    member of a AD domain */
2285
2286                 if (lp_security() == SEC_ADS) {
2287                         data->value = 0x01;
2288                 } else {
2289                         data->value = 0x00;
2290                 }
2291                 return WERR_OK;
2292         }
2293
2294         if (!StrCaseCmp(value, "DNSMachineName")) {
2295                 const char *hostname = get_mydnsfullname();
2296
2297                 if (!hostname) {
2298                         return WERR_BADFILE;
2299                 }
2300
2301                 *type = REG_SZ;
2302                 data->string = talloc_strdup(mem_ctx, hostname);
2303                 W_ERROR_HAVE_NO_MEMORY(data->string);
2304
2305                 return WERR_OK;
2306         }
2307
2308         *type = REG_NONE;
2309
2310         return WERR_INVALID_PARAM;
2311 }
2312
2313 /****************************************************************
2314  _spoolss_GetPrinterData
2315 ****************************************************************/
2316
2317 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2318                                struct spoolss_GetPrinterData *r)
2319 {
2320         struct spoolss_GetPrinterDataEx r2;
2321
2322         r2.in.handle            = r->in.handle;
2323         r2.in.key_name          = "PrinterDriverData";
2324         r2.in.value_name        = r->in.value_name;
2325         r2.in.offered           = r->in.offered;
2326         r2.out.type             = r->out.type;
2327         r2.out.data             = r->out.data;
2328         r2.out.needed           = r->out.needed;
2329
2330         return _spoolss_GetPrinterDataEx(p, &r2);
2331 }
2332
2333 /*********************************************************
2334  Connect to the client machine.
2335 **********************************************************/
2336
2337 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2338                         struct sockaddr_storage *client_ss, const char *remote_machine)
2339 {
2340         NTSTATUS ret;
2341         struct cli_state *the_cli;
2342         struct sockaddr_storage rm_addr;
2343         char addr[INET6_ADDRSTRLEN];
2344
2345         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2346                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2347                         remote_machine));
2348                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2349                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2350                         return false;
2351                 }
2352                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2353         } else {
2354                 rm_addr = *client_ss;
2355                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2356                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2357                         addr));
2358         }
2359
2360         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2361                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2362                         addr));
2363                 return false;
2364         }
2365
2366         /* setup the connection */
2367         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2368                 &rm_addr, 0, "IPC$", "IPC",
2369                 "", /* username */
2370                 "", /* domain */
2371                 "", /* password */
2372                 0, lp_client_signing(), NULL );
2373
2374         if ( !NT_STATUS_IS_OK( ret ) ) {
2375                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2376                         remote_machine ));
2377                 return false;
2378         }
2379
2380         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2381                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2382                 cli_shutdown(the_cli);
2383                 return false;
2384         }
2385
2386         /*
2387          * Ok - we have an anonymous connection to the IPC$ share.
2388          * Now start the NT Domain stuff :-).
2389          */
2390
2391         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2392         if (!NT_STATUS_IS_OK(ret)) {
2393                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2394                         remote_machine, nt_errstr(ret)));
2395                 cli_shutdown(the_cli);
2396                 return false;
2397         }
2398
2399         return true;
2400 }
2401
2402 /***************************************************************************
2403  Connect to the client.
2404 ****************************************************************************/
2405
2406 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2407                                         uint32_t localprinter, uint32_t type,
2408                                         struct policy_handle *handle,
2409                                         struct sockaddr_storage *client_ss)
2410 {
2411         WERROR result;
2412         NTSTATUS status;
2413
2414         /*
2415          * If it's the first connection, contact the client
2416          * and connect to the IPC$ share anonymously
2417          */
2418         if (smb_connections==0) {
2419                 fstring unix_printer;
2420
2421                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2422
2423                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2424                         return false;
2425
2426                 messaging_register(smbd_messaging_context(), NULL,
2427                                    MSG_PRINTER_NOTIFY2,
2428                                    receive_notify2_message_list);
2429                 /* Tell the connections db we're now interested in printer
2430                  * notify messages. */
2431                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2432         }
2433
2434         /*
2435          * Tell the specific printing tdb we want messages for this printer
2436          * by registering our PID.
2437          */
2438
2439         if (!print_notify_register_pid(snum))
2440                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2441
2442         smb_connections++;
2443
2444         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2445                                                  printer,
2446                                                  localprinter,
2447                                                  type,
2448                                                  0,
2449                                                  NULL,
2450                                                  handle,
2451                                                  &result);
2452         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2453                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2454                         win_errstr(result)));
2455
2456         return (W_ERROR_IS_OK(result));
2457 }
2458
2459 /****************************************************************
2460  ****************************************************************/
2461
2462 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2463                                                              const struct spoolss_NotifyOption *r)
2464 {
2465         struct spoolss_NotifyOption *option;
2466         uint32_t i,k;
2467
2468         if (!r) {
2469                 return NULL;
2470         }
2471
2472         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2473         if (!option) {
2474                 return NULL;
2475         }
2476
2477         *option = *r;
2478
2479         if (!option->count) {
2480                 return option;
2481         }
2482
2483         option->types = talloc_zero_array(option,
2484                 struct spoolss_NotifyOptionType, option->count);
2485         if (!option->types) {
2486                 talloc_free(option);
2487                 return NULL;
2488         }
2489
2490         for (i=0; i < option->count; i++) {
2491                 option->types[i] = r->types[i];
2492
2493                 if (option->types[i].count) {
2494                         option->types[i].fields = talloc_zero_array(option,
2495                                 union spoolss_Field, option->types[i].count);
2496                         if (!option->types[i].fields) {
2497                                 talloc_free(option);
2498                                 return NULL;
2499                         }
2500                         for (k=0; k<option->types[i].count; k++) {
2501                                 option->types[i].fields[k] =
2502                                         r->types[i].fields[k];
2503                         }
2504                 }
2505         }
2506
2507         return option;
2508 }
2509
2510 /****************************************************************
2511  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2512  *
2513  * before replying OK: status=0 a rpc call is made to the workstation
2514  * asking ReplyOpenPrinter
2515  *
2516  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2517  * called from api_spoolss_rffpcnex
2518 ****************************************************************/
2519
2520 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2521                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2522 {
2523         int snum = -1;
2524         struct spoolss_NotifyOption *option = r->in.notify_options;
2525         struct sockaddr_storage client_ss;
2526
2527         /* store the notify value in the printer struct */
2528
2529         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2530
2531         if (!Printer) {
2532                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2533                         "Invalid handle (%s:%u:%u).\n",
2534                         OUR_HANDLE(r->in.handle)));
2535                 return WERR_BADFID;
2536         }
2537
2538         Printer->notify.flags           = r->in.flags;
2539         Printer->notify.options         = r->in.options;
2540         Printer->notify.printerlocal    = r->in.printer_local;
2541
2542         TALLOC_FREE(Printer->notify.option);
2543         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2544
2545         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2546
2547         /* Connect to the client machine and send a ReplyOpenPrinter */
2548
2549         if ( Printer->printer_type == SPLHND_SERVER)
2550                 snum = -1;
2551         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2552                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2553                 return WERR_BADFID;
2554
2555         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2556                 "client_address is %s\n", p->client_address));
2557
2558         if (!interpret_string_addr(&client_ss, p->client_address,
2559                                    AI_NUMERICHOST)) {
2560                 return WERR_SERVER_UNAVAILABLE;
2561         }
2562
2563         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2564                                         Printer->notify.printerlocal, 1,
2565                                         &Printer->notify.client_hnd, &client_ss))
2566                 return WERR_SERVER_UNAVAILABLE;
2567
2568         Printer->notify.client_connected = true;
2569
2570         return WERR_OK;
2571 }
2572
2573 /*******************************************************************
2574  * fill a notify_info_data with the servername
2575  ********************************************************************/
2576
2577 void spoolss_notify_server_name(int snum,
2578                                        struct spoolss_Notify *data,
2579                                        print_queue_struct *queue,
2580                                        NT_PRINTER_INFO_LEVEL *printer,
2581                                        TALLOC_CTX *mem_ctx)
2582 {
2583         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2584 }
2585
2586 /*******************************************************************
2587  * fill a notify_info_data with the printername (not including the servername).
2588  ********************************************************************/
2589
2590 void spoolss_notify_printer_name(int snum,
2591                                         struct spoolss_Notify *data,
2592                                         print_queue_struct *queue,
2593                                         NT_PRINTER_INFO_LEVEL *printer,
2594                                         TALLOC_CTX *mem_ctx)
2595 {
2596         /* the notify name should not contain the \\server\ part */
2597         char *p = strrchr(printer->info_2->printername, '\\');
2598
2599         if (!p) {
2600                 p = printer->info_2->printername;
2601         } else {
2602                 p++;
2603         }
2604
2605         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2606 }
2607
2608 /*******************************************************************
2609  * fill a notify_info_data with the servicename
2610  ********************************************************************/
2611
2612 void spoolss_notify_share_name(int snum,
2613                                       struct spoolss_Notify *data,
2614                                       print_queue_struct *queue,
2615                                       NT_PRINTER_INFO_LEVEL *printer,
2616                                       TALLOC_CTX *mem_ctx)
2617 {
2618         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2619 }
2620
2621 /*******************************************************************
2622  * fill a notify_info_data with the port name
2623  ********************************************************************/
2624
2625 void spoolss_notify_port_name(int snum,
2626                                      struct spoolss_Notify *data,
2627                                      print_queue_struct *queue,
2628                                      NT_PRINTER_INFO_LEVEL *printer,
2629                                      TALLOC_CTX *mem_ctx)
2630 {
2631         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2632 }
2633
2634 /*******************************************************************
2635  * fill a notify_info_data with the printername
2636  * but it doesn't exist, have to see what to do
2637  ********************************************************************/
2638
2639 void spoolss_notify_driver_name(int snum,
2640                                        struct spoolss_Notify *data,
2641                                        print_queue_struct *queue,
2642                                        NT_PRINTER_INFO_LEVEL *printer,
2643                                        TALLOC_CTX *mem_ctx)
2644 {
2645         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2646 }
2647
2648 /*******************************************************************
2649  * fill a notify_info_data with the comment
2650  ********************************************************************/
2651
2652 void spoolss_notify_comment(int snum,
2653                                    struct spoolss_Notify *data,
2654                                    print_queue_struct *queue,
2655                                    NT_PRINTER_INFO_LEVEL *printer,
2656                                    TALLOC_CTX *mem_ctx)
2657 {
2658         char *p;
2659
2660         if (*printer->info_2->comment == '\0') {
2661                 p = lp_comment(snum);
2662         } else {
2663                 p = printer->info_2->comment;
2664         }
2665
2666         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2667 }
2668
2669 /*******************************************************************
2670  * fill a notify_info_data with the comment
2671  * location = "Room 1, floor 2, building 3"
2672  ********************************************************************/
2673
2674 void spoolss_notify_location(int snum,
2675                                     struct spoolss_Notify *data,
2676                                     print_queue_struct *queue,
2677                                     NT_PRINTER_INFO_LEVEL *printer,
2678                                     TALLOC_CTX *mem_ctx)
2679 {
2680         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2681 }
2682
2683 /*******************************************************************
2684  * fill a notify_info_data with the device mode
2685  * jfm:xxxx don't to it for know but that's a real problem !!!
2686  ********************************************************************/
2687
2688 static void spoolss_notify_devmode(int snum,
2689                                    struct spoolss_Notify *data,
2690                                    print_queue_struct *queue,
2691                                    NT_PRINTER_INFO_LEVEL *printer,
2692                                    TALLOC_CTX *mem_ctx)
2693 {
2694         /* for a dummy implementation we have to zero the fields */
2695         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2696 }
2697
2698 /*******************************************************************
2699  * fill a notify_info_data with the separator file name
2700  ********************************************************************/
2701
2702 void spoolss_notify_sepfile(int snum,
2703                                    struct spoolss_Notify *data,
2704                                    print_queue_struct *queue,
2705                                    NT_PRINTER_INFO_LEVEL *printer,
2706                                    TALLOC_CTX *mem_ctx)
2707 {
2708         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2709 }
2710
2711 /*******************************************************************
2712  * fill a notify_info_data with the print processor
2713  * jfm:xxxx return always winprint to indicate we don't do anything to it
2714  ********************************************************************/
2715
2716 void spoolss_notify_print_processor(int snum,
2717                                            struct spoolss_Notify *data,
2718                                            print_queue_struct *queue,
2719                                            NT_PRINTER_INFO_LEVEL *printer,
2720                                            TALLOC_CTX *mem_ctx)
2721 {
2722         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2723 }
2724
2725 /*******************************************************************
2726  * fill a notify_info_data with the print processor options
2727  * jfm:xxxx send an empty string
2728  ********************************************************************/
2729
2730 void spoolss_notify_parameters(int snum,
2731                                       struct spoolss_Notify *data,
2732                                       print_queue_struct *queue,
2733                                       NT_PRINTER_INFO_LEVEL *printer,
2734                                       TALLOC_CTX *mem_ctx)
2735 {
2736         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2737 }
2738
2739 /*******************************************************************
2740  * fill a notify_info_data with the data type
2741  * jfm:xxxx always send RAW as data type
2742  ********************************************************************/
2743
2744 void spoolss_notify_datatype(int snum,
2745                                     struct spoolss_Notify *data,
2746                                     print_queue_struct *queue,
2747                                     NT_PRINTER_INFO_LEVEL *printer,
2748                                     TALLOC_CTX *mem_ctx)
2749 {
2750         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2751 }
2752
2753 /*******************************************************************
2754  * fill a notify_info_data with the security descriptor
2755  * jfm:xxxx send an null pointer to say no security desc
2756  * have to implement security before !
2757  ********************************************************************/
2758
2759 static void spoolss_notify_security_desc(int snum,
2760                                          struct spoolss_Notify *data,
2761                                          print_queue_struct *queue,
2762                                          NT_PRINTER_INFO_LEVEL *printer,
2763                                          TALLOC_CTX *mem_ctx)
2764 {
2765         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2766                                           printer->info_2->secdesc_buf->sd_size,
2767                                           printer->info_2->secdesc_buf->sd);
2768 }
2769
2770 /*******************************************************************
2771  * fill a notify_info_data with the attributes
2772  * jfm:xxxx a samba printer is always shared
2773  ********************************************************************/
2774
2775 void spoolss_notify_attributes(int snum,
2776                                       struct spoolss_Notify *data,
2777                                       print_queue_struct *queue,
2778                                       NT_PRINTER_INFO_LEVEL *printer,
2779                                       TALLOC_CTX *mem_ctx)
2780 {
2781         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2782 }
2783
2784 /*******************************************************************
2785  * fill a notify_info_data with the priority
2786  ********************************************************************/
2787
2788 static void spoolss_notify_priority(int snum,
2789                                     struct spoolss_Notify *data,
2790                                     print_queue_struct *queue,
2791                                     NT_PRINTER_INFO_LEVEL *printer,
2792                                     TALLOC_CTX *mem_ctx)
2793 {
2794         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2795 }
2796
2797 /*******************************************************************
2798  * fill a notify_info_data with the default priority
2799  ********************************************************************/
2800
2801 static void spoolss_notify_default_priority(int snum,
2802                                             struct spoolss_Notify *data,
2803                                             print_queue_struct *queue,
2804                                             NT_PRINTER_INFO_LEVEL *printer,
2805                                             TALLOC_CTX *mem_ctx)
2806 {
2807         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2808 }
2809
2810 /*******************************************************************
2811  * fill a notify_info_data with the start time
2812  ********************************************************************/
2813
2814 static void spoolss_notify_start_time(int snum,
2815                                       struct spoolss_Notify *data,
2816                                       print_queue_struct *queue,
2817                                       NT_PRINTER_INFO_LEVEL *printer,
2818                                       TALLOC_CTX *mem_ctx)
2819 {
2820         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2821 }
2822
2823 /*******************************************************************
2824  * fill a notify_info_data with the until time
2825  ********************************************************************/
2826
2827 static void spoolss_notify_until_time(int snum,
2828                                       struct spoolss_Notify *data,
2829                                       print_queue_struct *queue,
2830                                       NT_PRINTER_INFO_LEVEL *printer,
2831                                       TALLOC_CTX *mem_ctx)
2832 {
2833         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2834 }
2835
2836 /*******************************************************************
2837  * fill a notify_info_data with the status
2838  ********************************************************************/
2839
2840 static void spoolss_notify_status(int snum,
2841                                   struct spoolss_Notify *data,
2842                                   print_queue_struct *queue,
2843                                   NT_PRINTER_INFO_LEVEL *printer,
2844                                   TALLOC_CTX *mem_ctx)
2845 {
2846         print_status_struct status;
2847
2848         print_queue_length(snum, &status);
2849         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2850 }
2851
2852 /*******************************************************************
2853  * fill a notify_info_data with the number of jobs queued
2854  ********************************************************************/
2855
2856 void spoolss_notify_cjobs(int snum,
2857                                  struct spoolss_Notify *data,
2858                                  print_queue_struct *queue,
2859                                  NT_PRINTER_INFO_LEVEL *printer,
2860                                  TALLOC_CTX *mem_ctx)
2861 {
2862         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2863 }
2864
2865 /*******************************************************************
2866  * fill a notify_info_data with the average ppm
2867  ********************************************************************/
2868
2869 static void spoolss_notify_average_ppm(int snum,
2870                                        struct spoolss_Notify *data,
2871                                        print_queue_struct *queue,
2872                                        NT_PRINTER_INFO_LEVEL *printer,
2873                                        TALLOC_CTX *mem_ctx)
2874 {
2875         /* always respond 8 pages per minutes */
2876         /* a little hard ! */
2877         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2878 }
2879
2880 /*******************************************************************
2881  * fill a notify_info_data with username
2882  ********************************************************************/
2883
2884 static void spoolss_notify_username(int snum,
2885                                     struct spoolss_Notify *data,
2886                                     print_queue_struct *queue,
2887                                     NT_PRINTER_INFO_LEVEL *printer,
2888                                     TALLOC_CTX *mem_ctx)
2889 {
2890         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2891 }
2892
2893 /*******************************************************************
2894  * fill a notify_info_data with job status
2895  ********************************************************************/
2896
2897 static void spoolss_notify_job_status(int snum,
2898                                       struct spoolss_Notify *data,
2899                                       print_queue_struct *queue,
2900                                       NT_PRINTER_INFO_LEVEL *printer,
2901                                       TALLOC_CTX *mem_ctx)
2902 {
2903         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2904 }
2905
2906 /*******************************************************************
2907  * fill a notify_info_data with job name
2908  ********************************************************************/
2909
2910 static void spoolss_notify_job_name(int snum,
2911                                     struct spoolss_Notify *data,
2912                                     print_queue_struct *queue,
2913                                     NT_PRINTER_INFO_LEVEL *printer,
2914                                     TALLOC_CTX *mem_ctx)
2915 {
2916         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2917 }
2918
2919 /*******************************************************************
2920  * fill a notify_info_data with job status
2921  ********************************************************************/
2922
2923 static void spoolss_notify_job_status_string(int snum,
2924                                              struct spoolss_Notify *data,
2925                                              print_queue_struct *queue,
2926                                              NT_PRINTER_INFO_LEVEL *printer,
2927                                              TALLOC_CTX *mem_ctx)
2928 {
2929         /*
2930          * Now we're returning job status codes we just return a "" here. JRA.
2931          */
2932
2933         const char *p = "";
2934
2935 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2936         p = "unknown";
2937
2938         switch (queue->status) {
2939         case LPQ_QUEUED:
2940                 p = "Queued";
2941                 break;
2942         case LPQ_PAUSED:
2943                 p = "";    /* NT provides the paused string */
2944                 break;
2945         case LPQ_SPOOLING:
2946                 p = "Spooling";
2947                 break;
2948         case LPQ_PRINTING:
2949                 p = "Printing";
2950                 break;
2951         }
2952 #endif /* NO LONGER NEEDED. */
2953
2954         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2955 }
2956
2957 /*******************************************************************
2958  * fill a notify_info_data with job time
2959  ********************************************************************/
2960
2961 static void spoolss_notify_job_time(int snum,
2962                                     struct spoolss_Notify *data,
2963                                     print_queue_struct *queue,
2964                                     NT_PRINTER_INFO_LEVEL *printer,
2965                                     TALLOC_CTX *mem_ctx)
2966 {
2967         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2968 }
2969
2970 /*******************************************************************
2971  * fill a notify_info_data with job size
2972  ********************************************************************/
2973
2974 static void spoolss_notify_job_size(int snum,
2975                                     struct spoolss_Notify *data,
2976                                     print_queue_struct *queue,
2977                                     NT_PRINTER_INFO_LEVEL *printer,
2978                                     TALLOC_CTX *mem_ctx)
2979 {
2980         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2981 }
2982
2983 /*******************************************************************
2984  * fill a notify_info_data with page info
2985  ********************************************************************/
2986 static void spoolss_notify_total_pages(int snum,
2987                                 struct spoolss_Notify *data,
2988                                 print_queue_struct *queue,
2989                                 NT_PRINTER_INFO_LEVEL *printer,
2990                                 TALLOC_CTX *mem_ctx)
2991 {
2992         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2993 }
2994
2995 /*******************************************************************
2996  * fill a notify_info_data with pages printed info.
2997  ********************************************************************/
2998 static void spoolss_notify_pages_printed(int snum,
2999                                 struct spoolss_Notify *data,
3000                                 print_queue_struct *queue,
3001                                 NT_PRINTER_INFO_LEVEL *printer,
3002                                 TALLOC_CTX *mem_ctx)
3003 {
3004         /* Add code when back-end tracks this */
3005         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3006 }
3007
3008 /*******************************************************************
3009  Fill a notify_info_data with job position.
3010  ********************************************************************/
3011
3012 static void spoolss_notify_job_position(int snum,
3013                                         struct spoolss_Notify *data,
3014                                         print_queue_struct *queue,
3015                                         NT_PRINTER_INFO_LEVEL *printer,
3016                                         TALLOC_CTX *mem_ctx)
3017 {
3018         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3019 }
3020
3021 /*******************************************************************
3022  Fill a notify_info_data with submitted time.
3023  ********************************************************************/
3024
3025 static void spoolss_notify_submitted_time(int snum,
3026                                           struct spoolss_Notify *data,
3027                                           print_queue_struct *queue,
3028                                           NT_PRINTER_INFO_LEVEL *printer,
3029                                           TALLOC_CTX *mem_ctx)
3030 {
3031         data->data.string.string = NULL;
3032         data->data.string.size = 0;
3033
3034         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3035                                &data->data.string.string,
3036                                &data->data.string.size);
3037
3038 }
3039
3040 struct s_notify_info_data_table
3041 {
3042         enum spoolss_NotifyType type;
3043         uint16_t field;
3044         const char *name;
3045         enum spoolss_NotifyTable variable_type;
3046         void (*fn) (int snum, struct spoolss_Notify *data,
3047                     print_queue_struct *queue,
3048                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3049 };
3050
3051 /* A table describing the various print notification constants and
3052    whether the notification data is a pointer to a variable sized
3053    buffer, a one value uint32_t or a two value uint32_t. */
3054
3055 static const struct s_notify_info_data_table notify_info_data_table[] =
3056 {
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3077 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3078 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3079 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3080 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3081 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3082 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3083 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3084 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3085 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3086 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3087 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3088 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3100 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3101 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3102 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3103 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3104 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3105 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3106 };
3107
3108 /*******************************************************************
3109  Return the variable_type of info_data structure.
3110 ********************************************************************/
3111
3112 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3113                                                   uint16_t field)
3114 {
3115         int i=0;
3116
3117         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3118                 if ( (notify_info_data_table[i].type == type) &&
3119                      (notify_info_data_table[i].field == field) ) {
3120                         return notify_info_data_table[i].variable_type;
3121                 }
3122         }
3123
3124         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3125
3126         return 0;
3127 }
3128
3129 /****************************************************************************
3130 ****************************************************************************/
3131
3132 static bool search_notify(enum spoolss_NotifyType type,
3133                           uint16_t field,
3134                           int *value)
3135 {
3136         int i;
3137
3138         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3139                 if (notify_info_data_table[i].type == type &&
3140                     notify_info_data_table[i].field == field &&
3141                     notify_info_data_table[i].fn != NULL) {
3142                         *value = i;
3143                         return true;
3144                 }
3145         }
3146
3147         return false;
3148 }
3149
3150 /****************************************************************************
3151 ****************************************************************************/
3152
3153 void construct_info_data(struct spoolss_Notify *info_data,
3154                          enum spoolss_NotifyType type,
3155                          uint16_t field,
3156                          int id)
3157 {
3158         info_data->type                 = type;
3159         info_data->field.field          = field;
3160         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3161         info_data->job_id               = id;
3162 }
3163
3164 /*******************************************************************
3165  *
3166  * fill a notify_info struct with info asked
3167  *
3168  ********************************************************************/
3169
3170 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3171                                           struct spoolss_NotifyInfo *info,
3172                                           int snum,
3173                                           const struct spoolss_NotifyOptionType *option_type,
3174                                           uint32_t id,
3175                                           TALLOC_CTX *mem_ctx)
3176 {
3177         int field_num,j;
3178         enum spoolss_NotifyType type;
3179         uint16_t field;
3180
3181         struct spoolss_Notify *current_data;
3182         NT_PRINTER_INFO_LEVEL *printer = NULL;
3183         print_queue_struct *queue=NULL;
3184
3185         type = option_type->type;
3186
3187         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3188                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3189                 option_type->count, lp_servicename(snum)));
3190
3191         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3192                 return false;
3193
3194         for(field_num=0; field_num < option_type->count; field_num++) {
3195                 field = option_type->fields[field_num].field;
3196
3197                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3198
3199                 if (!search_notify(type, field, &j) )
3200                         continue;
3201
3202                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3203                                                       struct spoolss_Notify,
3204                                                       info->count + 1);
3205                 if (info->notifies == NULL) {
3206                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3207                         free_a_printer(&printer, 2);
3208                         return false;
3209                 }
3210
3211                 current_data = &info->notifies[info->count];
3212
3213                 construct_info_data(current_data, type, field, id);
3214
3215                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3216                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3217
3218                 notify_info_data_table[j].fn(snum, current_data, queue,
3219                                              printer, mem_ctx);
3220
3221                 info->count++;
3222         }
3223
3224         free_a_printer(&printer, 2);
3225         return true;
3226 }
3227
3228 /*******************************************************************
3229  *
3230  * fill a notify_info struct with info asked
3231  *
3232  ********************************************************************/
3233
3234 static bool construct_notify_jobs_info(print_queue_struct *queue,
3235                                        struct spoolss_NotifyInfo *info,
3236                                        NT_PRINTER_INFO_LEVEL *printer,
3237                                        int snum,
3238                                        const struct spoolss_NotifyOptionType *option_type,
3239                                        uint32_t id,
3240                                        TALLOC_CTX *mem_ctx)
3241 {
3242         int field_num,j;
3243         enum spoolss_NotifyType type;
3244         uint16_t field;
3245         struct spoolss_Notify *current_data;
3246
3247         DEBUG(4,("construct_notify_jobs_info\n"));
3248
3249         type = option_type->type;
3250
3251         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3252                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3253                 option_type->count));
3254
3255         for(field_num=0; field_num<option_type->count; field_num++) {
3256                 field = option_type->fields[field_num].field;
3257
3258                 if (!search_notify(type, field, &j) )
3259                         continue;
3260
3261                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3262                                                       struct spoolss_Notify,
3263                                                       info->count + 1);
3264                 if (info->notifies == NULL) {
3265                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3266                         return false;
3267                 }
3268
3269                 current_data=&(info->notifies[info->count]);
3270
3271                 construct_info_data(current_data, type, field, id);
3272                 notify_info_data_table[j].fn(snum, current_data, queue,
3273                                              printer, mem_ctx);
3274                 info->count++;
3275         }
3276
3277         return true;
3278 }
3279
3280 /*
3281  * JFM: The enumeration is not that simple, it's even non obvious.
3282  *
3283  * let's take an example: I want to monitor the PRINTER SERVER for
3284  * the printer's name and the number of jobs currently queued.
3285  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3286  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3287  *
3288  * I have 3 printers on the back of my server.
3289  *
3290  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3291  * structures.
3292  *   Number     Data                    Id
3293  *      1       printer 1 name          1
3294  *      2       printer 1 cjob          1
3295  *      3       printer 2 name          2
3296  *      4       printer 2 cjob          2
3297  *      5       printer 3 name          3
3298  *      6       printer 3 name          3
3299  *
3300  * that's the print server case, the printer case is even worse.
3301  */
3302
3303 /*******************************************************************
3304  *
3305  * enumerate all printers on the printserver
3306  * fill a notify_info struct with info asked
3307  *
3308  ********************************************************************/
3309
3310 static WERROR printserver_notify_info(pipes_struct *p,
3311                                       struct policy_handle *hnd,
3312                                       struct spoolss_NotifyInfo *info,
3313                                       TALLOC_CTX *mem_ctx)
3314 {
3315         int snum;
3316         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3317         int n_services=lp_numservices();
3318         int i;
3319         struct spoolss_NotifyOption *option;
3320         struct spoolss_NotifyOptionType option_type;
3321
3322         DEBUG(4,("printserver_notify_info\n"));
3323
3324         if (!Printer)
3325                 return WERR_BADFID;
3326
3327         option = Printer->notify.option;
3328
3329         info->version   = 2;
3330         info->notifies  = NULL;
3331         info->count     = 0;
3332
3333         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3334            sending a ffpcn() request first */
3335
3336         if ( !option )
3337                 return WERR_BADFID;
3338
3339         for (i=0; i<option->count; i++) {
3340                 option_type = option->types[i];
3341
3342                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3343                         continue;
3344
3345                 for (snum=0; snum<n_services; snum++)
3346                 {
3347                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3348                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3349                 }
3350         }
3351
3352 #if 0
3353         /*
3354          * Debugging information, don't delete.
3355          */
3356
3357         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3358         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3359         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3360
3361         for (i=0; i<info->count; i++) {
3362                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3363                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3364                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3365         }
3366 #endif
3367
3368         return WERR_OK;
3369 }
3370
3371 /*******************************************************************
3372  *
3373  * fill a notify_info struct with info asked
3374  *
3375  ********************************************************************/
3376
3377 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3378                                   struct spoolss_NotifyInfo *info,
3379                                   TALLOC_CTX *mem_ctx)
3380 {
3381         int snum;
3382         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3383         int i;
3384         uint32_t id;
3385         struct spoolss_NotifyOption *option;
3386         struct spoolss_NotifyOptionType option_type;
3387         int count,j;
3388         print_queue_struct *queue=NULL;
3389         print_status_struct status;
3390
3391         DEBUG(4,("printer_notify_info\n"));
3392
3393         if (!Printer)
3394                 return WERR_BADFID;
3395
3396         option = Printer->notify.option;
3397         id = 0x0;
3398
3399         info->version   = 2;
3400         info->notifies  = NULL;
3401         info->count     = 0;
3402
3403         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3404            sending a ffpcn() request first */
3405
3406         if ( !option )
3407                 return WERR_BADFID;
3408
3409         get_printer_snum(p, hnd, &snum, NULL);
3410
3411         for (i=0; i<option->count; i++) {
3412                 option_type = option->types[i];
3413
3414                 switch (option_type.type) {
3415                 case PRINTER_NOTIFY_TYPE:
3416                         if(construct_notify_printer_info(Printer, info, snum,
3417                                                          &option_type, id,
3418                                                          mem_ctx))
3419                                 id--;
3420                         break;
3421
3422                 case JOB_NOTIFY_TYPE: {
3423                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3424
3425                         count = print_queue_status(snum, &queue, &status);
3426
3427                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3428                                 goto done;
3429
3430                         for (j=0; j<count; j++) {
3431                                 construct_notify_jobs_info(&queue[j], info,
3432                                                            printer, snum,
3433                                                            &option_type,
3434                                                            queue[j].job,
3435                                                            mem_ctx);
3436                         }
3437
3438                         free_a_printer(&printer, 2);
3439
3440                 done:
3441                         SAFE_FREE(queue);
3442                         break;
3443                 }
3444                 }
3445         }
3446
3447         /*
3448          * Debugging information, don't delete.
3449          */
3450         /*
3451         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3452         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3453         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3454
3455         for (i=0; i<info->count; i++) {
3456                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3457                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3458                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3459         }
3460         */
3461         return WERR_OK;
3462 }
3463
3464 /****************************************************************
3465  _spoolss_RouterRefreshPrinterChangeNotify
3466 ****************************************************************/
3467
3468 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3469                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3470 {
3471         struct spoolss_NotifyInfo *info;
3472
3473         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3474         WERROR result = WERR_BADFID;
3475
3476         /* we always have a spoolss_NotifyInfo struct */
3477         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3478         if (!info) {
3479                 result = WERR_NOMEM;
3480                 goto done;
3481         }
3482
3483         *r->out.info = info;
3484
3485         if (!Printer) {
3486                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3487                         "Invalid handle (%s:%u:%u).\n",
3488                         OUR_HANDLE(r->in.handle)));
3489                 goto done;
3490         }
3491
3492         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3493
3494         /*
3495          *      We are now using the change value, and
3496          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3497          *      I don't have a global notification system, I'm sending back all the
3498          *      informations even when _NOTHING_ has changed.
3499          */
3500
3501         /* We need to keep track of the change value to send back in
3502            RRPCN replies otherwise our updates are ignored. */
3503
3504         Printer->notify.fnpcn = true;
3505
3506         if (Printer->notify.client_connected) {
3507                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3508                         "Saving change value in request [%x]\n",
3509                         r->in.change_low));
3510                 Printer->notify.change = r->in.change_low;
3511         }
3512
3513         /* just ignore the spoolss_NotifyOption */
3514
3515         switch (Printer->printer_type) {
3516                 case SPLHND_SERVER:
3517                         result = printserver_notify_info(p, r->in.handle,
3518                                                          info, p->mem_ctx);
3519                         break;
3520
3521                 case SPLHND_PRINTER:
3522                         result = printer_notify_info(p, r->in.handle,
3523                                                      info, p->mem_ctx);
3524                         break;
3525         }
3526
3527         Printer->notify.fnpcn = false;
3528
3529 done:
3530         return result;
3531 }
3532
3533 /********************************************************************
3534  * construct_printer_info_0
3535  * fill a printer_info_0 struct
3536  ********************************************************************/
3537
3538 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3539                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3540                                       struct spoolss_PrinterInfo0 *r,
3541                                       int snum)
3542 {
3543         int count;
3544         counter_printer_0 *session_counter;
3545         time_t setuptime;
3546         print_status_struct status;
3547
3548         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3549         W_ERROR_HAVE_NO_MEMORY(r->printername);
3550
3551         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3552         W_ERROR_HAVE_NO_MEMORY(r->servername);
3553
3554         count = print_queue_length(snum, &status);
3555
3556         /* check if we already have a counter for this printer */
3557         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3558                 if (session_counter->snum == snum)
3559                         break;
3560         }
3561
3562         /* it's the first time, add it to the list */
3563         if (session_counter == NULL) {
3564                 session_counter = SMB_MALLOC_P(counter_printer_0);
3565                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3566                 ZERO_STRUCTP(session_counter);
3567                 session_counter->snum           = snum;
3568                 session_counter->counter        = 0;
3569                 DLIST_ADD(counter_list, session_counter);
3570         }
3571
3572         /* increment it */
3573         session_counter->counter++;
3574
3575         r->cjobs                        = count;
3576         r->total_jobs                   = 0;
3577         r->total_bytes                  = 0;
3578
3579         setuptime = (time_t)ntprinter->info_2->setuptime;
3580
3581         init_systemtime(&r->time, gmtime(&setuptime));
3582
3583         /* JFM:
3584          * the global_counter should be stored in a TDB as it's common to all the clients
3585          * and should be zeroed on samba startup
3586          */
3587         r->global_counter               = session_counter->counter;
3588         r->total_pages                  = 0;
3589         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3590         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3591         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3592         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3593         r->spooling                     = 0;
3594         r->max_spooling                 = 0;
3595         r->session_counter              = session_counter->counter;
3596         r->num_error_out_of_paper       = 0x0;
3597         r->num_error_not_ready          = 0x0;          /* number of print failure */
3598         r->job_error                    = 0x0;
3599         r->number_of_processors         = 0x1;
3600         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3601         r->high_part_total_bytes        = 0x0;
3602         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3603         r->last_error                   = WERR_OK;
3604         r->status                       = nt_printq_status(status.status);
3605         r->enumerate_network_printers   = 0x0;
3606         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3607         r->processor_architecture       = 0x0;
3608         r->processor_level              = 0x6;          /* 6  ???*/
3609         r->ref_ic                       = 0;
3610         r->reserved2                    = 0;
3611         r->reserved3                    = 0;
3612
3613         return WERR_OK;
3614 }
3615
3616 /****************************************************************************
3617  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3618  should be valid upon entry
3619 ****************************************************************************/
3620
3621 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3622                                     struct spoolss_DeviceMode *r,
3623                                     const NT_DEVICEMODE *ntdevmode)
3624 {
3625         if (!r || !ntdevmode) {
3626                 return WERR_INVALID_PARAM;
3627         }
3628
3629         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3630         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3631
3632         r->specversion          = ntdevmode->specversion;
3633         r->driverversion        = ntdevmode->driverversion;
3634         r->size                 = ntdevmode->size;
3635         r->__driverextra_length = ntdevmode->driverextra;
3636         r->fields               = ntdevmode->fields;
3637
3638         r->orientation          = ntdevmode->orientation;
3639         r->papersize            = ntdevmode->papersize;
3640         r->paperlength          = ntdevmode->paperlength;
3641         r->paperwidth           = ntdevmode->paperwidth;
3642         r->scale                = ntdevmode->scale;
3643         r->copies               = ntdevmode->copies;
3644         r->defaultsource        = ntdevmode->defaultsource;
3645         r->printquality         = ntdevmode->printquality;
3646         r->color                = ntdevmode->color;
3647         r->duplex               = ntdevmode->duplex;
3648         r->yresolution          = ntdevmode->yresolution;
3649         r->ttoption             = ntdevmode->ttoption;
3650         r->collate              = ntdevmode->collate;
3651
3652         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3653         W_ERROR_HAVE_NO_MEMORY(r->formname);
3654
3655         r->logpixels            = ntdevmode->logpixels;
3656         r->bitsperpel           = ntdevmode->bitsperpel;
3657         r->pelswidth            = ntdevmode->pelswidth;
3658         r->pelsheight           = ntdevmode->pelsheight;
3659         r->displayflags         = ntdevmode->displayflags;
3660         r->displayfrequency     = ntdevmode->displayfrequency;
3661         r->icmmethod            = ntdevmode->icmmethod;
3662         r->icmintent            = ntdevmode->icmintent;
3663         r->mediatype            = ntdevmode->mediatype;
3664         r->dithertype           = ntdevmode->dithertype;
3665         r->reserved1            = ntdevmode->reserved1;
3666         r->reserved2            = ntdevmode->reserved2;
3667         r->panningwidth         = ntdevmode->panningwidth;
3668         r->panningheight        = ntdevmode->panningheight;
3669
3670         if (ntdevmode->nt_dev_private != NULL) {
3671                 r->driverextra_data = data_blob_talloc(mem_ctx,
3672                         ntdevmode->nt_dev_private,
3673                         ntdevmode->driverextra);
3674                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3675         }
3676
3677         return WERR_OK;
3678 }
3679
3680
3681 /****************************************************************************
3682  Create a spoolss_DeviceMode struct. Returns talloced memory.
3683 ****************************************************************************/
3684
3685 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3686                                               const char *servicename)
3687 {
3688         WERROR result;
3689         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3690         struct spoolss_DeviceMode *devmode = NULL;
3691
3692         DEBUG(7,("construct_dev_mode\n"));
3693
3694         DEBUGADD(8,("getting printer characteristics\n"));
3695
3696         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3697                 return NULL;
3698
3699         if (!printer->info_2->devmode) {
3700                 DEBUG(5, ("BONG! There was no device mode!\n"));
3701                 goto done;
3702         }
3703
3704         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3705         if (!devmode) {
3706                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3707                 goto done;
3708         }
3709
3710         DEBUGADD(8,("loading DEVICEMODE\n"));
3711
3712         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3713         if (!W_ERROR_IS_OK(result)) {
3714                 TALLOC_FREE(devmode);
3715         }
3716
3717 done:
3718         free_a_printer(&printer,2);
3719
3720         return devmode;
3721 }
3722
3723 /********************************************************************
3724  * construct_printer_info1
3725  * fill a spoolss_PrinterInfo1 struct
3726 ********************************************************************/
3727
3728 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3729                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3730                                       uint32_t flags,
3731                                       struct spoolss_PrinterInfo1 *r,
3732                                       int snum)
3733 {
3734         r->flags                = flags;
3735
3736         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3737                                                   ntprinter->info_2->printername,
3738                                                   ntprinter->info_2->drivername,
3739                                                   ntprinter->info_2->location);
3740         W_ERROR_HAVE_NO_MEMORY(r->description);
3741
3742         if (*ntprinter->info_2->comment == '\0') {
3743                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3744         } else {
3745                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3746         }
3747         W_ERROR_HAVE_NO_MEMORY(r->comment);
3748
3749         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3750         W_ERROR_HAVE_NO_MEMORY(r->name);
3751
3752         return WERR_OK;
3753 }
3754
3755 /********************************************************************
3756  * construct_printer_info2
3757  * fill a spoolss_PrinterInfo2 struct
3758 ********************************************************************/
3759
3760 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3761                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3762                                       struct spoolss_PrinterInfo2 *r,
3763                                       int snum)
3764 {
3765         int count;
3766
3767         print_status_struct status;
3768
3769         count = print_queue_length(snum, &status);
3770
3771         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3772         W_ERROR_HAVE_NO_MEMORY(r->servername);
3773         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3774         W_ERROR_HAVE_NO_MEMORY(r->printername);
3775         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3776         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3777         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3778         W_ERROR_HAVE_NO_MEMORY(r->portname);
3779         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3780         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3781
3782         if (*ntprinter->info_2->comment == '\0') {
3783                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3784         } else {
3785                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3786         }
3787         W_ERROR_HAVE_NO_MEMORY(r->comment);
3788
3789         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3790         W_ERROR_HAVE_NO_MEMORY(r->location);
3791         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3792         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3793         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3794         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3795         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3796         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3797         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3798         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3799
3800         r->attributes           = ntprinter->info_2->attributes;
3801
3802         r->priority             = ntprinter->info_2->priority;
3803         r->defaultpriority      = ntprinter->info_2->default_priority;
3804         r->starttime            = ntprinter->info_2->starttime;
3805         r->untiltime            = ntprinter->info_2->untiltime;
3806         r->status               = nt_printq_status(status.status);
3807         r->cjobs                = count;
3808         r->averageppm           = ntprinter->info_2->averageppm;
3809
3810         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3811         if (!r->devmode) {
3812                 DEBUG(8,("Returning NULL Devicemode!\n"));
3813         }
3814
3815         r->secdesc              = NULL;
3816
3817         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3818                 /* don't use talloc_steal() here unless you do a deep steal of all
3819                    the SEC_DESC members */
3820
3821                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3822         }
3823
3824         return WERR_OK;
3825 }
3826
3827 /********************************************************************
3828  * construct_printer_info3
3829  * fill a spoolss_PrinterInfo3 struct
3830  ********************************************************************/
3831
3832 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3833                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3834                                       struct spoolss_PrinterInfo3 *r,
3835                                       int snum)
3836 {
3837         /* These are the components of the SD we are returning. */
3838
3839         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3840                 /* don't use talloc_steal() here unless you do a deep steal of all
3841                    the SEC_DESC members */
3842
3843                 r->secdesc = dup_sec_desc(mem_ctx,
3844                                           ntprinter->info_2->secdesc_buf->sd);
3845                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3846         }
3847
3848         return WERR_OK;
3849 }
3850
3851 /********************************************************************
3852  * construct_printer_info4
3853  * fill a spoolss_PrinterInfo4 struct
3854  ********************************************************************/
3855
3856 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3857                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3858                                       struct spoolss_PrinterInfo4 *r,
3859                                       int snum)
3860 {
3861         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3862         W_ERROR_HAVE_NO_MEMORY(r->printername);
3863         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3864         W_ERROR_HAVE_NO_MEMORY(r->servername);
3865
3866         r->attributes   = ntprinter->info_2->attributes;
3867
3868         return WERR_OK;
3869 }
3870
3871 /********************************************************************
3872  * construct_printer_info5
3873  * fill a spoolss_PrinterInfo5 struct
3874  ********************************************************************/
3875
3876 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3877                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3878                                       struct spoolss_PrinterInfo5 *r,
3879                                       int snum)
3880 {
3881         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3882         W_ERROR_HAVE_NO_MEMORY(r->printername);
3883         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3884         W_ERROR_HAVE_NO_MEMORY(r->portname);
3885
3886         r->attributes   = ntprinter->info_2->attributes;
3887
3888         /* these two are not used by NT+ according to MSDN */
3889
3890         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3891         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3892
3893         return WERR_OK;
3894 }
3895
3896 /********************************************************************
3897  * construct_printer_info_6
3898  * fill a spoolss_PrinterInfo6 struct
3899  ********************************************************************/
3900
3901 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3902                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3903                                       struct spoolss_PrinterInfo6 *r,
3904                                       int snum)
3905 {
3906         int count;
3907         print_status_struct status;
3908
3909         count = print_queue_length(snum, &status);
3910
3911         r->status = nt_printq_status(status.status);
3912
3913         return WERR_OK;
3914 }
3915
3916 /********************************************************************
3917  * construct_printer_info7
3918  * fill a spoolss_PrinterInfo7 struct
3919  ********************************************************************/
3920
3921 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3922                                       Printer_entry *print_hnd,
3923                                       struct spoolss_PrinterInfo7 *r,
3924                                       int snum)
3925 {
3926         struct GUID guid;
3927
3928         if (is_printer_published(print_hnd, snum, &guid)) {
3929                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3930                 r->action = DSPRINT_PUBLISH;
3931         } else {
3932                 r->guid = talloc_strdup(mem_ctx, "");
3933                 r->action = DSPRINT_UNPUBLISH;
3934         }
3935         W_ERROR_HAVE_NO_MEMORY(r->guid);
3936
3937         return WERR_OK;
3938 }
3939
3940 /********************************************************************
3941  * construct_printer_info8
3942  * fill a spoolss_PrinterInfo8 struct
3943  ********************************************************************/
3944
3945 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3946                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3947                                       struct spoolss_DeviceModeInfo *r,
3948                                       int snum)
3949 {
3950         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3951         if (!r->devmode) {
3952                 DEBUG(8,("Returning NULL Devicemode!\n"));
3953         }
3954
3955         return WERR_OK;
3956 }
3957
3958
3959 /********************************************************************
3960 ********************************************************************/
3961
3962 static bool snum_is_shared_printer(int snum)
3963 {
3964         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3965 }
3966
3967 /********************************************************************
3968  Spoolss_enumprinters.
3969 ********************************************************************/
3970
3971 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3972                                            uint32_t level,
3973                                            uint32_t flags,
3974                                            union spoolss_PrinterInfo **info_p,
3975                                            uint32_t *count_p)
3976 {
3977         int snum;
3978         int n_services = lp_numservices();
3979         union spoolss_PrinterInfo *info = NULL;
3980         uint32_t count = 0;
3981         WERROR result = WERR_OK;
3982
3983         *count_p = 0;
3984         *info_p = NULL;
3985
3986         for (snum = 0; snum < n_services; snum++) {
3987
3988                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3989
3990                 if (!snum_is_shared_printer(snum)) {
3991                         continue;
3992                 }
3993
3994                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3995                         lp_servicename(snum), snum));
3996
3997                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3998                                             union spoolss_PrinterInfo,
3999                                             count + 1);
4000                 if (!info) {
4001                         result = WERR_NOMEM;
4002                         goto out;
4003                 }
4004
4005                 result = get_a_printer(NULL, &ntprinter, 2,
4006                                        lp_const_servicename(snum));
4007                 if (!W_ERROR_IS_OK(result)) {
4008                         goto out;
4009                 }
4010
4011                 switch (level) {
4012                 case 0:
4013                         result = construct_printer_info0(info, ntprinter,
4014                                                          &info[count].info0, snum);
4015                         break;
4016                 case 1:
4017                         result = construct_printer_info1(info, ntprinter, flags,
4018                                                          &info[count].info1, snum);
4019                         break;
4020                 case 2:
4021                         result = construct_printer_info2(info, ntprinter,
4022                                                          &info[count].info2, snum);
4023                         break;
4024                 case 4:
4025                         result = construct_printer_info4(info, ntprinter,
4026                                                          &info[count].info4, snum);
4027                         break;
4028                 case 5:
4029                         result = construct_printer_info5(info, ntprinter,
4030                                                          &info[count].info5, snum);
4031                         break;
4032
4033                 default:
4034                         result = WERR_UNKNOWN_LEVEL;
4035                         free_a_printer(&ntprinter, 2);
4036                         goto out;
4037                 }
4038
4039                 free_a_printer(&ntprinter, 2);
4040                 if (!W_ERROR_IS_OK(result)) {
4041                         goto out;
4042                 }
4043
4044                 count++;
4045         }
4046
4047         *count_p = count;
4048         *info_p = info;
4049
4050  out:
4051         if (!W_ERROR_IS_OK(result)) {
4052                 TALLOC_FREE(info);
4053                 return result;
4054         }
4055
4056         *info_p = info;
4057
4058         return WERR_OK;
4059 }
4060
4061 /********************************************************************
4062  * handle enumeration of printers at level 0
4063  ********************************************************************/
4064
4065 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4066                                   uint32_t flags,
4067                                   const char *servername,
4068                                   union spoolss_PrinterInfo **info,
4069                                   uint32_t *count)
4070 {
4071         DEBUG(4,("enum_all_printers_info_0\n"));
4072
4073         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4074 }
4075
4076
4077 /********************************************************************
4078 ********************************************************************/
4079
4080 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4081                                        uint32_t flags,
4082                                        union spoolss_PrinterInfo **info,
4083                                        uint32_t *count)
4084 {
4085         DEBUG(4,("enum_all_printers_info_1\n"));
4086
4087         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4088 }
4089
4090 /********************************************************************
4091  enum_all_printers_info_1_local.
4092 *********************************************************************/
4093
4094 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4095                                              union spoolss_PrinterInfo **info,
4096                                              uint32_t *count)
4097 {
4098         DEBUG(4,("enum_all_printers_info_1_local\n"));
4099
4100         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4101 }
4102
4103 /********************************************************************
4104  enum_all_printers_info_1_name.
4105 *********************************************************************/
4106
4107 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4108                                             const char *name,
4109                                             union spoolss_PrinterInfo **info,
4110                                             uint32_t *count)
4111 {
4112         const char *s = name;
4113
4114         DEBUG(4,("enum_all_printers_info_1_name\n"));
4115
4116         if ((name[0] == '\\') && (name[1] == '\\')) {
4117                 s = name + 2;
4118         }
4119
4120         if (!is_myname_or_ipaddr(s)) {
4121                 return WERR_INVALID_NAME;
4122         }
4123
4124         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4125 }
4126
4127 /********************************************************************
4128  enum_all_printers_info_1_network.
4129 *********************************************************************/
4130
4131 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4132                                                const char *name,
4133                                                union spoolss_PrinterInfo **info,
4134                                                uint32_t *count)
4135 {
4136         const char *s = name;
4137
4138         DEBUG(4,("enum_all_printers_info_1_network\n"));
4139
4140         /* If we respond to a enum_printers level 1 on our name with flags
4141            set to PRINTER_ENUM_REMOTE with a list of printers then these
4142            printers incorrectly appear in the APW browse list.
4143            Specifically the printers for the server appear at the workgroup
4144            level where all the other servers in the domain are
4145            listed. Windows responds to this call with a
4146            WERR_CAN_NOT_COMPLETE so we should do the same. */
4147
4148         if (name[0] == '\\' && name[1] == '\\') {
4149                  s = name + 2;
4150         }
4151
4152         if (is_myname_or_ipaddr(s)) {
4153                  return WERR_CAN_NOT_COMPLETE;
4154         }
4155
4156         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4157 }
4158
4159 /********************************************************************
4160  * api_spoolss_enumprinters
4161  *
4162  * called from api_spoolss_enumprinters (see this to understand)
4163  ********************************************************************/
4164
4165 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4166                                        union spoolss_PrinterInfo **info,
4167                                        uint32_t *count)
4168 {
4169         DEBUG(4,("enum_all_printers_info_2\n"));
4170
4171         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4172 }
4173
4174 /********************************************************************
4175  * handle enumeration of printers at level 1
4176  ********************************************************************/
4177
4178 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4179                                   uint32_t flags,
4180                                   const char *name,
4181                                   union spoolss_PrinterInfo **info,
4182                                   uint32_t *count)
4183 {
4184         /* Not all the flags are equals */
4185
4186         if (flags & PRINTER_ENUM_LOCAL) {
4187                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4188         }
4189
4190         if (flags & PRINTER_ENUM_NAME) {
4191                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4192         }
4193
4194         if (flags & PRINTER_ENUM_NETWORK) {
4195                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4196         }
4197
4198         return WERR_OK; /* NT4sp5 does that */
4199 }
4200
4201 /********************************************************************
4202  * handle enumeration of printers at level 2
4203  ********************************************************************/
4204
4205 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4206                                   uint32_t flags,
4207                                   const char *servername,
4208                                   union spoolss_PrinterInfo **info,
4209                                   uint32_t *count)
4210 {
4211         if (flags & PRINTER_ENUM_LOCAL) {
4212                 return enum_all_printers_info_2(mem_ctx, info, count);
4213         }
4214
4215         if (flags & PRINTER_ENUM_NAME) {
4216                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4217                         return WERR_INVALID_NAME;
4218                 }
4219
4220                 return enum_all_printers_info_2(mem_ctx, info, count);
4221         }
4222
4223         if (flags & PRINTER_ENUM_REMOTE) {
4224                 return WERR_UNKNOWN_LEVEL;
4225         }
4226
4227         return WERR_OK;
4228 }
4229
4230 /********************************************************************
4231  * handle enumeration of printers at level 4
4232  ********************************************************************/
4233
4234 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4235                                   uint32_t flags,
4236                                   const char *servername,
4237                                   union spoolss_PrinterInfo **info,
4238                                   uint32_t *count)
4239 {
4240         DEBUG(4,("enum_all_printers_info_4\n"));
4241
4242         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4243 }
4244
4245
4246 /********************************************************************
4247  * handle enumeration of printers at level 5
4248  ********************************************************************/
4249
4250 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4251                                   uint32_t flags,
4252                                   const char *servername,
4253                                   union spoolss_PrinterInfo **info,
4254                                   uint32_t *count)
4255 {
4256         DEBUG(4,("enum_all_printers_info_5\n"));
4257
4258         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4259 }
4260
4261 /****************************************************************
4262  _spoolss_EnumPrinters
4263 ****************************************************************/
4264
4265 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4266                              struct spoolss_EnumPrinters *r)
4267 {
4268         const char *name = NULL;
4269         WERROR result;
4270
4271         /* that's an [in out] buffer */
4272
4273         if (!r->in.buffer && (r->in.offered != 0)) {
4274                 return WERR_INVALID_PARAM;
4275         }
4276
4277         DEBUG(4,("_spoolss_EnumPrinters\n"));
4278
4279         *r->out.needed = 0;
4280         *r->out.count = 0;
4281         *r->out.info = NULL;
4282
4283         /*
4284          * Level 1:
4285          *          flags==PRINTER_ENUM_NAME
4286          *           if name=="" then enumerates all printers
4287          *           if name!="" then enumerate the printer
4288          *          flags==PRINTER_ENUM_REMOTE
4289          *          name is NULL, enumerate printers
4290          * Level 2: name!="" enumerates printers, name can't be NULL
4291          * Level 3: doesn't exist
4292          * Level 4: does a local registry lookup
4293          * Level 5: same as Level 2
4294          */
4295
4296         if (r->in.server) {
4297                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4298                 W_ERROR_HAVE_NO_MEMORY(name);
4299         }
4300
4301         switch (r->in.level) {
4302         case 0:
4303                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4304                                              r->out.info, r->out.count);
4305                 break;
4306         case 1:
4307                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4308                                              r->out.info, r->out.count);
4309                 break;
4310         case 2:
4311                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4312                                              r->out.info, r->out.count);
4313                 break;
4314         case 4:
4315                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4316                                              r->out.info, r->out.count);
4317                 break;
4318         case 5:
4319                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4320                                              r->out.info, r->out.count);
4321                 break;
4322         default:
4323                 return WERR_UNKNOWN_LEVEL;
4324         }
4325
4326         if (!W_ERROR_IS_OK(result)) {
4327                 return result;
4328         }
4329
4330         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4331                                                      spoolss_EnumPrinters, NULL,
4332                                                      *r->out.info, r->in.level,
4333                                                      *r->out.count);
4334         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4335         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4336
4337         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4338 }
4339
4340 /****************************************************************
4341  _spoolss_GetPrinter
4342 ****************************************************************/
4343
4344 WERROR _spoolss_GetPrinter(pipes_struct *p,
4345                            struct spoolss_GetPrinter *r)
4346 {
4347         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4348         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4349         WERROR result = WERR_OK;
4350
4351         int snum;
4352
4353         /* that's an [in out] buffer */
4354
4355         if (!r->in.buffer && (r->in.offered != 0)) {
4356                 return WERR_INVALID_PARAM;
4357         }
4358
4359         *r->out.needed = 0;
4360
4361         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4362                 return WERR_BADFID;
4363         }
4364
4365         result = get_a_printer(Printer, &ntprinter, 2,
4366                                lp_const_servicename(snum));
4367         if (!W_ERROR_IS_OK(result)) {
4368                 return result;
4369         }
4370
4371         switch (r->in.level) {
4372         case 0:
4373                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4374                                                  &r->out.info->info0, snum);
4375                 break;
4376         case 1:
4377                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4378                                                  PRINTER_ENUM_ICON8,
4379                                                  &r->out.info->info1, snum);
4380                 break;
4381         case 2:
4382                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4383                                                  &r->out.info->info2, snum);
4384                 break;
4385         case 3:
4386                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4387                                                  &r->out.info->info3, snum);
4388                 break;
4389         case 4:
4390                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4391                                                  &r->out.info->info4, snum);
4392                 break;
4393         case 5:
4394                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4395                                                  &r->out.info->info5, snum);
4396                 break;
4397         case 6:
4398                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4399                                                  &r->out.info->info6, snum);
4400                 break;
4401         case 7:
4402                 result = construct_printer_info7(p->mem_ctx, Printer,
4403                                                  &r->out.info->info7, snum);
4404                 break;
4405         case 8:
4406                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4407                                                  &r->out.info->info8, snum);
4408                 break;
4409         default:
4410                 result = WERR_UNKNOWN_LEVEL;
4411                 break;
4412         }
4413
4414         free_a_printer(&ntprinter, 2);
4415
4416         if (!W_ERROR_IS_OK(result)) {
4417                 TALLOC_FREE(r->out.info);
4418                 return result;
4419         }
4420
4421         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4422                                                r->out.info, r->in.level);
4423         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4424
4425         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4426 }
4427
4428 /********************************************************************
4429  ********************************************************************/
4430
4431 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4432                                                   const char **string_array,
4433                                                   const char *cservername)
4434 {
4435         int i, num_strings = 0;
4436         const char **array = NULL;
4437
4438         if (!string_array) {
4439                 return NULL;
4440         }
4441
4442         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4443
4444                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4445                                                   cservername, string_array[i]);
4446                 if (!str) {
4447                         TALLOC_FREE(array);
4448                         return NULL;
4449                 }
4450
4451
4452                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4453                         TALLOC_FREE(array);
4454                         return NULL;
4455                 }
4456         }
4457
4458         if (i > 0) {
4459                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4460                              &array, &num_strings);
4461         }
4462
4463         return array;
4464 }
4465
4466 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4467         do { \
4468                 if (in && strlen(in)) { \
4469                         out = talloc_strdup(mem_ctx, in); \
4470                         W_ERROR_HAVE_NO_MEMORY(out); \
4471                 } else { \
4472                         out = NULL; \
4473                 } \
4474         } while (0);
4475
4476 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4477         do { \
4478                 if (in && strlen(in)) { \
4479                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4480                 } else { \
4481                         out = talloc_strdup(mem_ctx, ""); \
4482                 } \
4483                 W_ERROR_HAVE_NO_MEMORY(out); \
4484         } while (0);
4485
4486 /********************************************************************
4487  * fill a spoolss_DriverInfo1 struct
4488  ********************************************************************/
4489
4490 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4491                                         struct spoolss_DriverInfo1 *r,
4492                                         const struct spoolss_DriverInfo8 *driver,
4493                                         const char *servername)
4494 {
4495         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4496         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4497
4498         return WERR_OK;
4499 }
4500
4501 /********************************************************************
4502  * fill a spoolss_DriverInfo2 struct
4503  ********************************************************************/
4504
4505 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4506                                         struct spoolss_DriverInfo2 *r,
4507                                         const struct spoolss_DriverInfo8 *driver,
4508                                         const char *servername)
4509
4510 {
4511         const char *cservername = canon_servername(servername);
4512
4513         r->version              = driver->version;
4514
4515         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4516         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4517         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4518         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4519
4520         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4521                                driver->driver_path,
4522                                r->driver_path);
4523
4524         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4525                                driver->data_file,
4526                                r->data_file);
4527
4528         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4529                                driver->config_file,
4530                                r->config_file);
4531
4532         return WERR_OK;
4533 }
4534
4535 /********************************************************************
4536  * fill a spoolss_DriverInfo3 struct
4537  ********************************************************************/
4538
4539 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4540                                         struct spoolss_DriverInfo3 *r,
4541                                         const struct spoolss_DriverInfo8 *driver,
4542                                         const char *servername)
4543 {
4544         const char *cservername = canon_servername(servername);
4545
4546         r->version              = driver->version;
4547
4548         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4549         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4550         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4551         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4552
4553         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4554                                driver->driver_path,
4555                                r->driver_path);
4556
4557         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4558                                driver->data_file,
4559                                r->data_file);
4560
4561         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4562                                driver->config_file,
4563                                r->config_file);
4564
4565         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4566                                driver->help_file,
4567                                r->help_file);
4568
4569         FILL_DRIVER_STRING(mem_ctx,
4570                            driver->monitor_name,
4571                            r->monitor_name);
4572
4573         FILL_DRIVER_STRING(mem_ctx,
4574                            driver->default_datatype,
4575                            r->default_datatype);
4576
4577         r->dependent_files = string_array_from_driver_info(mem_ctx,
4578                                                            driver->dependent_files,
4579                                                            cservername);
4580         return WERR_OK;
4581 }
4582
4583 /********************************************************************
4584  * fill a spoolss_DriverInfo4 struct
4585  ********************************************************************/
4586
4587 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4588                                         struct spoolss_DriverInfo4 *r,
4589                                         const struct spoolss_DriverInfo8 *driver,
4590                                         const char *servername)
4591 {
4592         const char *cservername = canon_servername(servername);
4593
4594         r->version              = driver->version;
4595
4596         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4597         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4598         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4599         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4600
4601         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4602                                driver->driver_path,
4603                                r->driver_path);
4604
4605         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4606                                driver->data_file,
4607                                r->data_file);
4608
4609         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4610                                driver->config_file,
4611                                r->config_file);
4612
4613         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4614                                driver->help_file,
4615                                r->help_file);
4616
4617         r->dependent_files = string_array_from_driver_info(mem_ctx,
4618                                                            driver->dependent_files,
4619                                                            cservername);
4620
4621         FILL_DRIVER_STRING(mem_ctx,
4622                            driver->monitor_name,
4623                            r->monitor_name);
4624
4625         FILL_DRIVER_STRING(mem_ctx,
4626                            driver->default_datatype,
4627                            r->default_datatype);
4628
4629         r->previous_names = string_array_from_driver_info(mem_ctx,
4630                                                           driver->previous_names,
4631                                                           cservername);
4632
4633         return WERR_OK;
4634 }
4635
4636 /********************************************************************
4637  * fill a spoolss_DriverInfo5 struct
4638  ********************************************************************/
4639
4640 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4641                                         struct spoolss_DriverInfo5 *r,
4642                                         const struct spoolss_DriverInfo8 *driver,
4643                                         const char *servername)
4644 {
4645         const char *cservername = canon_servername(servername);
4646
4647         r->version              = driver->version;
4648
4649         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4650         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4651         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4652         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4653
4654         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4655                                driver->driver_path,
4656                                r->driver_path);
4657
4658         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4659                                driver->data_file,
4660                                r->data_file);
4661
4662         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4663                                driver->config_file,
4664                                r->config_file);
4665
4666         r->driver_attributes    = 0;
4667         r->config_version       = 0;
4668         r->driver_version       = 0;
4669
4670         return WERR_OK;
4671 }
4672 /********************************************************************
4673  * fill a spoolss_DriverInfo6 struct
4674  ********************************************************************/
4675
4676 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4677                                         struct spoolss_DriverInfo6 *r,
4678                                         const struct spoolss_DriverInfo8 *driver,
4679                                         const char *servername)
4680 {
4681         const char *cservername = canon_servername(servername);
4682
4683         r->version              = driver->version;
4684
4685         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4686         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4687         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4688         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4689
4690         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4691                                driver->driver_path,
4692                                r->driver_path);
4693
4694         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4695                                driver->data_file,
4696                                r->data_file);
4697
4698         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4699                                driver->config_file,
4700                                r->config_file);
4701
4702         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4703                                driver->help_file,
4704                                r->help_file);
4705
4706         FILL_DRIVER_STRING(mem_ctx,
4707                            driver->monitor_name,
4708                            r->monitor_name);
4709
4710         FILL_DRIVER_STRING(mem_ctx,
4711                            driver->default_datatype,
4712                            r->default_datatype);
4713
4714         r->dependent_files = string_array_from_driver_info(mem_ctx,
4715                                                            driver->dependent_files,
4716                                                            cservername);
4717         r->previous_names = string_array_from_driver_info(mem_ctx,
4718                                                           driver->previous_names,
4719                                                           cservername);
4720
4721         r->driver_date          = driver->driver_date;
4722         r->driver_version       = driver->driver_version;
4723
4724         FILL_DRIVER_STRING(mem_ctx,
4725                            driver->manufacturer_name,
4726                            r->manufacturer_name);
4727         FILL_DRIVER_STRING(mem_ctx,
4728                            driver->manufacturer_url,
4729                            r->manufacturer_url);
4730         FILL_DRIVER_STRING(mem_ctx,
4731                            driver->hardware_id,
4732                            r->hardware_id);
4733         FILL_DRIVER_STRING(mem_ctx,
4734                            driver->provider,
4735                            r->provider);
4736
4737         return WERR_OK;
4738 }
4739
4740 /********************************************************************
4741  * fill a spoolss_DriverInfo8 struct
4742  ********************************************************************/
4743
4744 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4745                                         struct spoolss_DriverInfo8 *r,
4746                                         const struct spoolss_DriverInfo8 *driver,
4747                                         const char *servername)
4748 {
4749         const char *cservername = canon_servername(servername);
4750
4751         r->version              = driver->version;
4752
4753         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4754         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4755         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4756         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4757
4758         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4759                                driver->driver_path,
4760                                r->driver_path);
4761
4762         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4763                                driver->data_file,
4764                                r->data_file);
4765
4766         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4767                                driver->config_file,
4768                                r->config_file);
4769
4770         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4771                                driver->help_file,
4772                                r->help_file);
4773
4774         FILL_DRIVER_STRING(mem_ctx,
4775                            driver->monitor_name,
4776                            r->monitor_name);
4777
4778         FILL_DRIVER_STRING(mem_ctx,
4779                            driver->default_datatype,
4780                            r->default_datatype);
4781
4782         r->dependent_files = string_array_from_driver_info(mem_ctx,
4783                                                            driver->dependent_files,
4784                                                            cservername);
4785         r->previous_names = string_array_from_driver_info(mem_ctx,
4786                                                           driver->previous_names,
4787                                                           cservername);
4788
4789         r->driver_date          = driver->driver_date;
4790         r->driver_version       = driver->driver_version;
4791
4792         FILL_DRIVER_STRING(mem_ctx,
4793                            driver->manufacturer_name,
4794                            r->manufacturer_name);
4795         FILL_DRIVER_STRING(mem_ctx,
4796                            driver->manufacturer_url,
4797                            r->manufacturer_url);
4798         FILL_DRIVER_STRING(mem_ctx,
4799                            driver->hardware_id,
4800                            r->hardware_id);
4801         FILL_DRIVER_STRING(mem_ctx,
4802                            driver->provider,
4803                            r->provider);
4804
4805         FILL_DRIVER_STRING(mem_ctx,
4806                            driver->print_processor,
4807                            r->print_processor);
4808         FILL_DRIVER_STRING(mem_ctx,
4809                            driver->vendor_setup,
4810                            r->vendor_setup);
4811
4812         r->color_profiles = string_array_from_driver_info(mem_ctx,
4813                                                           driver->color_profiles,
4814                                                           cservername);
4815
4816         FILL_DRIVER_STRING(mem_ctx,
4817                            driver->inf_path,
4818                            r->inf_path);
4819
4820         r->printer_driver_attributes    = driver->printer_driver_attributes;
4821
4822         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4823                                                                     driver->core_driver_dependencies,
4824                                                                     cservername);
4825
4826         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4827         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4828
4829         return WERR_OK;
4830 }
4831
4832 #if 0 /* disabled until marshalling issues are resolved - gd */
4833 /********************************************************************
4834  ********************************************************************/
4835
4836 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4837                                           struct spoolss_DriverFileInfo *r,
4838                                           const char *cservername,
4839                                           const char *file_name,
4840                                           enum spoolss_DriverFileType file_type,
4841                                           uint32_t file_version)
4842 {
4843         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4844                                           cservername, file_name);
4845         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4846         r->file_type    = file_type;
4847         r->file_version = file_version;
4848
4849         return WERR_OK;
4850 }
4851
4852 /********************************************************************
4853  ********************************************************************/
4854
4855 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4856                                                  const struct spoolss_DriverInfo8 *driver,
4857                                                  const char *cservername,
4858                                                  struct spoolss_DriverFileInfo **info_p,
4859                                                  uint32_t *count_p)
4860 {
4861         struct spoolss_DriverFileInfo *info = NULL;
4862         uint32_t count = 0;
4863         WERROR result;
4864         uint32_t i;
4865
4866         *info_p = NULL;
4867         *count_p = 0;
4868
4869         if (strlen(driver->driver_path)) {
4870                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4871                                             struct spoolss_DriverFileInfo,
4872                                             count + 1);
4873                 W_ERROR_HAVE_NO_MEMORY(info);
4874                 result = fill_spoolss_DriverFileInfo(info,
4875                                                      &info[count],
4876                                                      cservername,
4877                                                      driver->driver_path,
4878                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4879                                                      0);
4880                 W_ERROR_NOT_OK_RETURN(result);
4881                 count++;
4882         }
4883
4884         if (strlen(driver->config_file)) {
4885                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4886                                             struct spoolss_DriverFileInfo,
4887                                             count + 1);
4888                 W_ERROR_HAVE_NO_MEMORY(info);
4889                 result = fill_spoolss_DriverFileInfo(info,
4890                                                      &info[count],
4891                                                      cservername,
4892                                                      driver->config_file,
4893                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4894                                                      0);
4895                 W_ERROR_NOT_OK_RETURN(result);
4896                 count++;
4897         }
4898
4899         if (strlen(driver->data_file)) {
4900                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4901                                             struct spoolss_DriverFileInfo,
4902                                             count + 1);
4903                 W_ERROR_HAVE_NO_MEMORY(info);
4904                 result = fill_spoolss_DriverFileInfo(info,
4905                                                      &info[count],
4906                                                      cservername,
4907                                                      driver->data_file,
4908                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4909                                                      0);
4910                 W_ERROR_NOT_OK_RETURN(result);
4911                 count++;
4912         }
4913
4914         if (strlen(driver->help_file)) {
4915                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4916                                             struct spoolss_DriverFileInfo,
4917                                             count + 1);
4918                 W_ERROR_HAVE_NO_MEMORY(info);
4919                 result = fill_spoolss_DriverFileInfo(info,
4920                                                      &info[count],
4921                                                      cservername,
4922                                                      driver->help_file,
4923                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4924                                                      0);
4925                 W_ERROR_NOT_OK_RETURN(result);
4926                 count++;
4927         }
4928
4929         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4930                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4931                                             struct spoolss_DriverFileInfo,
4932                                             count + 1);
4933                 W_ERROR_HAVE_NO_MEMORY(info);
4934                 result = fill_spoolss_DriverFileInfo(info,
4935                                                      &info[count],
4936                                                      cservername,
4937                                                      driver->dependent_files[i],
4938                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4939                                                      0);
4940                 W_ERROR_NOT_OK_RETURN(result);
4941                 count++;
4942         }
4943
4944         *info_p = info;
4945         *count_p = count;
4946
4947         return WERR_OK;
4948 }
4949
4950 /********************************************************************
4951  * fill a spoolss_DriverInfo101 struct
4952  ********************************************************************/
4953
4954 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4955                                           struct spoolss_DriverInfo101 *r,
4956                                           const struct spoolss_DriverInfo8 *driver,
4957                                           const char *servername)
4958 {
4959         const char *cservername = canon_servername(servername);
4960         WERROR result;
4961
4962         r->version              = driver->version;
4963
4964         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4965         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4966         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4967         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4968
4969         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4970                                                     cservername,
4971                                                     &r->file_info,
4972                                                     &r->file_count);
4973         if (!W_ERROR_IS_OK(result)) {
4974                 return result;
4975         }
4976
4977         FILL_DRIVER_STRING(mem_ctx,
4978                            driver->monitor_name,
4979                            r->monitor_name);
4980
4981         FILL_DRIVER_STRING(mem_ctx,
4982                            driver->default_datatype,
4983                            r->default_datatype);
4984
4985         r->previous_names = string_array_from_driver_info(mem_ctx,
4986                                                           driver->previous_names,
4987                                                           cservername);
4988         r->driver_date          = driver->driver_date;
4989         r->driver_version       = driver->driver_version;
4990
4991         FILL_DRIVER_STRING(mem_ctx,
4992                            driver->manufacturer_name,
4993                            r->manufacturer_name);
4994         FILL_DRIVER_STRING(mem_ctx,
4995                            driver->manufacturer_url,
4996                            r->manufacturer_url);
4997         FILL_DRIVER_STRING(mem_ctx,
4998                            driver->hardware_id,
4999                            r->hardware_id);
5000         FILL_DRIVER_STRING(mem_ctx,
5001                            driver->provider,
5002                            r->provider);
5003
5004         return WERR_OK;
5005 }
5006 #endif
5007 /********************************************************************
5008  ********************************************************************/
5009
5010 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5011                                                   uint32_t level,
5012                                                   union spoolss_DriverInfo *r,
5013                                                   int snum,
5014                                                   const char *servername,
5015                                                   const char *architecture,
5016                                                   uint32_t version)
5017 {
5018         NT_PRINTER_INFO_LEVEL *printer = NULL;
5019         struct spoolss_DriverInfo8 *driver;
5020         WERROR result;
5021
5022         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5023
5024         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5025                 win_errstr(result)));
5026
5027         if (!W_ERROR_IS_OK(result)) {
5028                 return WERR_INVALID_PRINTER_NAME;
5029         }
5030
5031         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5032                                       architecture, version);
5033
5034         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5035                 win_errstr(result)));
5036
5037         if (!W_ERROR_IS_OK(result)) {
5038                 /*
5039                  * Is this a W2k client ?
5040                  */
5041
5042                 if (version < 3) {
5043                         free_a_printer(&printer, 2);
5044                         return WERR_UNKNOWN_PRINTER_DRIVER;
5045                 }
5046
5047                 /* Yes - try again with a WinNT driver. */
5048                 version = 2;
5049                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5050                                               architecture, version);
5051                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5052                         win_errstr(result)));
5053                 if (!W_ERROR_IS_OK(result)) {
5054                         free_a_printer(&printer, 2);
5055                         return WERR_UNKNOWN_PRINTER_DRIVER;
5056                 }
5057         }
5058
5059         switch (level) {
5060         case 1:
5061                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5062                 break;
5063         case 2:
5064                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5065                 break;
5066         case 3:
5067                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5068                 break;
5069         case 4:
5070                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5071                 break;
5072         case 5:
5073                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5074                 break;
5075         case 6:
5076                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5077                 break;
5078         case 8:
5079                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5080                 break;
5081 #if 0 /* disabled until marshalling issues are resolved - gd */
5082         case 101:
5083                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5084                 break;
5085 #endif
5086         default:
5087                 result = WERR_UNKNOWN_LEVEL;
5088                 break;
5089         }
5090
5091         free_a_printer(&printer, 2);
5092         free_a_printer_driver(driver);
5093
5094         return result;
5095 }
5096
5097 /****************************************************************
5098  _spoolss_GetPrinterDriver2
5099 ****************************************************************/
5100
5101 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5102                                   struct spoolss_GetPrinterDriver2 *r)
5103 {
5104         Printer_entry *printer;
5105         WERROR result;
5106
5107         const char *servername;
5108         int snum;
5109
5110         /* that's an [in out] buffer */
5111
5112         if (!r->in.buffer && (r->in.offered != 0)) {
5113                 return WERR_INVALID_PARAM;
5114         }
5115
5116         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5117
5118         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5119                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5120                 return WERR_INVALID_PRINTER_NAME;
5121         }
5122
5123         *r->out.needed = 0;
5124         *r->out.server_major_version = 0;
5125         *r->out.server_minor_version = 0;
5126
5127         servername = get_server_name(printer);
5128
5129         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5130                 return WERR_BADFID;
5131         }
5132
5133         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5134                                                      r->out.info, snum,
5135                                                      servername,
5136                                                      r->in.architecture,
5137                                                      r->in.client_major_version);
5138         if (!W_ERROR_IS_OK(result)) {
5139                 TALLOC_FREE(r->out.info);
5140                 return result;
5141         }
5142
5143         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5144                                                r->out.info, r->in.level);
5145         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5146
5147         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5148 }
5149
5150
5151 /****************************************************************
5152  _spoolss_StartPagePrinter
5153 ****************************************************************/
5154
5155 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5156                                  struct spoolss_StartPagePrinter *r)
5157 {
5158         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5159
5160         if (!Printer) {
5161                 DEBUG(3,("_spoolss_StartPagePrinter: "
5162                         "Error in startpageprinter printer handle\n"));
5163                 return WERR_BADFID;
5164         }
5165
5166         Printer->page_started = true;
5167         return WERR_OK;
5168 }
5169
5170 /****************************************************************
5171  _spoolss_EndPagePrinter
5172 ****************************************************************/
5173
5174 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5175                                struct spoolss_EndPagePrinter *r)
5176 {
5177         int snum;
5178
5179         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5180
5181         if (!Printer) {
5182                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5183                         OUR_HANDLE(r->in.handle)));
5184                 return WERR_BADFID;
5185         }
5186
5187         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5188                 return WERR_BADFID;
5189
5190         Printer->page_started = false;
5191         print_job_endpage(snum, Printer->jobid);
5192
5193         return WERR_OK;
5194 }
5195
5196 /****************************************************************
5197  _spoolss_StartDocPrinter
5198 ****************************************************************/
5199
5200 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5201                                 struct spoolss_StartDocPrinter *r)
5202 {
5203         struct spoolss_DocumentInfo1 *info_1;
5204         int snum;
5205         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5206
5207         if (!Printer) {
5208                 DEBUG(2,("_spoolss_StartDocPrinter: "
5209                         "Invalid handle (%s:%u:%u)\n",
5210                         OUR_HANDLE(r->in.handle)));
5211                 return WERR_BADFID;
5212         }
5213
5214         if (r->in.level != 1) {
5215                 return WERR_UNKNOWN_LEVEL;
5216         }
5217
5218         info_1 = r->in.info.info1;
5219
5220         /*
5221          * a nice thing with NT is it doesn't listen to what you tell it.
5222          * when asked to send _only_ RAW datas, it tries to send datas
5223          * in EMF format.
5224          *
5225          * So I add checks like in NT Server ...
5226          */
5227
5228         if (info_1->datatype) {
5229                 if (strcmp(info_1->datatype, "RAW") != 0) {
5230                         *r->out.job_id = 0;
5231                         return WERR_INVALID_DATATYPE;
5232                 }
5233         }
5234
5235         /* get the share number of the printer */
5236         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5237                 return WERR_BADFID;
5238         }
5239
5240         Printer->jobid = print_job_start(p->server_info, snum,
5241                                          info_1->document_name,
5242                                          Printer->nt_devmode);
5243
5244         /* An error occured in print_job_start() so return an appropriate
5245            NT error code. */
5246
5247         if (Printer->jobid == -1) {
5248                 return map_werror_from_unix(errno);
5249         }
5250
5251         Printer->document_started = true;
5252         *r->out.job_id = Printer->jobid;
5253
5254         return WERR_OK;
5255 }
5256
5257 /****************************************************************
5258  _spoolss_EndDocPrinter
5259 ****************************************************************/
5260
5261 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5262                               struct spoolss_EndDocPrinter *r)
5263 {
5264         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5265         int snum;
5266
5267         if (!Printer) {
5268                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5269                         OUR_HANDLE(r->in.handle)));
5270                 return WERR_BADFID;
5271         }
5272
5273         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5274                 return WERR_BADFID;
5275         }
5276
5277         Printer->document_started = false;
5278         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5279         /* error codes unhandled so far ... */
5280
5281         return WERR_OK;
5282 }
5283
5284 /****************************************************************
5285  _spoolss_WritePrinter
5286 ****************************************************************/
5287
5288 WERROR _spoolss_WritePrinter(pipes_struct *p,
5289                              struct spoolss_WritePrinter *r)
5290 {
5291         ssize_t buffer_written;
5292         int snum;
5293         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5294
5295         if (!Printer) {
5296                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5297                         OUR_HANDLE(r->in.handle)));
5298                 *r->out.num_written = r->in._data_size;
5299                 return WERR_BADFID;
5300         }
5301
5302         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5303                 return WERR_BADFID;
5304
5305         buffer_written = print_job_write(snum, Printer->jobid,
5306                                                    (const char *)r->in.data.data,
5307                                                    (SMB_OFF_T)-1,
5308                                                    (size_t)r->in._data_size);
5309         if (buffer_written == (ssize_t)-1) {
5310                 *r->out.num_written = 0;
5311                 if (errno == ENOSPC)
5312                         return WERR_NO_SPOOL_SPACE;
5313                 else
5314                         return WERR_ACCESS_DENIED;
5315         }
5316
5317         *r->out.num_written = r->in._data_size;
5318
5319         return WERR_OK;
5320 }
5321
5322 /********************************************************************
5323  * api_spoolss_getprinter
5324  * called from the spoolss dispatcher
5325  *
5326  ********************************************************************/
5327
5328 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5329                               pipes_struct *p)
5330 {
5331         int snum;
5332         WERROR errcode = WERR_BADFUNC;
5333         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5334
5335         if (!Printer) {
5336                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5337                         OUR_HANDLE(handle)));
5338                 return WERR_BADFID;
5339         }
5340
5341         if (!get_printer_snum(p, handle, &snum, NULL))
5342                 return WERR_BADFID;
5343
5344         switch (command) {
5345         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5346                 errcode = print_queue_pause(p->server_info, snum);
5347                 break;
5348         case SPOOLSS_PRINTER_CONTROL_RESUME:
5349         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5350                 errcode = print_queue_resume(p->server_info, snum);
5351                 break;
5352         case SPOOLSS_PRINTER_CONTROL_PURGE:
5353                 errcode = print_queue_purge(p->server_info, snum);
5354                 break;
5355         default:
5356                 return WERR_UNKNOWN_LEVEL;
5357         }
5358
5359         return errcode;
5360 }
5361
5362
5363 /****************************************************************
5364  _spoolss_AbortPrinter
5365  * From MSDN: "Deletes printer's spool file if printer is configured
5366  * for spooling"
5367 ****************************************************************/
5368
5369 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5370                              struct spoolss_AbortPrinter *r)
5371 {
5372         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5373         int             snum;
5374         WERROR          errcode = WERR_OK;
5375
5376         if (!Printer) {
5377                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5378                         OUR_HANDLE(r->in.handle)));
5379                 return WERR_BADFID;
5380         }
5381
5382         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5383                 return WERR_BADFID;
5384
5385         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5386
5387         return errcode;
5388 }
5389
5390 /********************************************************************
5391  * called by spoolss_api_setprinter
5392  * when updating a printer description
5393  ********************************************************************/
5394
5395 static WERROR update_printer_sec(struct policy_handle *handle,
5396                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5397 {
5398         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5399         WERROR result;
5400         int snum;
5401
5402         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5403
5404         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5405                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5406                          OUR_HANDLE(handle)));
5407
5408                 result = WERR_BADFID;
5409                 goto done;
5410         }
5411
5412         if (!secdesc_ctr) {
5413                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5414                 result = WERR_INVALID_PARAM;
5415                 goto done;
5416         }
5417
5418         /* Check the user has permissions to change the security
5419            descriptor.  By experimentation with two NT machines, the user
5420            requires Full Access to the printer to change security
5421            information. */
5422
5423         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5424                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5425                 result = WERR_ACCESS_DENIED;
5426                 goto done;
5427         }
5428
5429         /* NT seems to like setting the security descriptor even though
5430            nothing may have actually changed. */
5431
5432         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5433                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5434                 result = WERR_BADFID;
5435                 goto done;
5436         }
5437
5438         if (DEBUGLEVEL >= 10) {
5439                 SEC_ACL *the_acl;
5440                 int i;
5441
5442                 the_acl = old_secdesc_ctr->sd->dacl;
5443                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5444                            PRINTERNAME(snum), the_acl->num_aces));
5445
5446                 for (i = 0; i < the_acl->num_aces; i++) {
5447                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5448                                            &the_acl->aces[i].trustee),
5449                                   the_acl->aces[i].access_mask));
5450                 }
5451
5452                 the_acl = secdesc_ctr->sd->dacl;
5453
5454                 if (the_acl) {
5455                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5456                                    PRINTERNAME(snum), the_acl->num_aces));
5457
5458                         for (i = 0; i < the_acl->num_aces; i++) {
5459                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5460                                                    &the_acl->aces[i].trustee),
5461                                            the_acl->aces[i].access_mask));
5462                         }
5463                 } else {
5464                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5465                 }
5466         }
5467
5468         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5469         if (!new_secdesc_ctr) {
5470                 result = WERR_NOMEM;
5471                 goto done;
5472         }
5473
5474         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5475                 result = WERR_OK;
5476                 goto done;
5477         }
5478
5479         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5480
5481  done:
5482
5483         return result;
5484 }
5485
5486 /********************************************************************
5487  Canonicalize printer info from a client
5488
5489  ATTN: It does not matter what we set the servername to hear
5490  since we do the necessary work in get_a_printer() to set it to
5491  the correct value based on what the client sent in the
5492  _spoolss_open_printer_ex().
5493  ********************************************************************/
5494
5495 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5496 {
5497         fstring printername;
5498         const char *p;
5499
5500         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5501                 "portname=%s drivername=%s comment=%s location=%s\n",
5502                 info->servername, info->printername, info->sharename,
5503                 info->portname, info->drivername, info->comment, info->location));
5504
5505         /* we force some elements to "correct" values */
5506         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5507         fstrcpy(info->sharename, lp_servicename(snum));
5508
5509         /* check to see if we allow printername != sharename */
5510
5511         if ( lp_force_printername(snum) ) {
5512                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5513                         global_myname(), info->sharename );
5514         } else {
5515
5516                 /* make sure printername is in \\server\printername format */
5517
5518                 fstrcpy( printername, info->printername );
5519                 p = printername;
5520                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5521                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5522                                 p++;
5523                 }
5524
5525                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5526                          global_myname(), p );
5527         }
5528
5529         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5530         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5531
5532
5533
5534         return true;
5535 }
5536
5537 /****************************************************************************
5538 ****************************************************************************/
5539
5540 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5541 {
5542         char *cmd = lp_addport_cmd();
5543         char *command = NULL;
5544         int ret;
5545         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5546         bool is_print_op = false;
5547
5548         if ( !*cmd ) {
5549                 return WERR_ACCESS_DENIED;
5550         }
5551
5552         command = talloc_asprintf(ctx,
5553                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5554         if (!command) {
5555                 return WERR_NOMEM;
5556         }
5557
5558         if ( token )
5559                 is_print_op = user_has_privileges( token, &se_printop );
5560
5561         DEBUG(10,("Running [%s]\n", command));
5562
5563         /********* BEGIN SePrintOperatorPrivilege **********/
5564
5565         if ( is_print_op )
5566                 become_root();
5567
5568         ret = smbrun(command, NULL);
5569
5570         if ( is_print_op )
5571                 unbecome_root();
5572
5573         /********* END SePrintOperatorPrivilege **********/
5574
5575         DEBUGADD(10,("returned [%d]\n", ret));
5576
5577         TALLOC_FREE(command);
5578
5579         if ( ret != 0 ) {
5580                 return WERR_ACCESS_DENIED;
5581         }
5582
5583         return WERR_OK;
5584 }
5585
5586 /****************************************************************************
5587 ****************************************************************************/
5588
5589 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5590 {
5591         char *cmd = lp_addprinter_cmd();
5592         char **qlines;
5593         char *command = NULL;
5594         int numlines;
5595         int ret;
5596         int fd;
5597         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5598         bool is_print_op = false;
5599         char *remote_machine = talloc_strdup(ctx, "%m");
5600
5601         if (!remote_machine) {
5602                 return false;
5603         }
5604         remote_machine = talloc_sub_basic(ctx,
5605                                 current_user_info.smb_name,
5606                                 current_user_info.domain,
5607                                 remote_machine);
5608         if (!remote_machine) {
5609                 return false;
5610         }
5611
5612         command = talloc_asprintf(ctx,
5613                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5614                         cmd, printer->info_2->printername, printer->info_2->sharename,
5615                         printer->info_2->portname, printer->info_2->drivername,
5616                         printer->info_2->location, printer->info_2->comment, remote_machine);
5617         if (!command) {
5618                 return false;
5619         }
5620
5621         if ( token )
5622                 is_print_op = user_has_privileges( token, &se_printop );
5623
5624         DEBUG(10,("Running [%s]\n", command));
5625
5626         /********* BEGIN SePrintOperatorPrivilege **********/
5627
5628         if ( is_print_op )
5629                 become_root();
5630
5631         if ( (ret = smbrun(command, &fd)) == 0 ) {
5632                 /* Tell everyone we updated smb.conf. */
5633                 message_send_all(smbd_messaging_context(),
5634                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5635         }
5636
5637         if ( is_print_op )
5638                 unbecome_root();
5639
5640         /********* END SePrintOperatorPrivilege **********/
5641
5642         DEBUGADD(10,("returned [%d]\n", ret));
5643
5644         TALLOC_FREE(command);
5645         TALLOC_FREE(remote_machine);
5646
5647         if ( ret != 0 ) {
5648                 if (fd != -1)
5649                         close(fd);
5650                 return false;
5651         }
5652
5653         /* reload our services immediately */
5654         become_root();
5655         reload_services(false);
5656         unbecome_root();
5657
5658         numlines = 0;
5659         /* Get lines and convert them back to dos-codepage */
5660         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5661         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5662         close(fd);
5663
5664         /* Set the portname to what the script says the portname should be. */
5665         /* but don't require anything to be return from the script exit a good error code */
5666
5667         if (numlines) {
5668                 /* Set the portname to what the script says the portname should be. */
5669                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5670                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5671         }
5672
5673         TALLOC_FREE(qlines);
5674         return true;
5675 }
5676
5677
5678 /********************************************************************
5679  * Called by spoolss_api_setprinter
5680  * when updating a printer description.
5681  ********************************************************************/
5682
5683 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5684                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5685                              struct spoolss_DeviceMode *devmode)
5686 {
5687         int snum;
5688         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5689         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5690         WERROR result;
5691         DATA_BLOB buffer;
5692         fstring asc_buffer;
5693
5694         DEBUG(8,("update_printer\n"));
5695
5696         result = WERR_OK;
5697
5698         if (!Printer) {
5699                 result = WERR_BADFID;
5700                 goto done;
5701         }
5702
5703         if (!get_printer_snum(p, handle, &snum, NULL)) {
5704                 result = WERR_BADFID;
5705                 goto done;
5706         }
5707
5708         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5709             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5710                 result = WERR_BADFID;
5711                 goto done;
5712         }
5713
5714         DEBUGADD(8,("Converting info_2 struct\n"));
5715
5716         /*
5717          * convert_printer_info converts the incoming
5718          * info from the client and overwrites the info
5719          * just read from the tdb in the pointer 'printer'.
5720          */
5721
5722         if (!convert_printer_info(info_ctr, printer)) {
5723                 result =  WERR_NOMEM;
5724                 goto done;
5725         }
5726
5727         if (devmode) {
5728                 /* we have a valid devmode
5729                    convert it and link it*/
5730
5731                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5732                 if (!convert_devicemode(printer->info_2->printername, devmode,
5733                                         &printer->info_2->devmode)) {
5734                         result =  WERR_NOMEM;
5735                         goto done;
5736                 }
5737         }
5738
5739         /* Do sanity check on the requested changes for Samba */
5740
5741         if (!check_printer_ok(printer->info_2, snum)) {
5742                 result = WERR_INVALID_PARAM;
5743                 goto done;
5744         }
5745
5746         /* FIXME!!! If the driver has changed we really should verify that
5747            it is installed before doing much else   --jerry */
5748
5749         /* Check calling user has permission to update printer description */
5750
5751         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5752                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5753                 result = WERR_ACCESS_DENIED;
5754                 goto done;
5755         }
5756
5757         /* Call addprinter hook */
5758         /* Check changes to see if this is really needed */
5759
5760         if ( *lp_addprinter_cmd()
5761                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5762                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5763                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5764                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5765         {
5766                 /* add_printer_hook() will call reload_services() */
5767
5768                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5769                                        printer) ) {
5770                         result = WERR_ACCESS_DENIED;
5771                         goto done;
5772                 }
5773         }
5774
5775         /*
5776          * When a *new* driver is bound to a printer, the drivername is used to
5777          * lookup previously saved driver initialization info, which is then
5778          * bound to the printer, simulating what happens in the Windows arch.
5779          */
5780         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5781         {
5782                 if (!set_driver_init(printer, 2))
5783                 {
5784                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5785                                 printer->info_2->drivername));
5786                 }
5787
5788                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5789                         printer->info_2->drivername));
5790
5791                 notify_printer_driver(snum, printer->info_2->drivername);
5792         }
5793
5794         /*
5795          * flag which changes actually occured.  This is a small subset of
5796          * all the possible changes.  We also have to update things in the
5797          * DsSpooler key.
5798          */
5799
5800         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5801                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->comment);
5802                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5803                         REG_SZ, buffer.data, buffer.length);
5804
5805                 notify_printer_comment(snum, printer->info_2->comment);
5806         }
5807
5808         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5809                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->sharename);
5810                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5811                         REG_SZ, buffer.data, buffer.length);
5812
5813                 notify_printer_sharename(snum, printer->info_2->sharename);
5814         }
5815
5816         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5817                 char *pname;
5818
5819                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5820                         pname++;
5821                 else
5822                         pname = printer->info_2->printername;
5823
5824
5825                 push_reg_sz(talloc_tos(), NULL, &buffer, pname);
5826                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5827                         REG_SZ, buffer.data, buffer.length);
5828
5829                 notify_printer_printername( snum, pname );
5830         }
5831
5832         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5833                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->portname);
5834                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5835                         REG_SZ, buffer.data, buffer.length);
5836
5837                 notify_printer_port(snum, printer->info_2->portname);
5838         }
5839
5840         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5841                 push_reg_sz(talloc_tos(), NULL, &buffer, printer->info_2->location);
5842                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5843                         REG_SZ, buffer.data, buffer.length);
5844
5845                 notify_printer_location(snum, printer->info_2->location);
5846         }
5847
5848         /* here we need to update some more DsSpooler keys */
5849         /* uNCName, serverName, shortServerName */
5850
5851         push_reg_sz(talloc_tos(), NULL, &buffer, global_myname());
5852         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5853                 REG_SZ, buffer.data, buffer.length);
5854         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5855                 REG_SZ, buffer.data, buffer.length);
5856
5857         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5858                  global_myname(), printer->info_2->sharename );
5859         push_reg_sz(talloc_tos(), NULL, &buffer, asc_buffer);
5860         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5861                 REG_SZ, buffer.data, buffer.length);
5862
5863         /* Update printer info */
5864         result = mod_a_printer(printer, 2);
5865
5866 done:
5867         free_a_printer(&printer, 2);
5868         free_a_printer(&old_printer, 2);
5869
5870
5871         return result;
5872 }
5873
5874 /****************************************************************************
5875 ****************************************************************************/
5876 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5877                                            struct policy_handle *handle,
5878                                            struct spoolss_SetPrinterInfo7 *info7)
5879 {
5880 #ifdef HAVE_ADS
5881         int snum;
5882         Printer_entry *Printer;
5883
5884         if ( lp_security() != SEC_ADS ) {
5885                 return WERR_UNKNOWN_LEVEL;
5886         }
5887
5888         Printer = find_printer_index_by_hnd(p, handle);
5889
5890         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5891
5892         if (!Printer)
5893                 return WERR_BADFID;
5894
5895         if (!get_printer_snum(p, handle, &snum, NULL))
5896                 return WERR_BADFID;
5897
5898         nt_printer_publish(Printer, snum, info7->action);
5899
5900         return WERR_OK;
5901 #else
5902         return WERR_UNKNOWN_LEVEL;
5903 #endif
5904 }
5905
5906 /********************************************************************
5907  ********************************************************************/
5908
5909 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5910                                      struct spoolss_DeviceMode *devmode)
5911 {
5912         int snum;
5913         NT_PRINTER_INFO_LEVEL *printer = NULL;
5914         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5915         WERROR result;
5916
5917         DEBUG(8,("update_printer_devmode\n"));
5918
5919         result = WERR_OK;
5920
5921         if (!Printer) {
5922                 result = WERR_BADFID;
5923                 goto done;
5924         }
5925
5926         if (!get_printer_snum(p, handle, &snum, NULL)) {
5927                 result = WERR_BADFID;
5928                 goto done;
5929         }
5930
5931         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5932                 result = WERR_BADFID;
5933                 goto done;
5934         }
5935
5936         if (devmode) {
5937                 /* we have a valid devmode
5938                    convert it and link it*/
5939
5940                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5941                 if (!convert_devicemode(printer->info_2->printername, devmode,
5942                                         &printer->info_2->devmode)) {
5943                         result =  WERR_NOMEM;
5944                         goto done;
5945                 }
5946         }
5947
5948         /* Check calling user has permission to update printer description */
5949
5950         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5951                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5952                 result = WERR_ACCESS_DENIED;
5953                 goto done;
5954         }
5955
5956
5957         /* Update printer info */
5958         result = mod_a_printer(printer, 2);
5959
5960 done:
5961         free_a_printer(&printer, 2);
5962
5963         return result;
5964 }
5965
5966
5967 /****************************************************************
5968  _spoolss_SetPrinter
5969 ****************************************************************/
5970
5971 WERROR _spoolss_SetPrinter(pipes_struct *p,
5972                            struct spoolss_SetPrinter *r)
5973 {
5974         WERROR result;
5975
5976         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5977
5978         if (!Printer) {
5979                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5980                         OUR_HANDLE(r->in.handle)));
5981                 return WERR_BADFID;
5982         }
5983
5984         /* check the level */
5985         switch (r->in.info_ctr->level) {
5986                 case 0:
5987                         return control_printer(r->in.handle, r->in.command, p);
5988                 case 2:
5989                         result = update_printer(p, r->in.handle,
5990                                                 r->in.info_ctr,
5991                                                 r->in.devmode_ctr->devmode);
5992                         if (!W_ERROR_IS_OK(result))
5993                                 return result;
5994                         if (r->in.secdesc_ctr->sd)
5995                                 result = update_printer_sec(r->in.handle, p,
5996                                                             r->in.secdesc_ctr);
5997                         return result;
5998                 case 3:
5999                         return update_printer_sec(r->in.handle, p,
6000                                                   r->in.secdesc_ctr);
6001                 case 7:
6002                         return publish_or_unpublish_printer(p, r->in.handle,
6003                                                             r->in.info_ctr->info.info7);
6004                 case 8:
6005                         return update_printer_devmode(p, r->in.handle,
6006                                                       r->in.devmode_ctr->devmode);
6007                 default:
6008                         return WERR_UNKNOWN_LEVEL;
6009         }
6010 }
6011
6012 /****************************************************************
6013  _spoolss_FindClosePrinterNotify
6014 ****************************************************************/
6015
6016 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6017                                        struct spoolss_FindClosePrinterNotify *r)
6018 {
6019         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6020
6021         if (!Printer) {
6022                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6023                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6024                 return WERR_BADFID;
6025         }
6026
6027         if (Printer->notify.client_connected == true) {
6028                 int snum = -1;
6029
6030                 if ( Printer->printer_type == SPLHND_SERVER)
6031                         snum = -1;
6032                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6033                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6034                         return WERR_BADFID;
6035
6036                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6037         }
6038
6039         Printer->notify.flags=0;
6040         Printer->notify.options=0;
6041         Printer->notify.localmachine[0]='\0';
6042         Printer->notify.printerlocal=0;
6043         TALLOC_FREE(Printer->notify.option);
6044         Printer->notify.client_connected = false;
6045
6046         return WERR_OK;
6047 }
6048
6049 /****************************************************************
6050  _spoolss_AddJob
6051 ****************************************************************/
6052
6053 WERROR _spoolss_AddJob(pipes_struct *p,
6054                        struct spoolss_AddJob *r)
6055 {
6056         if (!r->in.buffer && (r->in.offered != 0)) {
6057                 return WERR_INVALID_PARAM;
6058         }
6059
6060         /* this is what a NT server returns for AddJob. AddJob must fail on
6061          * non-local printers */
6062
6063         if (r->in.level != 1) {
6064                 return WERR_UNKNOWN_LEVEL;
6065         }
6066
6067         return WERR_INVALID_PARAM;
6068 }
6069
6070 /****************************************************************************
6071 fill_job_info1
6072 ****************************************************************************/
6073
6074 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6075                              struct spoolss_JobInfo1 *r,
6076                              const print_queue_struct *queue,
6077                              int position, int snum,
6078                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6079 {
6080         struct tm *t;
6081
6082         t = gmtime(&queue->time);
6083
6084         r->job_id               = queue->job;
6085
6086         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6087         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6088         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6089         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6090         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6091         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6092         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6093         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6094         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6095         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6096         r->text_status          = talloc_strdup(mem_ctx, "");
6097         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6098
6099         r->status               = nt_printj_status(queue->status);
6100         r->priority             = queue->priority;
6101         r->position             = position;
6102         r->total_pages          = queue->page_count;
6103         r->pages_printed        = 0; /* ??? */
6104
6105         init_systemtime(&r->submitted, t);
6106
6107         return WERR_OK;
6108 }
6109
6110 /****************************************************************************
6111 fill_job_info2
6112 ****************************************************************************/
6113
6114 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6115                              struct spoolss_JobInfo2 *r,
6116                              const print_queue_struct *queue,
6117                              int position, int snum,
6118                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6119                              struct spoolss_DeviceMode *devmode)
6120 {
6121         struct tm *t;
6122
6123         t = gmtime(&queue->time);
6124
6125         r->job_id               = queue->job;
6126
6127         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6128         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6129         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6130         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6131         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6132         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6133         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6134         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6135         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6136         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6137         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6138         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6139         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6140         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6141         r->parameters           = talloc_strdup(mem_ctx, "");
6142         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6143         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6144         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6145
6146         r->devmode              = devmode;
6147
6148         r->text_status          = talloc_strdup(mem_ctx, "");
6149         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6150
6151         r->secdesc              = NULL;
6152
6153         r->status               = nt_printj_status(queue->status);
6154         r->priority             = queue->priority;
6155         r->position             = position;
6156         r->start_time           = 0;
6157         r->until_time           = 0;
6158         r->total_pages          = queue->page_count;
6159         r->size                 = queue->size;
6160         init_systemtime(&r->submitted, t);
6161         r->time                 = 0;
6162         r->pages_printed        = 0; /* ??? */
6163
6164         return WERR_OK;
6165 }
6166
6167 /****************************************************************************
6168 fill_job_info3
6169 ****************************************************************************/
6170
6171 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6172                              struct spoolss_JobInfo3 *r,
6173                              const print_queue_struct *queue,
6174                              const print_queue_struct *next_queue,
6175                              int position, int snum,
6176                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6177 {
6178         r->job_id               = queue->job;
6179         r->next_job_id          = 0;
6180         if (next_queue) {
6181                 r->next_job_id  = next_queue->job;
6182         }
6183         r->reserved             = 0;
6184
6185         return WERR_OK;
6186 }
6187
6188 /****************************************************************************
6189  Enumjobs at level 1.
6190 ****************************************************************************/
6191
6192 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6193                               const print_queue_struct *queue,
6194                               uint32_t num_queues, int snum,
6195                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6196                               union spoolss_JobInfo **info_p,
6197                               uint32_t *count)
6198 {
6199         union spoolss_JobInfo *info;
6200         int i;
6201         WERROR result = WERR_OK;
6202
6203         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6204         W_ERROR_HAVE_NO_MEMORY(info);
6205
6206         *count = num_queues;
6207
6208         for (i=0; i<*count; i++) {
6209                 result = fill_job_info1(info,
6210                                         &info[i].info1,
6211                                         &queue[i],
6212                                         i,
6213                                         snum,
6214                                         ntprinter);
6215                 if (!W_ERROR_IS_OK(result)) {
6216                         goto out;
6217                 }
6218         }
6219
6220  out:
6221         if (!W_ERROR_IS_OK(result)) {
6222                 TALLOC_FREE(info);
6223                 *count = 0;
6224                 return result;
6225         }
6226
6227         *info_p = info;
6228
6229         return WERR_OK;
6230 }
6231
6232 /****************************************************************************
6233  Enumjobs at level 2.
6234 ****************************************************************************/
6235
6236 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6237                               const print_queue_struct *queue,
6238                               uint32_t num_queues, int snum,
6239                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6240                               union spoolss_JobInfo **info_p,
6241                               uint32_t *count)
6242 {
6243         union spoolss_JobInfo *info;
6244         int i;
6245         WERROR result = WERR_OK;
6246
6247         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6248         W_ERROR_HAVE_NO_MEMORY(info);
6249
6250         *count = num_queues;
6251
6252         for (i=0; i<*count; i++) {
6253
6254                 struct spoolss_DeviceMode *devmode;
6255
6256                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6257                 if (!devmode) {
6258                         result = WERR_NOMEM;
6259                         goto out;
6260                 }
6261
6262                 result = fill_job_info2(info,
6263                                         &info[i].info2,
6264                                         &queue[i],
6265                                         i,
6266                                         snum,
6267                                         ntprinter,
6268                                         devmode);
6269                 if (!W_ERROR_IS_OK(result)) {
6270                         goto out;
6271                 }
6272         }
6273
6274  out:
6275         if (!W_ERROR_IS_OK(result)) {
6276                 TALLOC_FREE(info);
6277                 *count = 0;
6278                 return result;
6279         }
6280
6281         *info_p = info;
6282
6283         return WERR_OK;
6284 }
6285
6286 /****************************************************************************
6287  Enumjobs at level 3.
6288 ****************************************************************************/
6289
6290 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6291                               const print_queue_struct *queue,
6292                               uint32_t num_queues, int snum,
6293                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6294                               union spoolss_JobInfo **info_p,
6295                               uint32_t *count)
6296 {
6297         union spoolss_JobInfo *info;
6298         int i;
6299         WERROR result = WERR_OK;
6300
6301         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6302         W_ERROR_HAVE_NO_MEMORY(info);
6303
6304         *count = num_queues;
6305
6306         for (i=0; i<*count; i++) {
6307                 const print_queue_struct *next_queue = NULL;
6308
6309                 if (i+1 < *count) {
6310                         next_queue = &queue[i+1];
6311                 }
6312
6313                 result = fill_job_info3(info,
6314                                         &info[i].info3,
6315                                         &queue[i],
6316                                         next_queue,
6317                                         i,
6318                                         snum,
6319                                         ntprinter);
6320                 if (!W_ERROR_IS_OK(result)) {
6321                         goto out;
6322                 }
6323         }
6324
6325  out:
6326         if (!W_ERROR_IS_OK(result)) {
6327                 TALLOC_FREE(info);
6328                 *count = 0;
6329                 return result;
6330         }
6331
6332         *info_p = info;
6333
6334         return WERR_OK;
6335 }
6336
6337 /****************************************************************
6338  _spoolss_EnumJobs
6339 ****************************************************************/
6340
6341 WERROR _spoolss_EnumJobs(pipes_struct *p,
6342                          struct spoolss_EnumJobs *r)
6343 {
6344         WERROR result;
6345         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6346         int snum;
6347         print_status_struct prt_status;
6348         print_queue_struct *queue = NULL;
6349         uint32_t count;
6350
6351         /* that's an [in out] buffer */
6352
6353         if (!r->in.buffer && (r->in.offered != 0)) {
6354                 return WERR_INVALID_PARAM;
6355         }
6356
6357         DEBUG(4,("_spoolss_EnumJobs\n"));
6358
6359         *r->out.needed = 0;
6360         *r->out.count = 0;
6361         *r->out.info = NULL;
6362
6363         /* lookup the printer snum and tdb entry */
6364
6365         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6366                 return WERR_BADFID;
6367         }
6368
6369         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6370         if (!W_ERROR_IS_OK(result)) {
6371                 return result;
6372         }
6373
6374         count = print_queue_status(snum, &queue, &prt_status);
6375         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6376                 count, prt_status.status, prt_status.message));
6377
6378         if (count == 0) {
6379                 SAFE_FREE(queue);
6380                 free_a_printer(&ntprinter, 2);
6381                 return WERR_OK;
6382         }
6383
6384         switch (r->in.level) {
6385         case 1:
6386                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6387                                          ntprinter, r->out.info, r->out.count);
6388                 break;
6389         case 2:
6390                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6391                                          ntprinter, r->out.info, r->out.count);
6392                 break;
6393         case 3:
6394                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6395                                          ntprinter, r->out.info, r->out.count);
6396                 break;
6397         default:
6398                 result = WERR_UNKNOWN_LEVEL;
6399                 break;
6400         }
6401
6402         SAFE_FREE(queue);
6403         free_a_printer(&ntprinter, 2);
6404
6405         if (!W_ERROR_IS_OK(result)) {
6406                 return result;
6407         }
6408
6409         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6410                                                      spoolss_EnumJobs, NULL,
6411                                                      *r->out.info, r->in.level,
6412                                                      *r->out.count);
6413         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6414         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6415
6416         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6417 }
6418
6419 /****************************************************************
6420  _spoolss_ScheduleJob
6421 ****************************************************************/
6422
6423 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6424                             struct spoolss_ScheduleJob *r)
6425 {
6426         return WERR_OK;
6427 }
6428
6429 /****************************************************************
6430 ****************************************************************/
6431
6432 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6433                                const char *printer_name,
6434                                uint32_t job_id,
6435                                struct spoolss_SetJobInfo1 *r)
6436 {
6437         char *old_doc_name;
6438
6439         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6440                 return WERR_BADFID;
6441         }
6442
6443         if (strequal(old_doc_name, r->document_name)) {
6444                 return WERR_OK;
6445         }
6446
6447         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6448                 return WERR_BADFID;
6449         }
6450
6451         return WERR_OK;
6452 }
6453
6454 /****************************************************************
6455  _spoolss_SetJob
6456 ****************************************************************/
6457
6458 WERROR _spoolss_SetJob(pipes_struct *p,
6459                        struct spoolss_SetJob *r)
6460 {
6461         int snum;
6462         WERROR errcode = WERR_BADFUNC;
6463
6464         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6465                 return WERR_BADFID;
6466         }
6467
6468         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6469                 return WERR_INVALID_PRINTER_NAME;
6470         }
6471
6472         switch (r->in.command) {
6473         case SPOOLSS_JOB_CONTROL_CANCEL:
6474         case SPOOLSS_JOB_CONTROL_DELETE:
6475                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6476                         errcode = WERR_OK;
6477                 }
6478                 break;
6479         case SPOOLSS_JOB_CONTROL_PAUSE:
6480                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6481                         errcode = WERR_OK;
6482                 }
6483                 break;
6484         case SPOOLSS_JOB_CONTROL_RESTART:
6485         case SPOOLSS_JOB_CONTROL_RESUME:
6486                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6487                         errcode = WERR_OK;
6488                 }
6489                 break;
6490         case 0:
6491                 errcode = WERR_OK;
6492                 break;
6493         default:
6494                 return WERR_UNKNOWN_LEVEL;
6495         }
6496
6497         if (!W_ERROR_IS_OK(errcode)) {
6498                 return errcode;
6499         }
6500
6501         if (r->in.ctr == NULL) {
6502                 return errcode;
6503         }
6504
6505         switch (r->in.ctr->level) {
6506         case 1:
6507                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6508                                            r->in.job_id,
6509                                            r->in.ctr->info.info1);
6510                 break;
6511         case 2:
6512         case 3:
6513         case 4:
6514         default:
6515                 return WERR_UNKNOWN_LEVEL;
6516         }
6517
6518         return errcode;
6519 }
6520
6521 /****************************************************************************
6522  Enumerates all printer drivers by level and architecture.
6523 ****************************************************************************/
6524
6525 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6526                                                        const char *servername,
6527                                                        const char *architecture,
6528                                                        uint32_t level,
6529                                                        union spoolss_DriverInfo **info_p,
6530                                                        uint32_t *count_p)
6531 {
6532         int i;
6533         int ndrivers;
6534         uint32_t version;
6535         fstring *list = NULL;
6536         struct spoolss_DriverInfo8 *driver;
6537         union spoolss_DriverInfo *info = NULL;
6538         uint32_t count = 0;
6539         WERROR result = WERR_OK;
6540
6541         *count_p = 0;
6542         *info_p = NULL;
6543
6544         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6545                 list = NULL;
6546                 ndrivers = get_ntdrivers(&list, architecture, version);
6547                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6548                         ndrivers, architecture, version));
6549
6550                 if (ndrivers == -1) {
6551                         result = WERR_NOMEM;
6552                         goto out;
6553                 }
6554
6555                 if (ndrivers != 0) {
6556                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6557                                                     union spoolss_DriverInfo,
6558                                                     count + ndrivers);
6559                         if (!info) {
6560                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6561                                         "failed to enlarge driver info buffer!\n"));
6562                                 result = WERR_NOMEM;
6563                                 goto out;
6564                         }
6565                 }
6566
6567                 for (i=0; i<ndrivers; i++) {
6568                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6569                         ZERO_STRUCT(driver);
6570                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6571                                                       architecture, version);
6572                         if (!W_ERROR_IS_OK(result)) {
6573                                 goto out;
6574                         }
6575
6576                         switch (level) {
6577                         case 1:
6578                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6579                                                                    driver, servername);
6580                                 break;
6581                         case 2:
6582                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6583                                                                    driver, servername);
6584                                 break;
6585                         case 3:
6586                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6587                                                                    driver, servername);
6588                                 break;
6589                         case 4:
6590                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6591                                                                    driver, servername);
6592                                 break;
6593                         case 5:
6594                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6595                                                                    driver, servername);
6596                                 break;
6597                         case 6:
6598                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6599                                                                    driver, servername);
6600                                 break;
6601                         case 8:
6602                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6603                                                                    driver, servername);
6604                                 break;
6605                         default:
6606                                 result = WERR_UNKNOWN_LEVEL;
6607                                 break;
6608                         }
6609
6610                         free_a_printer_driver(driver);
6611
6612                         if (!W_ERROR_IS_OK(result)) {
6613                                 goto out;
6614                         }
6615                 }
6616
6617                 count += ndrivers;
6618                 SAFE_FREE(list);
6619         }
6620
6621  out:
6622         SAFE_FREE(list);
6623
6624         if (!W_ERROR_IS_OK(result)) {
6625                 TALLOC_FREE(info);
6626                 return result;
6627         }
6628
6629         *info_p = info;
6630         *count_p = count;
6631
6632         return WERR_OK;
6633 }
6634
6635 /****************************************************************************
6636  Enumerates all printer drivers by level.
6637 ****************************************************************************/
6638
6639 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6640                                        const char *servername,
6641                                        const char *architecture,
6642                                        uint32_t level,
6643                                        union spoolss_DriverInfo **info_p,
6644                                        uint32_t *count_p)
6645 {
6646         uint32_t a,i;
6647         WERROR result = WERR_OK;
6648
6649         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6650
6651                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6652
6653                         union spoolss_DriverInfo *info = NULL;
6654                         uint32_t count = 0;
6655
6656                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6657                                                                           servername,
6658                                                                           archi_table[a].long_archi,
6659                                                                           level,
6660                                                                           &info,
6661                                                                           &count);
6662                         if (!W_ERROR_IS_OK(result)) {
6663                                 continue;
6664                         }
6665
6666                         for (i=0; i < count; i++) {
6667                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6668                                              info[i], info_p, count_p);
6669                         }
6670                 }
6671
6672                 return result;
6673         }
6674
6675         return enumprinterdrivers_level_by_architecture(mem_ctx,
6676                                                         servername,
6677                                                         architecture,
6678                                                         level,
6679                                                         info_p,
6680                                                         count_p);
6681 }
6682
6683 /****************************************************************
6684  _spoolss_EnumPrinterDrivers
6685 ****************************************************************/
6686
6687 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6688                                    struct spoolss_EnumPrinterDrivers *r)
6689 {
6690         const char *cservername;
6691         WERROR result;
6692
6693         /* that's an [in out] buffer */
6694
6695         if (!r->in.buffer && (r->in.offered != 0)) {
6696                 return WERR_INVALID_PARAM;
6697         }
6698
6699         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6700
6701         *r->out.needed = 0;
6702         *r->out.count = 0;
6703         *r->out.info = NULL;
6704
6705         cservername = canon_servername(r->in.server);
6706
6707         if (!is_myname_or_ipaddr(cservername)) {
6708                 return WERR_UNKNOWN_PRINTER_DRIVER;
6709         }
6710
6711         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6712                                           r->in.environment,
6713                                           r->in.level,
6714                                           r->out.info,
6715                                           r->out.count);
6716         if (!W_ERROR_IS_OK(result)) {
6717                 return result;
6718         }
6719
6720         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6721                                                      spoolss_EnumPrinterDrivers, NULL,
6722                                                      *r->out.info, r->in.level,
6723                                                      *r->out.count);
6724         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6725         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6726
6727         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6728 }
6729
6730 /****************************************************************************
6731 ****************************************************************************/
6732
6733 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6734                                struct spoolss_FormInfo1 *r,
6735                                const nt_forms_struct *form)
6736 {
6737         r->form_name    = talloc_strdup(mem_ctx, form->name);
6738         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6739
6740         r->flags        = form->flag;
6741         r->size.width   = form->width;
6742         r->size.height  = form->length;
6743         r->area.left    = form->left;
6744         r->area.top     = form->top;
6745         r->area.right   = form->right;
6746         r->area.bottom  = form->bottom;
6747
6748         return WERR_OK;
6749 }
6750
6751 /****************************************************************
6752  spoolss_enumforms_level1
6753 ****************************************************************/
6754
6755 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6756                                        const nt_forms_struct *builtin_forms,
6757                                        uint32_t num_builtin_forms,
6758                                        const nt_forms_struct *user_forms,
6759                                        uint32_t num_user_forms,
6760                                        union spoolss_FormInfo **info_p,
6761                                        uint32_t *count)
6762 {
6763         union spoolss_FormInfo *info;
6764         WERROR result = WERR_OK;
6765         int i;
6766
6767         *count = num_builtin_forms + num_user_forms;
6768
6769         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6770         W_ERROR_HAVE_NO_MEMORY(info);
6771
6772         /* construct the list of form structures */
6773         for (i=0; i<num_builtin_forms; i++) {
6774                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6775                 result = fill_form_info_1(info, &info[i].info1,
6776                                           &builtin_forms[i]);
6777                 if (!W_ERROR_IS_OK(result)) {
6778                         goto out;
6779                 }
6780         }
6781
6782         for (i=0; i<num_user_forms; i++) {
6783                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6784                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6785                                           &user_forms[i]);
6786                 if (!W_ERROR_IS_OK(result)) {
6787                         goto out;
6788                 }
6789         }
6790
6791  out:
6792         if (!W_ERROR_IS_OK(result)) {
6793                 TALLOC_FREE(info);
6794                 *count = 0;
6795                 return result;
6796         }
6797
6798         *info_p = info;
6799
6800         return WERR_OK;
6801 }
6802
6803 /****************************************************************
6804  _spoolss_EnumForms
6805 ****************************************************************/
6806
6807 WERROR _spoolss_EnumForms(pipes_struct *p,
6808                           struct spoolss_EnumForms *r)
6809 {
6810         WERROR result;
6811         nt_forms_struct *user_forms = NULL;
6812         nt_forms_struct *builtin_forms = NULL;
6813         uint32_t num_user_forms;
6814         uint32_t num_builtin_forms;
6815
6816         *r->out.count = 0;
6817         *r->out.needed = 0;
6818         *r->out.info = NULL;
6819
6820         /* that's an [in out] buffer */
6821
6822         if (!r->in.buffer && (r->in.offered != 0) ) {
6823                 return WERR_INVALID_PARAM;
6824         }
6825
6826         DEBUG(4,("_spoolss_EnumForms\n"));
6827         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6828         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6829
6830         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6831         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6832         num_user_forms = get_ntforms(&user_forms);
6833         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6834
6835         if (num_user_forms + num_builtin_forms == 0) {
6836                 SAFE_FREE(builtin_forms);
6837                 SAFE_FREE(user_forms);
6838                 return WERR_NO_MORE_ITEMS;
6839         }
6840
6841         switch (r->in.level) {
6842         case 1:
6843                 result = spoolss_enumforms_level1(p->mem_ctx,
6844                                                   builtin_forms,
6845                                                   num_builtin_forms,
6846                                                   user_forms,
6847                                                   num_user_forms,
6848                                                   r->out.info,
6849                                                   r->out.count);
6850                 break;
6851         default:
6852                 result = WERR_UNKNOWN_LEVEL;
6853                 break;
6854         }
6855
6856         SAFE_FREE(user_forms);
6857         SAFE_FREE(builtin_forms);
6858
6859         if (!W_ERROR_IS_OK(result)) {
6860                 return result;
6861         }
6862
6863         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6864                                                      spoolss_EnumForms, NULL,
6865                                                      *r->out.info, r->in.level,
6866                                                      *r->out.count);
6867         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6868         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6869
6870         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6871 }
6872
6873 /****************************************************************
6874 ****************************************************************/
6875
6876 static WERROR find_form_byname(const char *name,
6877                                nt_forms_struct *form)
6878 {
6879         nt_forms_struct *list = NULL;
6880         int num_forms = 0, i = 0;
6881
6882         if (get_a_builtin_ntform_by_string(name, form)) {
6883                 return WERR_OK;
6884         }
6885
6886         num_forms = get_ntforms(&list);
6887         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6888
6889         if (num_forms == 0) {
6890                 return WERR_BADFID;
6891         }
6892
6893         /* Check if the requested name is in the list of form structures */
6894         for (i = 0; i < num_forms; i++) {
6895
6896                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6897
6898                 if (strequal(name, list[i].name)) {
6899                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6900                         *form = list[i];
6901                         SAFE_FREE(list);
6902                         return WERR_OK;
6903                 }
6904         }
6905
6906         SAFE_FREE(list);
6907
6908         return WERR_BADFID;
6909 }
6910
6911 /****************************************************************
6912  _spoolss_GetForm
6913 ****************************************************************/
6914
6915 WERROR _spoolss_GetForm(pipes_struct *p,
6916                         struct spoolss_GetForm *r)
6917 {
6918         WERROR result;
6919         nt_forms_struct form;
6920
6921         /* that's an [in out] buffer */
6922
6923         if (!r->in.buffer && (r->in.offered != 0)) {
6924                 return WERR_INVALID_PARAM;
6925         }
6926
6927         DEBUG(4,("_spoolss_GetForm\n"));
6928         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6929         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6930
6931         result = find_form_byname(r->in.form_name, &form);
6932         if (!W_ERROR_IS_OK(result)) {
6933                 TALLOC_FREE(r->out.info);
6934                 return result;
6935         }
6936
6937         switch (r->in.level) {
6938         case 1:
6939                 result = fill_form_info_1(p->mem_ctx,
6940                                           &r->out.info->info1,
6941                                           &form);
6942                 break;
6943
6944         default:
6945                 result = WERR_UNKNOWN_LEVEL;
6946                 break;
6947         }
6948
6949         if (!W_ERROR_IS_OK(result)) {
6950                 TALLOC_FREE(r->out.info);
6951                 return result;
6952         }
6953
6954         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6955                                                r->out.info, r->in.level);
6956         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6957
6958         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6959 }
6960
6961 /****************************************************************************
6962 ****************************************************************************/
6963
6964 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6965                           struct spoolss_PortInfo1 *r,
6966                           const char *name)
6967 {
6968         r->port_name = talloc_strdup(mem_ctx, name);
6969         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6970
6971         return WERR_OK;
6972 }
6973
6974 /****************************************************************************
6975  TODO: This probably needs distinguish between TCP/IP and Local ports
6976  somehow.
6977 ****************************************************************************/
6978
6979 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6980                           struct spoolss_PortInfo2 *r,
6981                           const char *name)
6982 {
6983         r->port_name = talloc_strdup(mem_ctx, name);
6984         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6985
6986         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6987         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6988
6989         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6990         W_ERROR_HAVE_NO_MEMORY(r->description);
6991
6992         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6993         r->reserved = 0;
6994
6995         return WERR_OK;
6996 }
6997
6998
6999 /****************************************************************************
7000  wrapper around the enumer ports command
7001 ****************************************************************************/
7002
7003 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7004 {
7005         char *cmd = lp_enumports_cmd();
7006         char **qlines = NULL;
7007         char *command = NULL;
7008         int numlines;
7009         int ret;
7010         int fd;
7011
7012         *count = 0;
7013         *lines = NULL;
7014
7015         /* if no hook then just fill in the default port */
7016
7017         if ( !*cmd ) {
7018                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7019                         return WERR_NOMEM;
7020                 }
7021                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7022                         TALLOC_FREE(qlines);
7023                         return WERR_NOMEM;
7024                 }
7025                 qlines[1] = NULL;
7026                 numlines = 1;
7027         }
7028         else {
7029                 /* we have a valid enumport command */
7030
7031                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7032                 if (!command) {
7033                         return WERR_NOMEM;
7034                 }
7035
7036                 DEBUG(10,("Running [%s]\n", command));
7037                 ret = smbrun(command, &fd);
7038                 DEBUG(10,("Returned [%d]\n", ret));
7039                 TALLOC_FREE(command);
7040                 if (ret != 0) {
7041                         if (fd != -1) {
7042                                 close(fd);
7043                         }
7044                         return WERR_ACCESS_DENIED;
7045                 }
7046
7047                 numlines = 0;
7048                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7049                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7050                 close(fd);
7051         }
7052
7053         *count = numlines;
7054         *lines = qlines;
7055
7056         return WERR_OK;
7057 }
7058
7059 /****************************************************************************
7060  enumports level 1.
7061 ****************************************************************************/
7062
7063 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7064                                 union spoolss_PortInfo **info_p,
7065                                 uint32_t *count)
7066 {
7067         union spoolss_PortInfo *info = NULL;
7068         int i=0;
7069         WERROR result = WERR_OK;
7070         char **qlines = NULL;
7071         int numlines = 0;
7072
7073         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7074         if (!W_ERROR_IS_OK(result)) {
7075                 goto out;
7076         }
7077
7078         if (numlines) {
7079                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7080                 if (!info) {
7081                         DEBUG(10,("Returning WERR_NOMEM\n"));
7082                         result = WERR_NOMEM;
7083                         goto out;
7084                 }
7085
7086                 for (i=0; i<numlines; i++) {
7087                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7088                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7089                         if (!W_ERROR_IS_OK(result)) {
7090                                 goto out;
7091                         }
7092                 }
7093         }
7094         TALLOC_FREE(qlines);
7095
7096 out:
7097         if (!W_ERROR_IS_OK(result)) {
7098                 TALLOC_FREE(info);
7099                 TALLOC_FREE(qlines);
7100                 *count = 0;
7101                 *info_p = NULL;
7102                 return result;
7103         }
7104
7105         *info_p = info;
7106         *count = numlines;
7107
7108         return WERR_OK;
7109 }
7110
7111 /****************************************************************************
7112  enumports level 2.
7113 ****************************************************************************/
7114
7115 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7116                                 union spoolss_PortInfo **info_p,
7117                                 uint32_t *count)
7118 {
7119         union spoolss_PortInfo *info = NULL;
7120         int i=0;
7121         WERROR result = WERR_OK;
7122         char **qlines = NULL;
7123         int numlines = 0;
7124
7125         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7126         if (!W_ERROR_IS_OK(result)) {
7127                 goto out;
7128         }
7129
7130         if (numlines) {
7131                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7132                 if (!info) {
7133                         DEBUG(10,("Returning WERR_NOMEM\n"));
7134                         result = WERR_NOMEM;
7135                         goto out;
7136                 }
7137
7138                 for (i=0; i<numlines; i++) {
7139                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7140                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7141                         if (!W_ERROR_IS_OK(result)) {
7142                                 goto out;
7143                         }
7144                 }
7145         }
7146         TALLOC_FREE(qlines);
7147
7148 out:
7149         if (!W_ERROR_IS_OK(result)) {
7150                 TALLOC_FREE(info);
7151                 TALLOC_FREE(qlines);
7152                 *count = 0;
7153                 *info_p = NULL;
7154                 return result;
7155         }
7156
7157         *info_p = info;
7158         *count = numlines;
7159
7160         return WERR_OK;
7161 }
7162
7163 /****************************************************************
7164  _spoolss_EnumPorts
7165 ****************************************************************/
7166
7167 WERROR _spoolss_EnumPorts(pipes_struct *p,
7168                           struct spoolss_EnumPorts *r)
7169 {
7170         WERROR result;
7171
7172         /* that's an [in out] buffer */
7173
7174         if (!r->in.buffer && (r->in.offered != 0)) {
7175                 return WERR_INVALID_PARAM;
7176         }
7177
7178         DEBUG(4,("_spoolss_EnumPorts\n"));
7179
7180         *r->out.count = 0;
7181         *r->out.needed = 0;
7182         *r->out.info = NULL;
7183
7184         switch (r->in.level) {
7185         case 1:
7186                 result = enumports_level_1(p->mem_ctx, r->out.info,
7187                                            r->out.count);
7188                 break;
7189         case 2:
7190                 result = enumports_level_2(p->mem_ctx, r->out.info,
7191                                            r->out.count);
7192                 break;
7193         default:
7194                 return WERR_UNKNOWN_LEVEL;
7195         }
7196
7197         if (!W_ERROR_IS_OK(result)) {
7198                 return result;
7199         }
7200
7201         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7202                                                      spoolss_EnumPorts, NULL,
7203                                                      *r->out.info, r->in.level,
7204                                                      *r->out.count);
7205         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7206         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7207
7208         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7209 }
7210
7211 /****************************************************************************
7212 ****************************************************************************/
7213
7214 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7215                                            const char *server,
7216                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7217                                            struct spoolss_DeviceMode *devmode,
7218                                            struct security_descriptor *sec_desc,
7219                                            struct spoolss_UserLevelCtr *user_ctr,
7220                                            struct policy_handle *handle)
7221 {
7222         NT_PRINTER_INFO_LEVEL *printer = NULL;
7223         fstring name;
7224         int     snum;
7225         WERROR err = WERR_OK;
7226
7227         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7228                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7229                 return WERR_NOMEM;
7230         }
7231
7232         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7233         if (!convert_printer_info(info_ctr, printer)) {
7234                 free_a_printer(&printer, 2);
7235                 return WERR_NOMEM;
7236         }
7237
7238         /* samba does not have a concept of local, non-shared printers yet, so
7239          * make sure we always setup sharename - gd */
7240         if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7241                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7242                         "no sharename has been set, setting printername %s as sharename\n",
7243                         printer->info_2->printername));
7244                 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7245         }
7246
7247         /* check to see if the printer already exists */
7248
7249         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7250                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7251                         printer->info_2->sharename));
7252                 free_a_printer(&printer, 2);
7253                 return WERR_PRINTER_ALREADY_EXISTS;
7254         }
7255
7256         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7257                 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7258                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7259                                 printer->info_2->printername));
7260                         free_a_printer(&printer, 2);
7261                         return WERR_PRINTER_ALREADY_EXISTS;
7262                 }
7263         }
7264
7265         /* validate printer info struct */
7266         if (!info_ctr->info.info2->printername ||
7267             strlen(info_ctr->info.info2->printername) == 0) {
7268                 free_a_printer(&printer,2);
7269                 return WERR_INVALID_PRINTER_NAME;
7270         }
7271         if (!info_ctr->info.info2->portname ||
7272             strlen(info_ctr->info.info2->portname) == 0) {
7273                 free_a_printer(&printer,2);
7274                 return WERR_UNKNOWN_PORT;
7275         }
7276         if (!info_ctr->info.info2->drivername ||
7277             strlen(info_ctr->info.info2->drivername) == 0) {
7278                 free_a_printer(&printer,2);
7279                 return WERR_UNKNOWN_PRINTER_DRIVER;
7280         }
7281         if (!info_ctr->info.info2->printprocessor ||
7282             strlen(info_ctr->info.info2->printprocessor) == 0) {
7283                 free_a_printer(&printer,2);
7284                 return WERR_UNKNOWN_PRINTPROCESSOR;
7285         }
7286
7287         /* FIXME!!!  smbd should check to see if the driver is installed before
7288            trying to add a printer like this  --jerry */
7289
7290         if (*lp_addprinter_cmd() ) {
7291                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7292                                        printer) ) {
7293                         free_a_printer(&printer,2);
7294                         return WERR_ACCESS_DENIED;
7295                 }
7296         } else {
7297                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7298                         "smb.conf parameter \"addprinter command\" is defined. This"
7299                         "parameter must exist for this call to succeed\n",
7300                         printer->info_2->sharename ));
7301         }
7302
7303         /* use our primary netbios name since get_a_printer() will convert
7304            it to what the client expects on a case by case basis */
7305
7306         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7307              printer->info_2->sharename);
7308
7309
7310         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7311                 free_a_printer(&printer,2);
7312                 return WERR_ACCESS_DENIED;
7313         }
7314
7315         /* you must be a printer admin to add a new printer */
7316         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7317                 free_a_printer(&printer,2);
7318                 return WERR_ACCESS_DENIED;
7319         }
7320
7321         /*
7322          * Do sanity check on the requested changes for Samba.
7323          */
7324
7325         if (!check_printer_ok(printer->info_2, snum)) {
7326                 free_a_printer(&printer,2);
7327                 return WERR_INVALID_PARAM;
7328         }
7329
7330         /*
7331          * When a printer is created, the drivername bound to the printer is used
7332          * to lookup previously saved driver initialization info, which is then
7333          * bound to the new printer, simulating what happens in the Windows arch.
7334          */
7335
7336         if (!devmode)
7337         {
7338                 set_driver_init(printer, 2);
7339         }
7340         else
7341         {
7342                 /* A valid devmode was included, convert and link it
7343                 */
7344                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7345
7346                 if (!convert_devicemode(printer->info_2->printername, devmode,
7347                                         &printer->info_2->devmode)) {
7348                         return  WERR_NOMEM;
7349                 }
7350         }
7351
7352         /* write the ASCII on disk */
7353         err = mod_a_printer(printer, 2);
7354         if (!W_ERROR_IS_OK(err)) {
7355                 free_a_printer(&printer,2);
7356                 return err;
7357         }
7358
7359         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7360                 /* Handle open failed - remove addition. */
7361                 del_a_printer(printer->info_2->sharename);
7362                 free_a_printer(&printer,2);
7363                 ZERO_STRUCTP(handle);
7364                 return WERR_ACCESS_DENIED;
7365         }
7366
7367         update_c_setprinter(false);
7368         free_a_printer(&printer,2);
7369
7370         return WERR_OK;
7371 }
7372
7373 /****************************************************************
7374  _spoolss_AddPrinterEx
7375 ****************************************************************/
7376
7377 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7378                              struct spoolss_AddPrinterEx *r)
7379 {
7380         switch (r->in.info_ctr->level) {
7381         case 1:
7382                 /* we don't handle yet */
7383                 /* but I know what to do ... */
7384                 return WERR_UNKNOWN_LEVEL;
7385         case 2:
7386                 return spoolss_addprinterex_level_2(p, r->in.server,
7387                                                     r->in.info_ctr,
7388                                                     r->in.devmode_ctr->devmode,
7389                                                     r->in.secdesc_ctr->sd,
7390                                                     r->in.userlevel_ctr,
7391                                                     r->out.handle);
7392         default:
7393                 return WERR_UNKNOWN_LEVEL;
7394         }
7395 }
7396
7397 /****************************************************************
7398  _spoolss_AddPrinter
7399 ****************************************************************/
7400
7401 WERROR _spoolss_AddPrinter(pipes_struct *p,
7402                            struct spoolss_AddPrinter *r)
7403 {
7404         struct spoolss_AddPrinterEx a;
7405         struct spoolss_UserLevelCtr userlevel_ctr;
7406
7407         ZERO_STRUCT(userlevel_ctr);
7408
7409         userlevel_ctr.level = 1;
7410
7411         a.in.server             = r->in.server;
7412         a.in.info_ctr           = r->in.info_ctr;
7413         a.in.devmode_ctr        = r->in.devmode_ctr;
7414         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7415         a.in.userlevel_ctr      = &userlevel_ctr;
7416         a.out.handle            = r->out.handle;
7417
7418         return _spoolss_AddPrinterEx(p, &a);
7419 }
7420
7421 /****************************************************************
7422  _spoolss_AddPrinterDriverEx
7423 ****************************************************************/
7424
7425 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7426                                    struct spoolss_AddPrinterDriverEx *r)
7427 {
7428         WERROR err = WERR_OK;
7429         char *driver_name = NULL;
7430         uint32_t version;
7431         const char *fn;
7432
7433         switch (p->hdr_req.opnum) {
7434                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7435                         fn = "_spoolss_AddPrinterDriver";
7436                         break;
7437                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7438                         fn = "_spoolss_AddPrinterDriverEx";
7439                         break;
7440                 default:
7441                         return WERR_INVALID_PARAM;
7442         }
7443
7444         /*
7445          * we only support the semantics of AddPrinterDriver()
7446          * i.e. only copy files that are newer than existing ones
7447          */
7448
7449         if (r->in.flags == 0) {
7450                 return WERR_INVALID_PARAM;
7451         }
7452
7453         if (r->in.flags != APD_COPY_NEW_FILES) {
7454                 return WERR_ACCESS_DENIED;
7455         }
7456
7457         /* FIXME */
7458         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7459                 /* Clever hack from Martin Zielinski <mz@seh.de>
7460                  * to allow downgrade from level 8 (Vista).
7461                  */
7462                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7463                         r->in.info_ctr->level));
7464                 return WERR_UNKNOWN_LEVEL;
7465         }
7466
7467         DEBUG(5,("Cleaning driver's information\n"));
7468         err = clean_up_driver_struct(p, r->in.info_ctr);
7469         if (!W_ERROR_IS_OK(err))
7470                 goto done;
7471
7472         DEBUG(5,("Moving driver to final destination\n"));
7473         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7474                                                               &err)) ) {
7475                 goto done;
7476         }
7477
7478         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7479                 err = WERR_ACCESS_DENIED;
7480                 goto done;
7481         }
7482
7483         /*
7484          * I think this is where he DrvUpgradePrinter() hook would be
7485          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7486          * server.  Right now, we just need to send ourselves a message
7487          * to update each printer bound to this driver.   --jerry
7488          */
7489
7490         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7491                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7492                         fn, driver_name));
7493         }
7494
7495         /*
7496          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7497          * decide if the driver init data should be deleted. The rules are:
7498          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7499          *  2) delete init data only if there is no 2k/Xp driver
7500          *  3) always delete init data
7501          * The generalized rule is always use init data from the highest order driver.
7502          * It is necessary to follow the driver install by an initialization step to
7503          * finish off this process.
7504         */
7505
7506         switch (version) {
7507                 /*
7508                  * 9x printer driver - never delete init data
7509                 */
7510                 case 0:
7511                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7512                                 fn, driver_name));
7513                         break;
7514
7515                 /*
7516                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7517                  * there is no 2k/Xp driver init data for this driver name.
7518                 */
7519                 case 2:
7520                 {
7521                         struct spoolss_DriverInfo8 *driver1;
7522
7523                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
7524                                 /*
7525                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7526                                 */
7527                                 if (!del_driver_init(driver_name))
7528                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7529                                                 fn, driver_name));
7530                         } else {
7531                                 /*
7532                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7533                                 */
7534                                 free_a_printer_driver(driver1);
7535                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7536                                         fn, driver_name));
7537                         }
7538                 }
7539                 break;
7540
7541                 /*
7542                  * 2k or Xp printer driver - always delete init data
7543                 */
7544                 case 3:
7545                         if (!del_driver_init(driver_name))
7546                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7547                                         fn, driver_name));
7548                         break;
7549
7550                 default:
7551                         DEBUG(0,("%s: invalid level=%d\n", fn,
7552                                 r->in.info_ctr->level));
7553                         break;
7554         }
7555
7556
7557 done:
7558         return err;
7559 }
7560
7561 /****************************************************************
7562  _spoolss_AddPrinterDriver
7563 ****************************************************************/
7564
7565 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7566                                  struct spoolss_AddPrinterDriver *r)
7567 {
7568         struct spoolss_AddPrinterDriverEx a;
7569
7570         switch (r->in.info_ctr->level) {
7571         case 2:
7572         case 3:
7573         case 4:
7574         case 5:
7575                 break;
7576         default:
7577                 return WERR_UNKNOWN_LEVEL;
7578         }
7579
7580         a.in.servername         = r->in.servername;
7581         a.in.info_ctr           = r->in.info_ctr;
7582         a.in.flags              = APD_COPY_NEW_FILES;
7583
7584         return _spoolss_AddPrinterDriverEx(p, &a);
7585 }
7586
7587 /****************************************************************************
7588 ****************************************************************************/
7589
7590 struct _spoolss_paths {
7591         int type;
7592         const char *share;
7593         const char *dir;
7594 };
7595
7596 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7597
7598 static const struct _spoolss_paths spoolss_paths[]= {
7599         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7600         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7601 };
7602
7603 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7604                                           const char *servername,
7605                                           const char *environment,
7606                                           int component,
7607                                           char **path)
7608 {
7609         const char *pservername = NULL;
7610         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7611         const char *short_archi;
7612
7613         *path = NULL;
7614
7615         /* environment may be empty */
7616         if (environment && strlen(environment)) {
7617                 long_archi = environment;
7618         }
7619
7620         /* servername may be empty */
7621         if (servername && strlen(servername)) {
7622                 pservername = canon_servername(servername);
7623
7624                 if (!is_myname_or_ipaddr(pservername)) {
7625                         return WERR_INVALID_PARAM;
7626                 }
7627         }
7628
7629         if (!(short_archi = get_short_archi(long_archi))) {
7630                 return WERR_INVALID_ENVIRONMENT;
7631         }
7632
7633         switch (component) {
7634         case SPOOLSS_PRTPROCS_PATH:
7635         case SPOOLSS_DRIVER_PATH:
7636                 if (pservername) {
7637                         *path = talloc_asprintf(mem_ctx,
7638                                         "\\\\%s\\%s\\%s",
7639                                         pservername,
7640                                         spoolss_paths[component].share,
7641                                         short_archi);
7642                 } else {
7643                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7644                                         SPOOLSS_DEFAULT_SERVER_PATH,
7645                                         spoolss_paths[component].dir,
7646                                         short_archi);
7647                 }
7648                 break;
7649         default:
7650                 return WERR_INVALID_PARAM;
7651         }
7652
7653         if (!*path) {
7654                 return WERR_NOMEM;
7655         }
7656
7657         return WERR_OK;
7658 }
7659
7660 /****************************************************************************
7661 ****************************************************************************/
7662
7663 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7664                                           const char *servername,
7665                                           const char *environment,
7666                                           struct spoolss_DriverDirectoryInfo1 *r)
7667 {
7668         WERROR werr;
7669         char *path = NULL;
7670
7671         werr = compose_spoolss_server_path(mem_ctx,
7672                                            servername,
7673                                            environment,
7674                                            SPOOLSS_DRIVER_PATH,
7675                                            &path);
7676         if (!W_ERROR_IS_OK(werr)) {
7677                 return werr;
7678         }
7679
7680         DEBUG(4,("printer driver directory: [%s]\n", path));
7681
7682         r->directory_name = path;
7683
7684         return WERR_OK;
7685 }
7686
7687 /****************************************************************
7688  _spoolss_GetPrinterDriverDirectory
7689 ****************************************************************/
7690
7691 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7692                                           struct spoolss_GetPrinterDriverDirectory *r)
7693 {
7694         WERROR werror;
7695
7696         /* that's an [in out] buffer */
7697
7698         if (!r->in.buffer && (r->in.offered != 0)) {
7699                 return WERR_INVALID_PARAM;
7700         }
7701
7702         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7703                 r->in.level));
7704
7705         *r->out.needed = 0;
7706
7707         /* r->in.level is ignored */
7708
7709         werror = getprinterdriverdir_level_1(p->mem_ctx,
7710                                              r->in.server,
7711                                              r->in.environment,
7712                                              &r->out.info->info1);
7713         if (!W_ERROR_IS_OK(werror)) {
7714                 TALLOC_FREE(r->out.info);
7715                 return werror;
7716         }
7717
7718         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7719                                                r->out.info, r->in.level);
7720         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7721
7722         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7723 }
7724
7725 /****************************************************************
7726  _spoolss_EnumPrinterData
7727 ****************************************************************/
7728
7729 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7730                                 struct spoolss_EnumPrinterData *r)
7731 {
7732         WERROR result;
7733         struct spoolss_EnumPrinterDataEx r2;
7734         uint32_t count;
7735         struct spoolss_PrinterEnumValues *info, *val = NULL;
7736         uint32_t needed;
7737
7738         r2.in.handle    = r->in.handle;
7739         r2.in.key_name  = "PrinterDriverData";
7740         r2.in.offered   = 0;
7741         r2.out.count    = &count;
7742         r2.out.info     = &info;
7743         r2.out.needed   = &needed;
7744
7745         result = _spoolss_EnumPrinterDataEx(p, &r2);
7746         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7747                 r2.in.offered = needed;
7748                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7749         }
7750         if (!W_ERROR_IS_OK(result)) {
7751                 return result;
7752         }
7753
7754         /*
7755          * The NT machine wants to know the biggest size of value and data
7756          *
7757          * cf: MSDN EnumPrinterData remark section
7758          */
7759
7760         if (!r->in.value_offered && !r->in.data_offered) {
7761                 uint32_t biggest_valuesize = 0;
7762                 uint32_t biggest_datasize = 0;
7763                 int i, name_length;
7764
7765                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7766
7767                 for (i=0; i<count; i++) {
7768
7769                         name_length = strlen(info[i].value_name);
7770                         if (strlen(info[i].value_name) > biggest_valuesize) {
7771                                 biggest_valuesize = name_length;
7772                         }
7773
7774                         if (info[i].data_length > biggest_datasize) {
7775                                 biggest_datasize = info[i].data_length;
7776                         }
7777
7778                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7779                                 biggest_datasize));
7780                 }
7781
7782                 /* the value is an UNICODE string but real_value_size is the length
7783                    in bytes including the trailing 0 */
7784
7785                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7786                 *r->out.data_needed  = biggest_datasize;
7787
7788                 DEBUG(6,("final values: [%d], [%d]\n",
7789                         *r->out.value_needed, *r->out.data_needed));
7790
7791                 return WERR_OK;
7792         }
7793
7794         if (r->in.enum_index < count) {
7795                 val = &info[r->in.enum_index];
7796         }
7797
7798         if (val == NULL) {
7799                 /* out_value should default to "" or else NT4 has
7800                    problems unmarshalling the response */
7801
7802                 if (r->in.value_offered) {
7803                         *r->out.value_needed = 1;
7804                         r->out.value_name = talloc_strdup(r, "");
7805                         if (!r->out.value_name) {
7806                                 return WERR_NOMEM;
7807                         }
7808                 } else {
7809                         r->out.value_name = NULL;
7810                         *r->out.value_needed = 0;
7811                 }
7812
7813                 /* the data is counted in bytes */
7814
7815                 *r->out.data_needed = r->in.data_offered;
7816
7817                 result = WERR_NO_MORE_ITEMS;
7818         } else {
7819                 /*
7820                  * the value is:
7821                  * - counted in bytes in the request
7822                  * - counted in UNICODE chars in the max reply
7823                  * - counted in bytes in the real size
7824                  *
7825                  * take a pause *before* coding not *during* coding
7826                  */
7827
7828                 /* name */
7829                 if (r->in.value_offered) {
7830                         r->out.value_name = talloc_strdup(r, val->value_name);
7831                         if (!r->out.value_name) {
7832                                 return WERR_NOMEM;
7833                         }
7834                         *r->out.value_needed = val->value_name_len;
7835                 } else {
7836                         r->out.value_name = NULL;
7837                         *r->out.value_needed = 0;
7838                 }
7839
7840                 /* type */
7841
7842                 *r->out.type = val->type;
7843
7844                 /* data - counted in bytes */
7845
7846                 /*
7847                  * See the section "Dynamically Typed Query Parameters"
7848                  * in MS-RPRN.
7849                  */
7850
7851                 if (r->out.data && val->data && val->data->data &&
7852                                 val->data_length && r->in.data_offered) {
7853                         memcpy(r->out.data, val->data->data,
7854                                 MIN(val->data_length,r->in.data_offered));
7855                 }
7856
7857                 *r->out.data_needed = val->data_length;
7858
7859                 result = WERR_OK;
7860         }
7861
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         int i;
7950
7951         DEBUG(5,("_spoolss_AddForm\n"));
7952
7953         if (!Printer) {
7954                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7955                         OUR_HANDLE(r->in.handle)));
7956                 return WERR_BADFID;
7957         }
7958
7959
7960         /* forms can be added on printer or on the print server handle */
7961
7962         if ( Printer->printer_type == SPLHND_PRINTER )
7963         {
7964                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7965                         return WERR_BADFID;
7966
7967                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7968                 if (!W_ERROR_IS_OK(status))
7969                         goto done;
7970         }
7971
7972         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7973            and not a printer admin, then fail */
7974
7975         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7976              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7977              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7978                                           NULL, NULL,
7979                                           p->server_info->ptok,
7980                                           lp_printer_admin(snum))) {
7981                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7982                 status = WERR_ACCESS_DENIED;
7983                 goto done;
7984         }
7985
7986         switch (form->flags) {
7987         case SPOOLSS_FORM_USER:
7988         case SPOOLSS_FORM_BUILTIN:
7989         case SPOOLSS_FORM_PRINTER:
7990                 break;
7991         default:
7992                 status = WERR_INVALID_PARAM;
7993                 goto done;
7994         }
7995
7996         /* can't add if builtin */
7997
7998         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7999                 status = WERR_FILE_EXISTS;
8000                 goto done;
8001         }
8002
8003         count = get_ntforms(&list);
8004
8005         for (i=0; i < count; i++) {
8006                 if (strequal(form->form_name, list[i].name)) {
8007                         status = WERR_FILE_EXISTS;
8008                         goto done;
8009                 }
8010         }
8011
8012         if(!add_a_form(&list, form, &count)) {
8013                 status =  WERR_NOMEM;
8014                 goto done;
8015         }
8016
8017         become_root();
8018         write_ntforms(&list, count);
8019         unbecome_root();
8020
8021         /*
8022          * ChangeID must always be set if this is a printer
8023          */
8024
8025         if ( Printer->printer_type == SPLHND_PRINTER )
8026                 status = mod_a_printer(printer, 2);
8027
8028 done:
8029         if ( printer )
8030                 free_a_printer(&printer, 2);
8031         SAFE_FREE(list);
8032
8033         return status;
8034 }
8035
8036 /****************************************************************
8037  _spoolss_DeleteForm
8038 ****************************************************************/
8039
8040 WERROR _spoolss_DeleteForm(pipes_struct *p,
8041                            struct spoolss_DeleteForm *r)
8042 {
8043         const char *form_name = r->in.form_name;
8044         nt_forms_struct tmpForm;
8045         int count=0;
8046         nt_forms_struct *list=NULL;
8047         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8048         int snum = -1;
8049         WERROR status = WERR_OK;
8050         NT_PRINTER_INFO_LEVEL *printer = NULL;
8051         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8052         bool ret = false;
8053
8054         DEBUG(5,("_spoolss_DeleteForm\n"));
8055
8056         if (!Printer) {
8057                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8058                         OUR_HANDLE(r->in.handle)));
8059                 return WERR_BADFID;
8060         }
8061
8062         /* forms can be deleted on printer of on the print server handle */
8063
8064         if ( Printer->printer_type == SPLHND_PRINTER )
8065         {
8066                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8067                         return WERR_BADFID;
8068
8069                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8070                 if (!W_ERROR_IS_OK(status))
8071                         goto done;
8072         }
8073
8074         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8075              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8076              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8077                                           NULL, NULL,
8078                                           p->server_info->ptok,
8079                                           lp_printer_admin(snum))) {
8080                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8081                 return WERR_ACCESS_DENIED;
8082         }
8083
8084
8085         /* can't delete if builtin */
8086
8087         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8088                 status = WERR_INVALID_PARAM;
8089                 goto done;
8090         }
8091
8092         count = get_ntforms(&list);
8093
8094         become_root();
8095         ret = delete_a_form(&list, form_name, &count, &status);
8096         unbecome_root();
8097         if (ret == false) {
8098                 goto done;
8099         }
8100
8101         /*
8102          * ChangeID must always be set if this is a printer
8103          */
8104
8105         if ( Printer->printer_type == SPLHND_PRINTER )
8106                 status = mod_a_printer(printer, 2);
8107
8108 done:
8109         if ( printer )
8110                 free_a_printer(&printer, 2);
8111         SAFE_FREE(list);
8112
8113         return status;
8114 }
8115
8116 /****************************************************************
8117  _spoolss_SetForm
8118 ****************************************************************/
8119
8120 WERROR _spoolss_SetForm(pipes_struct *p,
8121                         struct spoolss_SetForm *r)
8122 {
8123         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8124         nt_forms_struct tmpForm;
8125         int snum = -1;
8126         WERROR status = WERR_OK;
8127         NT_PRINTER_INFO_LEVEL *printer = NULL;
8128         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8129
8130         int count=0;
8131         nt_forms_struct *list=NULL;
8132         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8133
8134         DEBUG(5,("_spoolss_SetForm\n"));
8135
8136         if (!Printer) {
8137                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8138                         OUR_HANDLE(r->in.handle)));
8139                 return WERR_BADFID;
8140         }
8141
8142         /* forms can be modified on printer of on the print server handle */
8143
8144         if ( Printer->printer_type == SPLHND_PRINTER )
8145         {
8146                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8147                         return WERR_BADFID;
8148
8149                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8150                 if (!W_ERROR_IS_OK(status))
8151                         goto done;
8152         }
8153
8154         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8155            and not a printer admin, then fail */
8156
8157         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8158              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8159              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8160                                           NULL, NULL,
8161                                           p->server_info->ptok,
8162                                           lp_printer_admin(snum))) {
8163                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8164                 status = WERR_ACCESS_DENIED;
8165                 goto done;
8166         }
8167
8168         /* can't set if builtin */
8169         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8170                 status = WERR_INVALID_PARAM;
8171                 goto done;
8172         }
8173
8174         count = get_ntforms(&list);
8175         update_a_form(&list, form, count);
8176         become_root();
8177         write_ntforms(&list, count);
8178         unbecome_root();
8179
8180         /*
8181          * ChangeID must always be set if this is a printer
8182          */
8183
8184         if ( Printer->printer_type == SPLHND_PRINTER )
8185                 status = mod_a_printer(printer, 2);
8186
8187
8188 done:
8189         if ( printer )
8190                 free_a_printer(&printer, 2);
8191         SAFE_FREE(list);
8192
8193         return status;
8194 }
8195
8196 /****************************************************************************
8197  fill_print_processor1
8198 ****************************************************************************/
8199
8200 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8201                                     struct spoolss_PrintProcessorInfo1 *r,
8202                                     const char *print_processor_name)
8203 {
8204         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8205         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8206
8207         return WERR_OK;
8208 }
8209
8210 /****************************************************************************
8211  enumprintprocessors level 1.
8212 ****************************************************************************/
8213
8214 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8215                                           union spoolss_PrintProcessorInfo **info_p,
8216                                           uint32_t *count)
8217 {
8218         union spoolss_PrintProcessorInfo *info;
8219         WERROR result;
8220
8221         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8222         W_ERROR_HAVE_NO_MEMORY(info);
8223
8224         *count = 1;
8225
8226         result = fill_print_processor1(info, &info[0].info1, "winprint");
8227         if (!W_ERROR_IS_OK(result)) {
8228                 goto out;
8229         }
8230
8231  out:
8232         if (!W_ERROR_IS_OK(result)) {
8233                 TALLOC_FREE(info);
8234                 *count = 0;
8235                 return result;
8236         }
8237
8238         *info_p = info;
8239
8240         return WERR_OK;
8241 }
8242
8243 /****************************************************************
8244  _spoolss_EnumPrintProcessors
8245 ****************************************************************/
8246
8247 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8248                                     struct spoolss_EnumPrintProcessors *r)
8249 {
8250         WERROR result;
8251
8252         /* that's an [in out] buffer */
8253
8254         if (!r->in.buffer && (r->in.offered != 0)) {
8255                 return WERR_INVALID_PARAM;
8256         }
8257
8258         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8259
8260         /*
8261          * Enumerate the print processors ...
8262          *
8263          * Just reply with "winprint", to keep NT happy
8264          * and I can use my nice printer checker.
8265          */
8266
8267         *r->out.count = 0;
8268         *r->out.needed = 0;
8269         *r->out.info = NULL;
8270
8271         switch (r->in.level) {
8272         case 1:
8273                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8274                                                      r->out.count);
8275                 break;
8276         default:
8277                 return WERR_UNKNOWN_LEVEL;
8278         }
8279
8280         if (!W_ERROR_IS_OK(result)) {
8281                 return result;
8282         }
8283
8284         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8285                                                      spoolss_EnumPrintProcessors, NULL,
8286                                                      *r->out.info, r->in.level,
8287                                                      *r->out.count);
8288         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8289         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8290
8291         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8292 }
8293
8294 /****************************************************************************
8295  fill_printprocdatatype1
8296 ****************************************************************************/
8297
8298 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8299                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8300                                       const char *name_array)
8301 {
8302         r->name_array = talloc_strdup(mem_ctx, name_array);
8303         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8304
8305         return WERR_OK;
8306 }
8307
8308 /****************************************************************************
8309  enumprintprocdatatypes level 1.
8310 ****************************************************************************/
8311
8312 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8313                                              union spoolss_PrintProcDataTypesInfo **info_p,
8314                                              uint32_t *count)
8315 {
8316         WERROR result;
8317         union spoolss_PrintProcDataTypesInfo *info;
8318
8319         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8320         W_ERROR_HAVE_NO_MEMORY(info);
8321
8322         *count = 1;
8323
8324         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8325         if (!W_ERROR_IS_OK(result)) {
8326                 goto out;
8327         }
8328
8329  out:
8330         if (!W_ERROR_IS_OK(result)) {
8331                 TALLOC_FREE(info);
8332                 *count = 0;
8333                 return result;
8334         }
8335
8336         *info_p = info;
8337
8338         return WERR_OK;
8339 }
8340
8341 /****************************************************************
8342  _spoolss_EnumPrintProcDataTypes
8343 ****************************************************************/
8344
8345 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8346                                        struct spoolss_EnumPrintProcDataTypes *r)
8347 {
8348         WERROR result;
8349
8350         /* that's an [in out] buffer */
8351
8352         if (!r->in.buffer && (r->in.offered != 0)) {
8353                 return WERR_INVALID_PARAM;
8354         }
8355
8356         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8357
8358         *r->out.count = 0;
8359         *r->out.needed = 0;
8360         *r->out.info = NULL;
8361
8362         switch (r->in.level) {
8363         case 1:
8364                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8365                                                         r->out.count);
8366                 break;
8367         default:
8368                 return WERR_UNKNOWN_LEVEL;
8369         }
8370
8371         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8372                                                      spoolss_EnumPrintProcDataTypes, NULL,
8373                                                      *r->out.info, r->in.level,
8374                                                      *r->out.count);
8375         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8376         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8377
8378         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8379 }
8380
8381 /****************************************************************************
8382  fill_monitor_1
8383 ****************************************************************************/
8384
8385 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8386                              struct spoolss_MonitorInfo1 *r,
8387                              const char *monitor_name)
8388 {
8389         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8390         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8391
8392         return WERR_OK;
8393 }
8394
8395 /****************************************************************************
8396  fill_monitor_2
8397 ****************************************************************************/
8398
8399 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8400                              struct spoolss_MonitorInfo2 *r,
8401                              const char *monitor_name,
8402                              const char *environment,
8403                              const char *dll_name)
8404 {
8405         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8406         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8407         r->environment                  = talloc_strdup(mem_ctx, environment);
8408         W_ERROR_HAVE_NO_MEMORY(r->environment);
8409         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8410         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8411
8412         return WERR_OK;
8413 }
8414
8415 /****************************************************************************
8416  enumprintmonitors level 1.
8417 ****************************************************************************/
8418
8419 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8420                                         union spoolss_MonitorInfo **info_p,
8421                                         uint32_t *count)
8422 {
8423         union spoolss_MonitorInfo *info;
8424         WERROR result = WERR_OK;
8425
8426         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8427         W_ERROR_HAVE_NO_MEMORY(info);
8428
8429         *count = 2;
8430
8431         result = fill_monitor_1(info, &info[0].info1,
8432                                 SPL_LOCAL_PORT);
8433         if (!W_ERROR_IS_OK(result)) {
8434                 goto out;
8435         }
8436
8437         result = fill_monitor_1(info, &info[1].info1,
8438                                 SPL_TCPIP_PORT);
8439         if (!W_ERROR_IS_OK(result)) {
8440                 goto out;
8441         }
8442
8443 out:
8444         if (!W_ERROR_IS_OK(result)) {
8445                 TALLOC_FREE(info);
8446                 *count = 0;
8447                 return result;
8448         }
8449
8450         *info_p = info;
8451
8452         return WERR_OK;
8453 }
8454
8455 /****************************************************************************
8456  enumprintmonitors level 2.
8457 ****************************************************************************/
8458
8459 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8460                                         union spoolss_MonitorInfo **info_p,
8461                                         uint32_t *count)
8462 {
8463         union spoolss_MonitorInfo *info;
8464         WERROR result = WERR_OK;
8465
8466         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8467         W_ERROR_HAVE_NO_MEMORY(info);
8468
8469         *count = 2;
8470
8471         result = fill_monitor_2(info, &info[0].info2,
8472                                 SPL_LOCAL_PORT,
8473                                 "Windows NT X86", /* FIXME */
8474                                 "localmon.dll");
8475         if (!W_ERROR_IS_OK(result)) {
8476                 goto out;
8477         }
8478
8479         result = fill_monitor_2(info, &info[1].info2,
8480                                 SPL_TCPIP_PORT,
8481                                 "Windows NT X86", /* FIXME */
8482                                 "tcpmon.dll");
8483         if (!W_ERROR_IS_OK(result)) {
8484                 goto out;
8485         }
8486
8487 out:
8488         if (!W_ERROR_IS_OK(result)) {
8489                 TALLOC_FREE(info);
8490                 *count = 0;
8491                 return result;
8492         }
8493
8494         *info_p = info;
8495
8496         return WERR_OK;
8497 }
8498
8499 /****************************************************************
8500  _spoolss_EnumMonitors
8501 ****************************************************************/
8502
8503 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8504                              struct spoolss_EnumMonitors *r)
8505 {
8506         WERROR result;
8507
8508         /* that's an [in out] buffer */
8509
8510         if (!r->in.buffer && (r->in.offered != 0)) {
8511                 return WERR_INVALID_PARAM;
8512         }
8513
8514         DEBUG(5,("_spoolss_EnumMonitors\n"));
8515
8516         /*
8517          * Enumerate the print monitors ...
8518          *
8519          * Just reply with "Local Port", to keep NT happy
8520          * and I can use my nice printer checker.
8521          */
8522
8523         *r->out.count = 0;
8524         *r->out.needed = 0;
8525         *r->out.info = NULL;
8526
8527         switch (r->in.level) {
8528         case 1:
8529                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8530                                                    r->out.count);
8531                 break;
8532         case 2:
8533                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8534                                                    r->out.count);
8535                 break;
8536         default:
8537                 return WERR_UNKNOWN_LEVEL;
8538         }
8539
8540         if (!W_ERROR_IS_OK(result)) {
8541                 return result;
8542         }
8543
8544         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8545                                                      spoolss_EnumMonitors, NULL,
8546                                                      *r->out.info, r->in.level,
8547                                                      *r->out.count);
8548         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8549         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8550
8551         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8552 }
8553
8554 /****************************************************************************
8555 ****************************************************************************/
8556
8557 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8558                              const print_queue_struct *queue,
8559                              int count, int snum,
8560                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8561                              uint32_t jobid,
8562                              struct spoolss_JobInfo1 *r)
8563 {
8564         int i = 0;
8565         bool found = false;
8566
8567         for (i=0; i<count; i++) {
8568                 if (queue[i].job == (int)jobid) {
8569                         found = true;
8570                         break;
8571                 }
8572         }
8573
8574         if (found == false) {
8575                 /* NT treats not found as bad param... yet another bad choice */
8576                 return WERR_INVALID_PARAM;
8577         }
8578
8579         return fill_job_info1(mem_ctx,
8580                               r,
8581                               &queue[i],
8582                               i,
8583                               snum,
8584                               ntprinter);
8585 }
8586
8587 /****************************************************************************
8588 ****************************************************************************/
8589
8590 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8591                              const print_queue_struct *queue,
8592                              int count, int snum,
8593                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8594                              uint32_t jobid,
8595                              struct spoolss_JobInfo2 *r)
8596 {
8597         int i = 0;
8598         bool found = false;
8599         struct spoolss_DeviceMode *devmode;
8600         NT_DEVICEMODE *nt_devmode;
8601         WERROR result;
8602
8603         for (i=0; i<count; i++) {
8604                 if (queue[i].job == (int)jobid) {
8605                         found = true;
8606                         break;
8607                 }
8608         }
8609
8610         if (found == false) {
8611                 /* NT treats not found as bad param... yet another bad
8612                    choice */
8613                 return WERR_INVALID_PARAM;
8614         }
8615
8616         /*
8617          * if the print job does not have a DEVMODE associated with it,
8618          * just use the one for the printer. A NULL devicemode is not
8619          *  a failure condition
8620          */
8621
8622         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8623         if (nt_devmode) {
8624                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8625                 W_ERROR_HAVE_NO_MEMORY(devmode);
8626                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8627                 if (!W_ERROR_IS_OK(result)) {
8628                         return result;
8629                 }
8630         } else {
8631                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8632                 W_ERROR_HAVE_NO_MEMORY(devmode);
8633         }
8634
8635         return fill_job_info2(mem_ctx,
8636                               r,
8637                               &queue[i],
8638                               i,
8639                               snum,
8640                               ntprinter,
8641                               devmode);
8642 }
8643
8644 /****************************************************************
8645  _spoolss_GetJob
8646 ****************************************************************/
8647
8648 WERROR _spoolss_GetJob(pipes_struct *p,
8649                        struct spoolss_GetJob *r)
8650 {
8651         WERROR result = WERR_OK;
8652         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8653         int snum;
8654         int count;
8655         print_queue_struct      *queue = NULL;
8656         print_status_struct prt_status;
8657
8658         /* that's an [in out] buffer */
8659
8660         if (!r->in.buffer && (r->in.offered != 0)) {
8661                 return WERR_INVALID_PARAM;
8662         }
8663
8664         DEBUG(5,("_spoolss_GetJob\n"));
8665
8666         *r->out.needed = 0;
8667
8668         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8669                 return WERR_BADFID;
8670         }
8671
8672         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8673         if (!W_ERROR_IS_OK(result)) {
8674                 return result;
8675         }
8676
8677         count = print_queue_status(snum, &queue, &prt_status);
8678
8679         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8680                      count, prt_status.status, prt_status.message));
8681
8682         switch (r->in.level) {
8683         case 1:
8684                 result = getjob_level_1(p->mem_ctx,
8685                                         queue, count, snum, ntprinter,
8686                                         r->in.job_id, &r->out.info->info1);
8687                 break;
8688         case 2:
8689                 result = getjob_level_2(p->mem_ctx,
8690                                         queue, count, snum, ntprinter,
8691                                         r->in.job_id, &r->out.info->info2);
8692                 break;
8693         default:
8694                 result = WERR_UNKNOWN_LEVEL;
8695                 break;
8696         }
8697
8698         SAFE_FREE(queue);
8699         free_a_printer(&ntprinter, 2);
8700
8701         if (!W_ERROR_IS_OK(result)) {
8702                 TALLOC_FREE(r->out.info);
8703                 return result;
8704         }
8705
8706         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8707                                                r->out.info, r->in.level);
8708         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8709
8710         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8711 }
8712
8713 /****************************************************************
8714  _spoolss_GetPrinterDataEx
8715 ****************************************************************/
8716
8717 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8718                                  struct spoolss_GetPrinterDataEx *r)
8719 {
8720
8721         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8722         struct regval_blob              *val = NULL;
8723         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8724         int                     snum = 0;
8725         WERROR result = WERR_OK;
8726         DATA_BLOB blob;
8727
8728         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8729
8730         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8731                 r->in.key_name, r->in.value_name));
8732
8733         /* in case of problem, return some default values */
8734
8735         *r->out.needed  = 0;
8736         *r->out.type    = REG_NONE;
8737
8738         if (!Printer) {
8739                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8740                         OUR_HANDLE(r->in.handle)));
8741                 result = WERR_BADFID;
8742                 goto done;
8743         }
8744
8745         /* Is the handle to a printer or to the server? */
8746
8747         if (Printer->printer_type == SPLHND_SERVER) {
8748
8749                 union spoolss_PrinterData data;
8750
8751                 result = getprinterdata_printer_server(p->mem_ctx,
8752                                                        r->in.value_name,
8753                                                        r->out.type,
8754                                                        &data);
8755                 if (!W_ERROR_IS_OK(result)) {
8756                         goto done;
8757                 }
8758
8759                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8760                                                   *r->out.type, &data);
8761                 if (!W_ERROR_IS_OK(result)) {
8762                         goto done;
8763                 }
8764
8765                 *r->out.needed = blob.length;
8766
8767                 if (r->in.offered >= *r->out.needed) {
8768                         memcpy(r->out.data, blob.data, blob.length);
8769                 }
8770
8771                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8772         }
8773
8774         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8775                 result = WERR_BADFID;
8776                 goto done;
8777         }
8778
8779         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8780         if (!W_ERROR_IS_OK(result)) {
8781                 goto done;
8782         }
8783
8784         /* check to see if the keyname is valid */
8785         if (!strlen(r->in.key_name)) {
8786                 result = WERR_INVALID_PARAM;
8787                 goto done;
8788         }
8789
8790         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8791
8792         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8793             strequal(r->in.value_name, "ChangeId")) {
8794                 *r->out.type = REG_DWORD;
8795                 *r->out.needed = 4;
8796                 if (r->in.offered >= *r->out.needed) {
8797                         SIVAL(r->out.data, 0, printer->info_2->changeid);
8798                         result = WERR_OK;
8799                 }
8800                 goto done;
8801         }
8802
8803         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8804                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8805                         "Invalid keyname [%s]\n", r->in.key_name ));
8806                 result = WERR_BADFILE;
8807                 goto done;
8808         }
8809
8810         val = get_printer_data(printer->info_2,
8811                                r->in.key_name, r->in.value_name);
8812         if (!val) {
8813                 result = WERR_BADFILE;
8814                 goto done;
8815         }
8816
8817         *r->out.needed = regval_size(val);
8818         *r->out.type = regval_type(val);
8819
8820         if (r->in.offered >= *r->out.needed) {
8821                 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8822         }
8823  done:
8824         if (printer) {
8825                 free_a_printer(&printer, 2);
8826         }
8827
8828         if (!W_ERROR_IS_OK(result)) {
8829                 return result;
8830         }
8831
8832         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8833         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8834
8835         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8836 }
8837
8838 /****************************************************************
8839  _spoolss_SetPrinterDataEx
8840 ****************************************************************/
8841
8842 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8843                                  struct spoolss_SetPrinterDataEx *r)
8844 {
8845         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8846         int                     snum = 0;
8847         WERROR                  result = WERR_OK;
8848         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8849         char                    *oid_string;
8850
8851         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8852
8853         /* From MSDN documentation of SetPrinterDataEx: pass request to
8854            SetPrinterData if key is "PrinterDriverData" */
8855
8856         if (!Printer) {
8857                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8858                         OUR_HANDLE(r->in.handle)));
8859                 return WERR_BADFID;
8860         }
8861
8862         if (Printer->printer_type == SPLHND_SERVER) {
8863                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8864                         "Not implemented for server handles yet\n"));
8865                 return WERR_INVALID_PARAM;
8866         }
8867
8868         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8869                 return WERR_BADFID;
8870         }
8871
8872         /*
8873          * Access check : NT returns "access denied" if you make a
8874          * SetPrinterData call without the necessary privildge.
8875          * we were originally returning OK if nothing changed
8876          * which made Win2k issue **a lot** of SetPrinterData
8877          * when connecting to a printer  --jerry
8878          */
8879
8880         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8881                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8882                         "change denied by handle access permissions\n"));
8883                 return WERR_ACCESS_DENIED;
8884         }
8885
8886         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8887         if (!W_ERROR_IS_OK(result)) {
8888                 return result;
8889         }
8890
8891         /* check for OID in valuename */
8892
8893         oid_string = strchr(r->in.value_name, ',');
8894         if (oid_string) {
8895                 *oid_string = '\0';
8896                 oid_string++;
8897         }
8898
8899         /*
8900          * When client side code sets a magic printer data key, detect it and save
8901          * the current printer data and the magic key's data (its the DEVMODE) for
8902          * future printer/driver initializations.
8903          */
8904         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8905                 /* Set devmode and printer initialization info */
8906                 result = save_driver_init(printer, 2, r->in.data, r->in.offered);
8907
8908                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8909
8910                 goto done;
8911         }
8912
8913         /* save the registry data */
8914
8915         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8916                                     r->in.type, r->in.data, r->in.offered);
8917
8918         if (W_ERROR_IS_OK(result)) {
8919                 /* save the OID if one was specified */
8920                 if (oid_string) {
8921                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8922                                 r->in.key_name, SPOOL_OID_KEY);
8923                         if (!str) {
8924                                 result = WERR_NOMEM;
8925                                 goto done;
8926                         }
8927
8928                         /*
8929                          * I'm not checking the status here on purpose.  Don't know
8930                          * if this is right, but I'm returning the status from the
8931                          * previous set_printer_dataex() call.  I have no idea if
8932                          * this is right.    --jerry
8933                          */
8934
8935                         set_printer_dataex(printer, str, r->in.value_name,
8936                                            REG_SZ, (uint8_t *)oid_string,
8937                                            strlen(oid_string)+1);
8938                 }
8939
8940                 result = mod_a_printer(printer, 2);
8941         }
8942
8943  done:
8944         free_a_printer(&printer, 2);
8945
8946         return result;
8947 }
8948
8949 /****************************************************************
8950  _spoolss_DeletePrinterDataEx
8951 ****************************************************************/
8952
8953 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8954                                     struct spoolss_DeletePrinterDataEx *r)
8955 {
8956         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8957         int             snum=0;
8958         WERROR          status = WERR_OK;
8959         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8960
8961         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8962
8963         if (!Printer) {
8964                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8965                         "Invalid handle (%s:%u:%u).\n",
8966                         OUR_HANDLE(r->in.handle)));
8967                 return WERR_BADFID;
8968         }
8969
8970         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8971                 return WERR_BADFID;
8972
8973         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8974                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8975                         "printer properties change denied by handle\n"));
8976                 return WERR_ACCESS_DENIED;
8977         }
8978
8979         if (!r->in.value_name || !r->in.key_name) {
8980                 return WERR_NOMEM;
8981         }
8982
8983         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8984         if (!W_ERROR_IS_OK(status))
8985                 return status;
8986
8987         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8988
8989         if ( W_ERROR_IS_OK(status) )
8990                 mod_a_printer( printer, 2 );
8991
8992         free_a_printer(&printer, 2);
8993
8994         return status;
8995 }
8996
8997 /****************************************************************
8998  _spoolss_EnumPrinterKey
8999 ****************************************************************/
9000
9001 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9002                                struct spoolss_EnumPrinterKey *r)
9003 {
9004         fstring         *keynames = NULL;
9005         int             num_keys;
9006         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9007         NT_PRINTER_DATA *data;
9008         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9009         int             snum = 0;
9010         WERROR          result = WERR_BADFILE;
9011         int i;
9012         const char **array = NULL;
9013         DATA_BLOB blob;
9014
9015         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9016
9017         if (!Printer) {
9018                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9019                         OUR_HANDLE(r->in.handle)));
9020                 return WERR_BADFID;
9021         }
9022
9023         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9024                 return WERR_BADFID;
9025         }
9026
9027         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9028         if (!W_ERROR_IS_OK(result)) {
9029                 return result;
9030         }
9031
9032         /* get the list of subkey names */
9033
9034         data = printer->info_2->data;
9035
9036         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9037         if (num_keys == -1) {
9038                 result = WERR_BADFILE;
9039                 goto done;
9040         }
9041
9042         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
9043         if (!array) {
9044                 result = WERR_NOMEM;
9045                 goto done;
9046         }
9047
9048         if (!num_keys) {
9049                 array[0] = talloc_strdup(array, "");
9050                 if (!array[0]) {
9051                         result = WERR_NOMEM;
9052                         goto done;
9053                 }
9054         }
9055
9056         for (i=0; i < num_keys; i++) {
9057
9058                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9059                         keynames[i]));
9060
9061                 array[i] = talloc_strdup(array, keynames[i]);
9062                 if (!array[i]) {
9063                         result = WERR_NOMEM;
9064                         goto done;
9065                 }
9066         }
9067
9068         if (!push_reg_multi_sz(p->mem_ctx, NULL, &blob, array)) {
9069                 result = WERR_NOMEM;
9070                 goto done;
9071         }
9072
9073         *r->out._ndr_size = r->in.offered / 2;
9074         *r->out.needed = blob.length;
9075
9076         if (r->in.offered < *r->out.needed) {
9077                 result = WERR_MORE_DATA;
9078         } else {
9079                 result = WERR_OK;
9080                 r->out.key_buffer->string_array = array;
9081         }
9082
9083  done:
9084         if (!W_ERROR_IS_OK(result)) {
9085                 TALLOC_FREE(array);
9086                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9087                         *r->out.needed = 0;
9088                 }
9089         }
9090
9091         free_a_printer(&printer, 2);
9092         SAFE_FREE(keynames);
9093
9094         return result;
9095 }
9096
9097 /****************************************************************
9098  _spoolss_DeletePrinterKey
9099 ****************************************************************/
9100
9101 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9102                                  struct spoolss_DeletePrinterKey *r)
9103 {
9104         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9105         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9106         int                     snum=0;
9107         WERROR                  status;
9108
9109         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9110
9111         if (!Printer) {
9112                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9113                         OUR_HANDLE(r->in.handle)));
9114                 return WERR_BADFID;
9115         }
9116
9117         /* if keyname == NULL, return error */
9118
9119         if ( !r->in.key_name )
9120                 return WERR_INVALID_PARAM;
9121
9122         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9123                 return WERR_BADFID;
9124
9125         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9126                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9127                         "printer properties change denied by handle\n"));
9128                 return WERR_ACCESS_DENIED;
9129         }
9130
9131         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9132         if (!W_ERROR_IS_OK(status))
9133                 return status;
9134
9135         /* delete the key and all subneys */
9136
9137         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9138
9139         if ( W_ERROR_IS_OK(status) )
9140                 status = mod_a_printer(printer, 2);
9141
9142         free_a_printer( &printer, 2 );
9143
9144         return status;
9145 }
9146
9147 /****************************************************************
9148 ****************************************************************/
9149
9150 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9151                                                    struct regval_blob *v,
9152                                                    struct spoolss_PrinterEnumValues *r)
9153 {
9154         r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
9155         W_ERROR_HAVE_NO_MEMORY(r->data);
9156
9157         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9158         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9159
9160         r->value_name_len = strlen_m_term(regval_name(v)) * 2;
9161
9162         r->type         = regval_type(v);
9163         r->data_length  = regval_size(v);
9164
9165         if (r->data_length) {
9166                 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
9167         }
9168
9169         return WERR_OK;
9170 }
9171
9172 /****************************************************************
9173  _spoolss_EnumPrinterDataEx
9174 ****************************************************************/
9175
9176 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9177                                   struct spoolss_EnumPrinterDataEx *r)
9178 {
9179         uint32_t        count = 0;
9180         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9181         struct spoolss_PrinterEnumValues *info = NULL;
9182         NT_PRINTER_DATA         *p_data;
9183         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9184         int             snum;
9185         WERROR          result;
9186         int             key_index;
9187         int             i;
9188
9189         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9190
9191         *r->out.count = 0;
9192         *r->out.needed = 0;
9193         *r->out.info = NULL;
9194
9195         if (!Printer) {
9196                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9197                         OUR_HANDLE(r->in.handle)));
9198                 return WERR_BADFID;
9199         }
9200
9201         /*
9202          * first check for a keyname of NULL or "".  Win2k seems to send
9203          * this a lot and we should send back WERR_INVALID_PARAM
9204          * no need to spend time looking up the printer in this case.
9205          * --jerry
9206          */
9207
9208         if (!strlen(r->in.key_name)) {
9209                 result = WERR_INVALID_PARAM;
9210                 goto done;
9211         }
9212
9213         /* get the printer off of disk */
9214
9215         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9216                 return WERR_BADFID;
9217         }
9218
9219         ZERO_STRUCT(printer);
9220         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9221         if (!W_ERROR_IS_OK(result)) {
9222                 return result;
9223         }
9224
9225         /* now look for a match on the key name */
9226
9227         p_data = printer->info_2->data;
9228
9229         key_index = lookup_printerkey(p_data, r->in.key_name);
9230         if (key_index == -1) {
9231                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9232                         r->in.key_name));
9233                 result = WERR_INVALID_PARAM;
9234                 goto done;
9235         }
9236
9237         /* allocate the memory for the array of pointers -- if necessary */
9238
9239         count = regval_ctr_numvals(p_data->keys[key_index].values);
9240         if (!count) {
9241                 result = WERR_OK; /* ??? */
9242                 goto done;
9243         }
9244
9245         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9246                                  struct spoolss_PrinterEnumValues,
9247                                  count);
9248         if (!info) {
9249                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9250                 result = WERR_NOMEM;
9251                 goto done;
9252         }
9253
9254         /*
9255          * loop through all params and build the array to pass
9256          * back to the  client
9257          */
9258
9259         for (i=0; i < count; i++) {
9260
9261                 struct regval_blob      *val;
9262
9263                 /* lookup the registry value */
9264
9265                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9266
9267                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9268
9269                 /* copy the data */
9270
9271                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9272                 if (!W_ERROR_IS_OK(result)) {
9273                         goto done;
9274                 }
9275         }
9276
9277 #if 0 /* FIXME - gd */
9278         /* housekeeping information in the reply */
9279
9280         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9281          * the hand marshalled container size is a multiple
9282          * of 4 bytes for RPC alignment.
9283          */
9284
9285         if (needed % 4) {
9286                 needed += 4-(needed % 4);
9287         }
9288 #endif
9289         *r->out.count   = count;
9290         *r->out.info    = info;
9291
9292  done:
9293
9294         if (printer) {
9295                 free_a_printer(&printer, 2);
9296         }
9297
9298         if (!W_ERROR_IS_OK(result)) {
9299                 return result;
9300         }
9301
9302         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9303                                                spoolss_EnumPrinterDataEx, NULL,
9304                                                *r->out.info,
9305                                                *r->out.count);
9306         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9307         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9308
9309         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9310 }
9311
9312 /****************************************************************************
9313 ****************************************************************************/
9314
9315 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9316                                                  const char *servername,
9317                                                  const char *environment,
9318                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9319 {
9320         WERROR werr;
9321         char *path = NULL;
9322
9323         werr = compose_spoolss_server_path(mem_ctx,
9324                                            servername,
9325                                            environment,
9326                                            SPOOLSS_PRTPROCS_PATH,
9327                                            &path);
9328         if (!W_ERROR_IS_OK(werr)) {
9329                 return werr;
9330         }
9331
9332         DEBUG(4,("print processor directory: [%s]\n", path));
9333
9334         r->directory_name = path;
9335
9336         return WERR_OK;
9337 }
9338
9339 /****************************************************************
9340  _spoolss_GetPrintProcessorDirectory
9341 ****************************************************************/
9342
9343 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9344                                            struct spoolss_GetPrintProcessorDirectory *r)
9345 {
9346         WERROR result;
9347
9348         /* that's an [in out] buffer */
9349
9350         if (!r->in.buffer && (r->in.offered != 0)) {
9351                 return WERR_INVALID_PARAM;
9352         }
9353
9354         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9355                 r->in.level));
9356
9357         *r->out.needed = 0;
9358
9359         /* r->in.level is ignored */
9360
9361         /* We always should reply with a local print processor directory so that
9362          * users are not forced to have a [prnproc$] share on the Samba spoolss
9363          * server - Guenther */
9364
9365         result = getprintprocessordirectory_level_1(p->mem_ctx,
9366                                                     NULL, /* r->in.server */
9367                                                     r->in.environment,
9368                                                     &r->out.info->info1);
9369         if (!W_ERROR_IS_OK(result)) {
9370                 TALLOC_FREE(r->out.info);
9371                 return result;
9372         }
9373
9374         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9375                                                r->out.info, r->in.level);
9376         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9377
9378         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9379 }
9380
9381 /*******************************************************************
9382  ********************************************************************/
9383
9384 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9385                                const char *dllname)
9386 {
9387         enum ndr_err_code ndr_err;
9388         struct spoolss_MonitorUi ui;
9389
9390         ui.dll_name = dllname;
9391
9392         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9393                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9394         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9395                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9396         }
9397         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9398 }
9399
9400 /*******************************************************************
9401  Streams the monitor UI DLL name in UNICODE
9402 *******************************************************************/
9403
9404 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9405                                NT_USER_TOKEN *token, DATA_BLOB *in,
9406                                DATA_BLOB *out, uint32_t *needed)
9407 {
9408         const char *dllname = "tcpmonui.dll";
9409
9410         *needed = (strlen(dllname)+1) * 2;
9411
9412         if (out->length < *needed) {
9413                 return WERR_INSUFFICIENT_BUFFER;
9414         }
9415
9416         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9417                 return WERR_NOMEM;
9418         }
9419
9420         return WERR_OK;
9421 }
9422
9423 /*******************************************************************
9424  ********************************************************************/
9425
9426 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9427                              struct spoolss_PortData1 *port1,
9428                              const DATA_BLOB *buf)
9429 {
9430         enum ndr_err_code ndr_err;
9431         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9432                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9433         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9434                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9435         }
9436         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9437 }
9438
9439 /*******************************************************************
9440  ********************************************************************/
9441
9442 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9443                              struct spoolss_PortData2 *port2,
9444                              const DATA_BLOB *buf)
9445 {
9446         enum ndr_err_code ndr_err;
9447         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9448                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9449         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9450                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9451         }
9452         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9453 }
9454
9455 /*******************************************************************
9456  Create a new TCP/IP port
9457 *******************************************************************/
9458
9459 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9460                              NT_USER_TOKEN *token, DATA_BLOB *in,
9461                              DATA_BLOB *out, uint32_t *needed)
9462 {
9463         struct spoolss_PortData1 port1;
9464         struct spoolss_PortData2 port2;
9465         char *device_uri = NULL;
9466         uint32_t version;
9467
9468         const char *portname;
9469         const char *hostaddress;
9470         const char *queue;
9471         uint32_t port_number;
9472         uint32_t protocol;
9473
9474         /* peek for spoolss_PortData version */
9475
9476         if (!in || (in->length < (128 + 4))) {
9477                 return WERR_GENERAL_FAILURE;
9478         }
9479
9480         version = IVAL(in->data, 128);
9481
9482         switch (version) {
9483                 case 1:
9484                         ZERO_STRUCT(port1);
9485
9486                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9487                                 return WERR_NOMEM;
9488                         }
9489
9490                         portname        = port1.portname;
9491                         hostaddress     = port1.hostaddress;
9492                         queue           = port1.queue;
9493                         protocol        = port1.protocol;
9494                         port_number     = port1.port_number;
9495
9496                         break;
9497                 case 2:
9498                         ZERO_STRUCT(port2);
9499
9500                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9501                                 return WERR_NOMEM;
9502                         }
9503
9504                         portname        = port2.portname;
9505                         hostaddress     = port2.hostaddress;
9506                         queue           = port2.queue;
9507                         protocol        = port2.protocol;
9508                         port_number     = port2.port_number;
9509
9510                         break;
9511                 default:
9512                         DEBUG(1,("xcvtcp_addport: "
9513                                 "unknown version of port_data: %d\n", version));
9514                         return WERR_UNKNOWN_PORT;
9515         }
9516
9517         /* create the device URI and call the add_port_hook() */
9518
9519         switch (protocol) {
9520         case PROTOCOL_RAWTCP_TYPE:
9521                 device_uri = talloc_asprintf(mem_ctx,
9522                                 "socket://%s:%d/", hostaddress,
9523                                 port_number);
9524                 break;
9525
9526         case PROTOCOL_LPR_TYPE:
9527                 device_uri = talloc_asprintf(mem_ctx,
9528                         "lpr://%s/%s", hostaddress, queue );
9529                 break;
9530
9531         default:
9532                 return WERR_UNKNOWN_PORT;
9533         }
9534
9535         if (!device_uri) {
9536                 return WERR_NOMEM;
9537         }
9538
9539         return add_port_hook(mem_ctx, token, portname, device_uri);
9540 }
9541
9542 /*******************************************************************
9543 *******************************************************************/
9544
9545 struct xcv_api_table xcvtcp_cmds[] = {
9546         { "MonitorUI",  xcvtcp_monitorui },
9547         { "AddPort",    xcvtcp_addport},
9548         { NULL,         NULL }
9549 };
9550
9551 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9552                                      NT_USER_TOKEN *token, const char *command,
9553                                      DATA_BLOB *inbuf,
9554                                      DATA_BLOB *outbuf,
9555                                      uint32_t *needed )
9556 {
9557         int i;
9558
9559         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9560
9561         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9562                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9563                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9564         }
9565
9566         return WERR_BADFUNC;
9567 }
9568
9569 /*******************************************************************
9570 *******************************************************************/
9571 #if 0   /* don't support management using the "Local Port" monitor */
9572
9573 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9574                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9575                                  DATA_BLOB *out, uint32_t *needed)
9576 {
9577         const char *dllname = "localui.dll";
9578
9579         *needed = (strlen(dllname)+1) * 2;
9580
9581         if (out->length < *needed) {
9582                 return WERR_INSUFFICIENT_BUFFER;
9583         }
9584
9585         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9586                 return WERR_NOMEM;
9587         }
9588
9589         return WERR_OK;
9590 }
9591
9592 /*******************************************************************
9593 *******************************************************************/
9594
9595 struct xcv_api_table xcvlocal_cmds[] = {
9596         { "MonitorUI",  xcvlocal_monitorui },
9597         { NULL,         NULL }
9598 };
9599 #else
9600 struct xcv_api_table xcvlocal_cmds[] = {
9601         { NULL,         NULL }
9602 };
9603 #endif
9604
9605
9606
9607 /*******************************************************************
9608 *******************************************************************/
9609
9610 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9611                                        NT_USER_TOKEN *token, const char *command,
9612                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9613                                        uint32_t *needed)
9614 {
9615         int i;
9616
9617         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9618
9619         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9620                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9621                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9622         }
9623         return WERR_BADFUNC;
9624 }
9625
9626 /****************************************************************
9627  _spoolss_XcvData
9628 ****************************************************************/
9629
9630 WERROR _spoolss_XcvData(pipes_struct *p,
9631                         struct spoolss_XcvData *r)
9632 {
9633         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9634         DATA_BLOB out_data = data_blob_null;
9635         WERROR werror;
9636
9637         if (!Printer) {
9638                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9639                         OUR_HANDLE(r->in.handle)));
9640                 return WERR_BADFID;
9641         }
9642
9643         /* Has to be a handle to the TCP/IP port monitor */
9644
9645         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9646                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9647                 return WERR_BADFID;
9648         }
9649
9650         /* requires administrative access to the server */
9651
9652         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9653                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9654                 return WERR_ACCESS_DENIED;
9655         }
9656
9657         /* Allocate the outgoing buffer */
9658
9659         if (r->in.out_data_size) {
9660                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9661                 if (out_data.data == NULL) {
9662                         return WERR_NOMEM;
9663                 }
9664         }
9665
9666         switch ( Printer->printer_type ) {
9667         case SPLHND_PORTMON_TCP:
9668                 werror = process_xcvtcp_command(p->mem_ctx,
9669                                                 p->server_info->ptok,
9670                                                 r->in.function_name,
9671                                                 &r->in.in_data, &out_data,
9672                                                 r->out.needed);
9673                 break;
9674         case SPLHND_PORTMON_LOCAL:
9675                 werror = process_xcvlocal_command(p->mem_ctx,
9676                                                   p->server_info->ptok,
9677                                                   r->in.function_name,
9678                                                   &r->in.in_data, &out_data,
9679                                                   r->out.needed);
9680                 break;
9681         default:
9682                 werror = WERR_INVALID_PRINT_MONITOR;
9683         }
9684
9685         if (!W_ERROR_IS_OK(werror)) {
9686                 return werror;
9687         }
9688
9689         *r->out.status_code = 0;
9690
9691         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9692                 memcpy(r->out.out_data, out_data.data,
9693                         MIN(r->in.out_data_size, out_data.length));
9694         }
9695
9696         return WERR_OK;
9697 }
9698
9699 /****************************************************************
9700  _spoolss_AddPrintProcessor
9701 ****************************************************************/
9702
9703 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9704                                   struct spoolss_AddPrintProcessor *r)
9705 {
9706         /* for now, just indicate success and ignore the add.  We'll
9707            automatically set the winprint processor for printer
9708            entries later.  Used to debug the LexMark Optra S 1855 PCL
9709            driver --jerry */
9710
9711         return WERR_OK;
9712 }
9713
9714 /****************************************************************
9715  _spoolss_AddPort
9716 ****************************************************************/
9717
9718 WERROR _spoolss_AddPort(pipes_struct *p,
9719                         struct spoolss_AddPort *r)
9720 {
9721         /* do what w2k3 does */
9722
9723         return WERR_NOT_SUPPORTED;
9724 }
9725
9726 /****************************************************************
9727  _spoolss_GetPrinterDriver
9728 ****************************************************************/
9729
9730 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9731                                  struct spoolss_GetPrinterDriver *r)
9732 {
9733         p->rng_fault_state = true;
9734         return WERR_NOT_SUPPORTED;
9735 }
9736
9737 /****************************************************************
9738  _spoolss_ReadPrinter
9739 ****************************************************************/
9740
9741 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9742                             struct spoolss_ReadPrinter *r)
9743 {
9744         p->rng_fault_state = true;
9745         return WERR_NOT_SUPPORTED;
9746 }
9747
9748 /****************************************************************
9749  _spoolss_WaitForPrinterChange
9750 ****************************************************************/
9751
9752 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9753                                      struct spoolss_WaitForPrinterChange *r)
9754 {
9755         p->rng_fault_state = true;
9756         return WERR_NOT_SUPPORTED;
9757 }
9758
9759 /****************************************************************
9760  _spoolss_ConfigurePort
9761 ****************************************************************/
9762
9763 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9764                               struct spoolss_ConfigurePort *r)
9765 {
9766         p->rng_fault_state = true;
9767         return WERR_NOT_SUPPORTED;
9768 }
9769
9770 /****************************************************************
9771  _spoolss_DeletePort
9772 ****************************************************************/
9773
9774 WERROR _spoolss_DeletePort(pipes_struct *p,
9775                            struct spoolss_DeletePort *r)
9776 {
9777         p->rng_fault_state = true;
9778         return WERR_NOT_SUPPORTED;
9779 }
9780
9781 /****************************************************************
9782  _spoolss_CreatePrinterIC
9783 ****************************************************************/
9784
9785 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9786                                 struct spoolss_CreatePrinterIC *r)
9787 {
9788         p->rng_fault_state = true;
9789         return WERR_NOT_SUPPORTED;
9790 }
9791
9792 /****************************************************************
9793  _spoolss_PlayGDIScriptOnPrinterIC
9794 ****************************************************************/
9795
9796 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9797                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9798 {
9799         p->rng_fault_state = true;
9800         return WERR_NOT_SUPPORTED;
9801 }
9802
9803 /****************************************************************
9804  _spoolss_DeletePrinterIC
9805 ****************************************************************/
9806
9807 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9808                                 struct spoolss_DeletePrinterIC *r)
9809 {
9810         p->rng_fault_state = true;
9811         return WERR_NOT_SUPPORTED;
9812 }
9813
9814 /****************************************************************
9815  _spoolss_AddPrinterConnection
9816 ****************************************************************/
9817
9818 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9819                                      struct spoolss_AddPrinterConnection *r)
9820 {
9821         p->rng_fault_state = true;
9822         return WERR_NOT_SUPPORTED;
9823 }
9824
9825 /****************************************************************
9826  _spoolss_DeletePrinterConnection
9827 ****************************************************************/
9828
9829 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9830                                         struct spoolss_DeletePrinterConnection *r)
9831 {
9832         p->rng_fault_state = true;
9833         return WERR_NOT_SUPPORTED;
9834 }
9835
9836 /****************************************************************
9837  _spoolss_PrinterMessageBox
9838 ****************************************************************/
9839
9840 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9841                                   struct spoolss_PrinterMessageBox *r)
9842 {
9843         p->rng_fault_state = true;
9844         return WERR_NOT_SUPPORTED;
9845 }
9846
9847 /****************************************************************
9848  _spoolss_AddMonitor
9849 ****************************************************************/
9850
9851 WERROR _spoolss_AddMonitor(pipes_struct *p,
9852                            struct spoolss_AddMonitor *r)
9853 {
9854         p->rng_fault_state = true;
9855         return WERR_NOT_SUPPORTED;
9856 }
9857
9858 /****************************************************************
9859  _spoolss_DeleteMonitor
9860 ****************************************************************/
9861
9862 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9863                               struct spoolss_DeleteMonitor *r)
9864 {
9865         p->rng_fault_state = true;
9866         return WERR_NOT_SUPPORTED;
9867 }
9868
9869 /****************************************************************
9870  _spoolss_DeletePrintProcessor
9871 ****************************************************************/
9872
9873 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9874                                      struct spoolss_DeletePrintProcessor *r)
9875 {
9876         p->rng_fault_state = true;
9877         return WERR_NOT_SUPPORTED;
9878 }
9879
9880 /****************************************************************
9881  _spoolss_AddPrintProvidor
9882 ****************************************************************/
9883
9884 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9885                                  struct spoolss_AddPrintProvidor *r)
9886 {
9887         p->rng_fault_state = true;
9888         return WERR_NOT_SUPPORTED;
9889 }
9890
9891 /****************************************************************
9892  _spoolss_DeletePrintProvidor
9893 ****************************************************************/
9894
9895 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9896                                     struct spoolss_DeletePrintProvidor *r)
9897 {
9898         p->rng_fault_state = true;
9899         return WERR_NOT_SUPPORTED;
9900 }
9901
9902 /****************************************************************
9903  _spoolss_FindFirstPrinterChangeNotification
9904 ****************************************************************/
9905
9906 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9907                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9908 {
9909         p->rng_fault_state = true;
9910         return WERR_NOT_SUPPORTED;
9911 }
9912
9913 /****************************************************************
9914  _spoolss_FindNextPrinterChangeNotification
9915 ****************************************************************/
9916
9917 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9918                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9919 {
9920         p->rng_fault_state = true;
9921         return WERR_NOT_SUPPORTED;
9922 }
9923
9924 /****************************************************************
9925  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9926 ****************************************************************/
9927
9928 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9929                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9930 {
9931         p->rng_fault_state = true;
9932         return WERR_NOT_SUPPORTED;
9933 }
9934
9935 /****************************************************************
9936  _spoolss_ReplyOpenPrinter
9937 ****************************************************************/
9938
9939 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9940                                  struct spoolss_ReplyOpenPrinter *r)
9941 {
9942         p->rng_fault_state = true;
9943         return WERR_NOT_SUPPORTED;
9944 }
9945
9946 /****************************************************************
9947  _spoolss_RouterReplyPrinter
9948 ****************************************************************/
9949
9950 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9951                                    struct spoolss_RouterReplyPrinter *r)
9952 {
9953         p->rng_fault_state = true;
9954         return WERR_NOT_SUPPORTED;
9955 }
9956
9957 /****************************************************************
9958  _spoolss_ReplyClosePrinter
9959 ****************************************************************/
9960
9961 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9962                                   struct spoolss_ReplyClosePrinter *r)
9963 {
9964         p->rng_fault_state = true;
9965         return WERR_NOT_SUPPORTED;
9966 }
9967
9968 /****************************************************************
9969  _spoolss_AddPortEx
9970 ****************************************************************/
9971
9972 WERROR _spoolss_AddPortEx(pipes_struct *p,
9973                           struct spoolss_AddPortEx *r)
9974 {
9975         p->rng_fault_state = true;
9976         return WERR_NOT_SUPPORTED;
9977 }
9978
9979 /****************************************************************
9980  _spoolss_RouterFindFirstPrinterChangeNotification
9981 ****************************************************************/
9982
9983 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9984                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9985 {
9986         p->rng_fault_state = true;
9987         return WERR_NOT_SUPPORTED;
9988 }
9989
9990 /****************************************************************
9991  _spoolss_SpoolerInit
9992 ****************************************************************/
9993
9994 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9995                             struct spoolss_SpoolerInit *r)
9996 {
9997         p->rng_fault_state = true;
9998         return WERR_NOT_SUPPORTED;
9999 }
10000
10001 /****************************************************************
10002  _spoolss_ResetPrinterEx
10003 ****************************************************************/
10004
10005 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10006                                struct spoolss_ResetPrinterEx *r)
10007 {
10008         p->rng_fault_state = true;
10009         return WERR_NOT_SUPPORTED;
10010 }
10011
10012 /****************************************************************
10013  _spoolss_RouterReplyPrinterEx
10014 ****************************************************************/
10015
10016 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10017                                      struct spoolss_RouterReplyPrinterEx *r)
10018 {
10019         p->rng_fault_state = true;
10020         return WERR_NOT_SUPPORTED;
10021 }
10022
10023 /****************************************************************
10024  _spoolss_44
10025 ****************************************************************/
10026
10027 WERROR _spoolss_44(pipes_struct *p,
10028                    struct spoolss_44 *r)
10029 {
10030         p->rng_fault_state = true;
10031         return WERR_NOT_SUPPORTED;
10032 }
10033
10034 /****************************************************************
10035  _spoolss_47
10036 ****************************************************************/
10037
10038 WERROR _spoolss_47(pipes_struct *p,
10039                    struct spoolss_47 *r)
10040 {
10041         p->rng_fault_state = true;
10042         return WERR_NOT_SUPPORTED;
10043 }
10044
10045 /****************************************************************
10046  _spoolss_4a
10047 ****************************************************************/
10048
10049 WERROR _spoolss_4a(pipes_struct *p,
10050                    struct spoolss_4a *r)
10051 {
10052         p->rng_fault_state = true;
10053         return WERR_NOT_SUPPORTED;
10054 }
10055
10056 /****************************************************************
10057  _spoolss_4b
10058 ****************************************************************/
10059
10060 WERROR _spoolss_4b(pipes_struct *p,
10061                    struct spoolss_4b *r)
10062 {
10063         p->rng_fault_state = true;
10064         return WERR_NOT_SUPPORTED;
10065 }
10066
10067 /****************************************************************
10068  _spoolss_4c
10069 ****************************************************************/
10070
10071 WERROR _spoolss_4c(pipes_struct *p,
10072                    struct spoolss_4c *r)
10073 {
10074         p->rng_fault_state = true;
10075         return WERR_NOT_SUPPORTED;
10076 }
10077
10078 /****************************************************************
10079  _spoolss_53
10080 ****************************************************************/
10081
10082 WERROR _spoolss_53(pipes_struct *p,
10083                    struct spoolss_53 *r)
10084 {
10085         p->rng_fault_state = true;
10086         return WERR_NOT_SUPPORTED;
10087 }
10088
10089 /****************************************************************
10090  _spoolss_55
10091 ****************************************************************/
10092
10093 WERROR _spoolss_55(pipes_struct *p,
10094                    struct spoolss_55 *r)
10095 {
10096         p->rng_fault_state = true;
10097         return WERR_NOT_SUPPORTED;
10098 }
10099
10100 /****************************************************************
10101  _spoolss_56
10102 ****************************************************************/
10103
10104 WERROR _spoolss_56(pipes_struct *p,
10105                    struct spoolss_56 *r)
10106 {
10107         p->rng_fault_state = true;
10108         return WERR_NOT_SUPPORTED;
10109 }
10110
10111 /****************************************************************
10112  _spoolss_57
10113 ****************************************************************/
10114
10115 WERROR _spoolss_57(pipes_struct *p,
10116                    struct spoolss_57 *r)
10117 {
10118         p->rng_fault_state = true;
10119         return WERR_NOT_SUPPORTED;
10120 }
10121
10122 /****************************************************************
10123  _spoolss_5a
10124 ****************************************************************/
10125
10126 WERROR _spoolss_5a(pipes_struct *p,
10127                    struct spoolss_5a *r)
10128 {
10129         p->rng_fault_state = true;
10130         return WERR_NOT_SUPPORTED;
10131 }
10132
10133 /****************************************************************
10134  _spoolss_5b
10135 ****************************************************************/
10136
10137 WERROR _spoolss_5b(pipes_struct *p,
10138                    struct spoolss_5b *r)
10139 {
10140         p->rng_fault_state = true;
10141         return WERR_NOT_SUPPORTED;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_5c
10146 ****************************************************************/
10147
10148 WERROR _spoolss_5c(pipes_struct *p,
10149                    struct spoolss_5c *r)
10150 {
10151         p->rng_fault_state = true;
10152         return WERR_NOT_SUPPORTED;
10153 }
10154
10155 /****************************************************************
10156  _spoolss_5d
10157 ****************************************************************/
10158
10159 WERROR _spoolss_5d(pipes_struct *p,
10160                    struct spoolss_5d *r)
10161 {
10162         p->rng_fault_state = true;
10163         return WERR_NOT_SUPPORTED;
10164 }
10165
10166 /****************************************************************
10167  _spoolss_5e
10168 ****************************************************************/
10169
10170 WERROR _spoolss_5e(pipes_struct *p,
10171                    struct spoolss_5e *r)
10172 {
10173         p->rng_fault_state = true;
10174         return WERR_NOT_SUPPORTED;
10175 }
10176
10177 /****************************************************************
10178  _spoolss_5f
10179 ****************************************************************/
10180
10181 WERROR _spoolss_5f(pipes_struct *p,
10182                    struct spoolss_5f *r)
10183 {
10184         p->rng_fault_state = true;
10185         return WERR_NOT_SUPPORTED;
10186 }
10187
10188 /****************************************************************
10189  _spoolss_60
10190 ****************************************************************/
10191
10192 WERROR _spoolss_60(pipes_struct *p,
10193                    struct spoolss_60 *r)
10194 {
10195         p->rng_fault_state = true;
10196         return WERR_NOT_SUPPORTED;
10197 }
10198
10199 /****************************************************************
10200  _spoolss_61
10201 ****************************************************************/
10202
10203 WERROR _spoolss_61(pipes_struct *p,
10204                    struct spoolss_61 *r)
10205 {
10206         p->rng_fault_state = true;
10207         return WERR_NOT_SUPPORTED;
10208 }
10209
10210 /****************************************************************
10211  _spoolss_62
10212 ****************************************************************/
10213
10214 WERROR _spoolss_62(pipes_struct *p,
10215                    struct spoolss_62 *r)
10216 {
10217         p->rng_fault_state = true;
10218         return WERR_NOT_SUPPORTED;
10219 }
10220
10221 /****************************************************************
10222  _spoolss_63
10223 ****************************************************************/
10224
10225 WERROR _spoolss_63(pipes_struct *p,
10226                    struct spoolss_63 *r)
10227 {
10228         p->rng_fault_state = true;
10229         return WERR_NOT_SUPPORTED;
10230 }
10231
10232 /****************************************************************
10233  _spoolss_64
10234 ****************************************************************/
10235
10236 WERROR _spoolss_64(pipes_struct *p,
10237                    struct spoolss_64 *r)
10238 {
10239         p->rng_fault_state = true;
10240         return WERR_NOT_SUPPORTED;
10241 }
10242
10243 /****************************************************************
10244  _spoolss_65
10245 ****************************************************************/
10246
10247 WERROR _spoolss_65(pipes_struct *p,
10248                    struct spoolss_65 *r)
10249 {
10250         p->rng_fault_state = true;
10251         return WERR_NOT_SUPPORTED;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_GetCorePrinterDrivers
10256 ****************************************************************/
10257
10258 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10259                                       struct spoolss_GetCorePrinterDrivers *r)
10260 {
10261         p->rng_fault_state = true;
10262         return WERR_NOT_SUPPORTED;
10263 }
10264
10265 /****************************************************************
10266  _spoolss_67
10267 ****************************************************************/
10268
10269 WERROR _spoolss_67(pipes_struct *p,
10270                    struct spoolss_67 *r)
10271 {
10272         p->rng_fault_state = true;
10273         return WERR_NOT_SUPPORTED;
10274 }
10275
10276 /****************************************************************
10277  _spoolss_GetPrinterDriverPackagePath
10278 ****************************************************************/
10279
10280 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10281                                             struct spoolss_GetPrinterDriverPackagePath *r)
10282 {
10283         p->rng_fault_state = true;
10284         return WERR_NOT_SUPPORTED;
10285 }
10286
10287 /****************************************************************
10288  _spoolss_69
10289 ****************************************************************/
10290
10291 WERROR _spoolss_69(pipes_struct *p,
10292                    struct spoolss_69 *r)
10293 {
10294         p->rng_fault_state = true;
10295         return WERR_NOT_SUPPORTED;
10296 }
10297
10298 /****************************************************************
10299  _spoolss_6a
10300 ****************************************************************/
10301
10302 WERROR _spoolss_6a(pipes_struct *p,
10303                    struct spoolss_6a *r)
10304 {
10305         p->rng_fault_state = true;
10306         return WERR_NOT_SUPPORTED;
10307 }
10308
10309 /****************************************************************
10310  _spoolss_6b
10311 ****************************************************************/
10312
10313 WERROR _spoolss_6b(pipes_struct *p,
10314                    struct spoolss_6b *r)
10315 {
10316         p->rng_fault_state = true;
10317         return WERR_NOT_SUPPORTED;
10318 }
10319
10320 /****************************************************************
10321  _spoolss_6c
10322 ****************************************************************/
10323
10324 WERROR _spoolss_6c(pipes_struct *p,
10325                    struct spoolss_6c *r)
10326 {
10327         p->rng_fault_state = true;
10328         return WERR_NOT_SUPPORTED;
10329 }
10330
10331 /****************************************************************
10332  _spoolss_6d
10333 ****************************************************************/
10334
10335 WERROR _spoolss_6d(pipes_struct *p,
10336                    struct spoolss_6d *r)
10337 {
10338         p->rng_fault_state = true;
10339         return WERR_NOT_SUPPORTED;
10340 }