s3-spoolss: fix enumprinter key client and server.
[abartlet/samba.git/.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35         ((info)?ndr_size_##fn(info, level, ic, 0):0)
36
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
39
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
42
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44
45
46 extern userdom_struct current_user_info;
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_RPC_SRV
50
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
53 #endif
54
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32_t counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected == true) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected = false;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231                                                 struct policy_handle *hnd)
232 {
233         Printer_entry *find_printer = NULL;
234
235         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
237                 return NULL;
238         }
239
240         return find_printer;
241 }
242
243 /****************************************************************************
244  Close printer index by handle.
245 ****************************************************************************/
246
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
248 {
249         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250
251         if (!Printer) {
252                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
253                         OUR_HANDLE(hnd)));
254                 return false;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return true;
260 }
261
262 /****************************************************************************
263  Delete a printer given a handle.
264 ****************************************************************************/
265
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
267 {
268         char *cmd = lp_deleteprinter_cmd();
269         char *command = NULL;
270         int ret;
271         SE_PRIV se_printop = SE_PRINT_OPERATOR;
272         bool is_print_op = false;
273
274         /* can't fail if we don't try */
275
276         if ( !*cmd )
277                 return WERR_OK;
278
279         command = talloc_asprintf(ctx,
280                         "%s \"%s\"",
281                         cmd, sharename);
282         if (!command) {
283                 return WERR_NOMEM;
284         }
285         if ( token )
286                 is_print_op = user_has_privileges( token, &se_printop );
287
288         DEBUG(10,("Running [%s]\n", command));
289
290         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
291
292         if ( is_print_op )
293                 become_root();
294
295         if ( (ret = smbrun(command, NULL)) == 0 ) {
296                 /* Tell everyone we updated smb.conf. */
297                 message_send_all(smbd_messaging_context(),
298                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299         }
300
301         if ( is_print_op )
302                 unbecome_root();
303
304         /********** END SePrintOperatorPrivlege BLOCK **********/
305
306         DEBUGADD(10,("returned [%d]\n", ret));
307
308         TALLOC_FREE(command);
309
310         if (ret != 0)
311                 return WERR_BADFID; /* What to return here? */
312
313         /* go ahead and re-read the services immediately */
314         become_root();
315         reload_services(false);
316         unbecome_root();
317
318         if ( lp_servicenumber( sharename )  < 0 )
319                 return WERR_ACCESS_DENIED;
320
321         return WERR_OK;
322 }
323
324 /****************************************************************************
325  Delete a printer given a handle.
326 ****************************************************************************/
327
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
329 {
330         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331
332         if (!Printer) {
333                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
334                         OUR_HANDLE(hnd)));
335                 return WERR_BADFID;
336         }
337
338         /*
339          * It turns out that Windows allows delete printer on a handle
340          * opened by an admin user, then used on a pipe handle created
341          * by an anonymous user..... but they're working on security.... riiight !
342          * JRA.
343          */
344
345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347                 return WERR_ACCESS_DENIED;
348         }
349
350         /* this does not need a become root since the access check has been
351            done on the handle already */
352
353         if (del_a_printer( Printer->sharename ) != 0) {
354                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
355                 return WERR_BADFID;
356         }
357
358         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359                                    Printer->sharename );
360 }
361
362 /****************************************************************************
363  Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
365
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367                              int *number, struct share_params **params)
368 {
369         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370
371         if (!Printer) {
372                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
373                         OUR_HANDLE(hnd)));
374                 return false;
375         }
376
377         switch (Printer->printer_type) {
378                 case SPLHND_PRINTER:
379                         DEBUG(4,("short name:%s\n", Printer->sharename));
380                         *number = print_queue_snum(Printer->sharename);
381                         return (*number != -1);
382                 case SPLHND_SERVER:
383                         return false;
384                 default:
385                         return false;
386         }
387 }
388
389 /****************************************************************************
390  Set printer handle type.
391  Check if it's \\server or \\server\printer
392 ****************************************************************************/
393
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
395 {
396         DEBUG(3,("Setting printer type=%s\n", handlename));
397
398         if ( strlen(handlename) < 3 ) {
399                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
400                 return false;
401         }
402
403         /* it's a print server */
404         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405                 DEBUGADD(4,("Printer is a print server\n"));
406                 Printer->printer_type = SPLHND_SERVER;
407         }
408         /* it's a printer (set_printer_hnd_name() will handle port monitors */
409         else {
410                 DEBUGADD(4,("Printer is a printer\n"));
411                 Printer->printer_type = SPLHND_PRINTER;
412         }
413
414         return true;
415 }
416
417 /****************************************************************************
418  Set printer handle name..  Accept names like \\server, \\server\printer,
419  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
420  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421  XcvDataPort() interface.
422 ****************************************************************************/
423
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 {
426         int snum;
427         int n_services=lp_numservices();
428         char *aprinter, *printername;
429         const char *servername;
430         fstring sname;
431         bool found = false;
432         NT_PRINTER_INFO_LEVEL *printer = NULL;
433         WERROR result;
434
435         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436                 (unsigned long)strlen(handlename)));
437
438         aprinter = CONST_DISCARD(char *, handlename);
439         if ( *handlename == '\\' ) {
440                 servername = canon_servername(handlename);
441                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
442                         *aprinter = '\0';
443                         aprinter++;
444                 }
445         } else {
446                 servername = global_myname();
447         }
448
449         /* save the servername to fill in replies on this handle */
450
451         if ( !is_myname_or_ipaddr( servername ) )
452                 return false;
453
454         fstrcpy( Printer->servername, servername );
455
456         if ( Printer->printer_type == SPLHND_SERVER )
457                 return true;
458
459         if ( Printer->printer_type != SPLHND_PRINTER )
460                 return false;
461
462         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
463
464         /* check for the Port Monitor Interface */
465
466         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467                 Printer->printer_type = SPLHND_PORTMON_TCP;
468                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469                 found = true;
470         }
471         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474                 found = true;
475         }
476
477         /* Search all sharenames first as this is easier than pulling
478            the printer_info_2 off of disk. Don't use find_service() since
479            that calls out to map_username() */
480
481         /* do another loop to look for printernames */
482
483         for (snum=0; !found && snum<n_services; snum++) {
484
485                 /* no point going on if this is not a printer */
486
487                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488                         continue;
489
490                 fstrcpy(sname, lp_servicename(snum));
491                 if ( strequal( aprinter, sname ) ) {
492                         found = true;
493                         break;
494                 }
495
496                 /* no point looking up the printer object if
497                    we aren't allowing printername != sharename */
498
499                 if ( lp_force_printername(snum) )
500                         continue;
501
502                 fstrcpy(sname, lp_servicename(snum));
503
504                 printer = NULL;
505
506                 /* This call doesn't fill in the location or comment from
507                  * a CUPS server for efficiency with large numbers of printers.
508                  * JRA.
509                  */
510
511                 result = get_a_printer_search( NULL, &printer, 2, sname );
512                 if ( !W_ERROR_IS_OK(result) ) {
513                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514                                 sname, win_errstr(result)));
515                         continue;
516                 }
517
518                 /* printername is always returned as \\server\printername */
519                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521                                 printer->info_2->printername));
522                         free_a_printer( &printer, 2);
523                         continue;
524                 }
525
526                 printername++;
527
528                 if ( strequal(printername, aprinter) ) {
529                         free_a_printer( &printer, 2);
530                         found = true;
531                         break;
532                 }
533
534                 DEBUGADD(10, ("printername: %s\n", printername));
535
536                 free_a_printer( &printer, 2);
537         }
538
539         free_a_printer( &printer, 2);
540
541         if ( !found ) {
542                 DEBUGADD(4,("Printer not found\n"));
543                 return false;
544         }
545
546         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
547
548         fstrcpy(Printer->sharename, sname);
549
550         return true;
551 }
552
553 /****************************************************************************
554  Find first available printer slot. creates a printer handle for you.
555  ****************************************************************************/
556
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558                              const char *name, uint32_t access_granted)
559 {
560         Printer_entry *new_printer;
561
562         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
563
564         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565         if (new_printer == NULL) {
566                 return false;
567         }
568         talloc_set_destructor(new_printer, printer_entry_destructor);
569
570         if (!create_policy_hnd(p, hnd, new_printer)) {
571                 TALLOC_FREE(new_printer);
572                 return false;
573         }
574
575         /* Add to the internal list. */
576         DLIST_ADD(printers_list, new_printer);
577
578         new_printer->notify.option=NULL;
579
580         if (!set_printer_hnd_printertype(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return false;
583         }
584
585         if (!set_printer_hnd_name(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         new_printer->access_granted = access_granted;
591
592         DEBUG(5, ("%d printer handles active\n",
593                   (int)num_pipe_handles(p->pipe_handles)));
594
595         return true;
596 }
597
598 /***************************************************************************
599  check to see if the client motify handle is monitoring the notification
600  given by (notify_type, notify_field).
601  **************************************************************************/
602
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604                                       uint16_t notify_field)
605 {
606         return true;
607 }
608
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610                                 uint16_t notify_field)
611 {
612         struct spoolss_NotifyOption *option = p->notify.option;
613         uint32_t i, j;
614
615         /*
616          * Flags should always be zero when the change notify
617          * is registered by the client's spooler.  A user Win32 app
618          * might use the flags though instead of the NOTIFY_OPTION_INFO
619          * --jerry
620          */
621
622         if (!option) {
623                 return false;
624         }
625
626         if (p->notify.flags)
627                 return is_monitoring_event_flags(
628                         p->notify.flags, notify_type, notify_field);
629
630         for (i = 0; i < option->count; i++) {
631
632                 /* Check match for notify_type */
633
634                 if (option->types[i].type != notify_type)
635                         continue;
636
637                 /* Check match for field */
638
639                 for (j = 0; j < option->types[i].count; j++) {
640                         if (option->types[i].fields[j].field == notify_field) {
641                                 return true;
642                         }
643                 }
644         }
645
646         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647                    p->servername, p->sharename, notify_type, notify_field));
648
649         return false;
650 }
651
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653         _data->data.integer[0] = _integer; \
654         _data->data.integer[1] = 0;
655
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659         if (!_data->data.string.string) {\
660                 _data->data.string.size = 0; \
661         } \
662         _data->data.string.size = strlen_m_term(_p) * 2;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665         _data->data.devmode.devmode = _devmode;
666
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669         if (!_data->data.sd.sd) { \
670                 _data->data.sd.sd_size = 0; \
671         } \
672         _data->data.sd.sd_size = _size;
673
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
675                                    struct tm *t,
676                                    const char **pp,
677                                    uint32_t *plen)
678 {
679         struct spoolss_Time st;
680         uint32_t len = 16;
681         char *p;
682
683         if (!init_systemtime(&st, t)) {
684                 return;
685         }
686
687         p = talloc_array(mem_ctx, char, len);
688         if (!p) {
689                 return;
690         }
691
692         /*
693          * Systemtime must be linearized as a set of UINT16's.
694          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695          */
696
697         SSVAL(p, 0, st.year);
698         SSVAL(p, 2, st.month);
699         SSVAL(p, 4, st.day_of_week);
700         SSVAL(p, 6, st.day);
701         SSVAL(p, 8, st.hour);
702         SSVAL(p, 10, st.minute);
703         SSVAL(p, 12, st.second);
704         SSVAL(p, 14, st.millisecond);
705
706         *pp = p;
707         *plen = len;
708 }
709
710 /* Convert a notification message to a struct spoolss_Notify */
711
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713                              struct spoolss_Notify *data,
714                              TALLOC_CTX *mem_ctx)
715 {
716         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 }
718
719 static void notify_string(struct spoolss_notify_msg *msg,
720                           struct spoolss_Notify *data,
721                           TALLOC_CTX *mem_ctx)
722 {
723         /* The length of the message includes the trailing \0 */
724
725         data->data.string.size = msg->len * 2;
726         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727         if (!data->data.string.string) {
728                 data->data.string.size = 0;
729                 return;
730         }
731 }
732
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734                                struct spoolss_Notify *data,
735                                TALLOC_CTX *mem_ctx)
736 {
737         data->data.string.string = NULL;
738         data->data.string.size = 0;
739
740         if (msg->len != sizeof(time_t)) {
741                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
742                           msg->len));
743                 return;
744         }
745
746         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747                                &data->data.string.string,
748                                &data->data.string.size);
749 }
750
751 struct notify2_message_table {
752         const char *name;
753         void (*fn)(struct spoolss_notify_msg *msg,
754                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 };
756
757 static struct notify2_message_table printer_notify_table[] = {
758         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 };
778
779 static struct notify2_message_table job_notify_table[] = {
780         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 };
805
806
807 /***********************************************************************
808  Allocate talloc context for container object
809  **********************************************************************/
810
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 {
813         if ( !ctr )
814                 return;
815
816         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817
818         return;
819 }
820
821 /***********************************************************************
822  release all allocated memory and zero out structure
823  **********************************************************************/
824
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 {
827         if ( !ctr )
828                 return;
829
830         if ( ctr->ctx )
831                 talloc_destroy(ctr->ctx);
832
833         ZERO_STRUCTP(ctr);
834
835         return;
836 }
837
838 /***********************************************************************
839  **********************************************************************/
840
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 {
843         if ( !ctr )
844                 return NULL;
845
846         return ctr->ctx;
847 }
848
849 /***********************************************************************
850  **********************************************************************/
851
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
853 {
854         if ( !ctr || !ctr->msg_groups )
855                 return NULL;
856
857         if ( idx >= ctr->num_groups )
858                 return NULL;
859
860         return &ctr->msg_groups[idx];
861
862 }
863
864 /***********************************************************************
865  How many groups of change messages do we have ?
866  **********************************************************************/
867
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 {
870         if ( !ctr )
871                 return 0;
872
873         return ctr->num_groups;
874 }
875
876 /***********************************************************************
877  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878  **********************************************************************/
879
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 {
882         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
883         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
884         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
885         int                             i, new_slot;
886
887         if ( !ctr || !msg )
888                 return 0;
889
890         /* loop over all groups looking for a matching printer name */
891
892         for ( i=0; i<ctr->num_groups; i++ ) {
893                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894                         break;
895         }
896
897         /* add a new group? */
898
899         if ( i == ctr->num_groups ) {
900                 ctr->num_groups++;
901
902                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904                         return 0;
905                 }
906                 ctr->msg_groups = groups;
907
908                 /* clear the new entry and set the printer name */
909
910                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912         }
913
914         /* add the change messages; 'i' is the correct index now regardless */
915
916         msg_grp = &ctr->msg_groups[i];
917
918         msg_grp->num_msgs++;
919
920         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922                 return 0;
923         }
924         msg_grp->msgs = msg_list;
925
926         new_slot = msg_grp->num_msgs-1;
927         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928
929         /* need to allocate own copy of data */
930
931         if ( msg->len != 0 )
932                 msg_grp->msgs[new_slot].notify.data = (char *)
933                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934
935         return ctr->num_groups;
936 }
937
938 /***********************************************************************
939  Send a change notication message on all handles which have a call
940  back registered
941  **********************************************************************/
942
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 {
945         Printer_entry            *p;
946         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
947         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948         SPOOLSS_NOTIFY_MSG       *messages;
949         int                      sending_msg_count;
950
951         if ( !msg_group ) {
952                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953                 return;
954         }
955
956         messages = msg_group->msgs;
957
958         if ( !messages ) {
959                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960                 return;
961         }
962
963         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964
965         /* loop over all printers */
966
967         for (p = printers_list; p; p = p->next) {
968                 struct spoolss_Notify *notifies;
969                 uint32_t count = 0;
970                 uint32_t id;
971                 int     i;
972
973                 /* Is there notification on this handle? */
974
975                 if ( !p->notify.client_connected )
976                         continue;
977
978                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979
980                 /* For this printer?  Print servers always receive
981                    notifications. */
982
983                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
984                     ( !strequal(msg_group->printername, p->sharename) ) )
985                         continue;
986
987                 DEBUG(10,("Our printer\n"));
988
989                 /* allocate the max entries possible */
990
991                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
992                 if (!notifies) {
993                         return;
994                 }
995
996                 /* build the array of change notifications */
997
998                 sending_msg_count = 0;
999
1000                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1002
1003                         /* Are we monitoring this event? */
1004
1005                         if (!is_monitoring_event(p, msg->type, msg->field))
1006                                 continue;
1007
1008                         sending_msg_count++;
1009
1010
1011                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012                                 msg->type, msg->field, p->sharename));
1013
1014                         /*
1015                          * if the is a printer notification handle and not a job notification
1016                          * type, then set the id to 0.  Other wise just use what was specified
1017                          * in the message.
1018                          *
1019                          * When registering change notification on a print server handle
1020                          * we always need to send back the id (snum) matching the printer
1021                          * for which the change took place.  For change notify registered
1022                          * on a printer handle, this does not matter and the id should be 0.
1023                          *
1024                          * --jerry
1025                          */
1026
1027                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028                                 id = 0;
1029                         else
1030                                 id = msg->id;
1031
1032
1033                         /* Convert unix jobid to smb jobid */
1034
1035                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036                                 id = sysjob_to_jobid(msg->id);
1037
1038                                 if (id == -1) {
1039                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040                                         goto done;
1041                                 }
1042                         }
1043
1044                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1045
1046                         switch(msg->type) {
1047                         case PRINTER_NOTIFY_TYPE:
1048                                 if ( printer_notify_table[msg->field].fn )
1049                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1050                                 break;
1051
1052                         case JOB_NOTIFY_TYPE:
1053                                 if ( job_notify_table[msg->field].fn )
1054                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1055                                 break;
1056
1057                         default:
1058                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059                                 goto done;
1060                         }
1061
1062                         count++;
1063                 }
1064
1065                 if ( sending_msg_count ) {
1066                         NTSTATUS status;
1067                         WERROR werr;
1068                         union spoolss_ReplyPrinterInfo info;
1069                         struct spoolss_NotifyInfo info0;
1070                         uint32_t reply_result;
1071
1072                         info0.version   = 0x2;
1073                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074                         info0.count     = count;
1075                         info0.notifies  = notifies;
1076
1077                         info.info0 = &info0;
1078
1079                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080                                                                      &p->notify.client_hnd,
1081                                                                      p->notify.change, /* color */
1082                                                                      p->notify.flags,
1083                                                                      &reply_result,
1084                                                                      0, /* reply_type, must be 0 */
1085                                                                      info,
1086                                                                      &werr);
1087                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089                                         notify_cli_pipe->srv_name_slash,
1090                                         win_errstr(werr)));
1091                         }
1092                         switch (reply_result) {
1093                                 case 0:
1094                                         break;
1095                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1096                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1098                                         break;
1099                                 default:
1100                                         break;
1101                         }
1102                 }
1103         }
1104
1105 done:
1106         DEBUG(8,("send_notify2_changes: Exit...\n"));
1107         return;
1108 }
1109
1110 /***********************************************************************
1111  **********************************************************************/
1112
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 {
1115
1116         uint32_t tv_sec, tv_usec;
1117         size_t offset = 0;
1118
1119         /* Unpack message */
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122                              msg->printer);
1123
1124         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1125                                 &tv_sec, &tv_usec,
1126                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127
1128         if (msg->len == 0)
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130                            &msg->notify.value[0], &msg->notify.value[1]);
1131         else
1132                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133                            &msg->len, &msg->notify.data);
1134
1135         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1137
1138         tv->tv_sec = tv_sec;
1139         tv->tv_usec = tv_usec;
1140
1141         if (msg->len == 0)
1142                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143                           msg->notify.value[1]));
1144         else
1145                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1146
1147         return true;
1148 }
1149
1150 /********************************************************************
1151  Receive a notify2 message list
1152  ********************************************************************/
1153
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1155                                          void *private_data,
1156                                          uint32_t msg_type,
1157                                          struct server_id server_id,
1158                                          DATA_BLOB *data)
1159 {
1160         size_t                  msg_count, i;
1161         char                    *buf = (char *)data->data;
1162         char                    *msg_ptr;
1163         size_t                  msg_len;
1164         SPOOLSS_NOTIFY_MSG      notify;
1165         SPOOLSS_NOTIFY_MSG_CTR  messages;
1166         int                     num_groups;
1167
1168         if (data->length < 4) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170                 return;
1171         }
1172
1173         msg_count = IVAL(buf, 0);
1174         msg_ptr = buf + 4;
1175
1176         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1177
1178         if (msg_count == 0) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180                 return;
1181         }
1182
1183         /* initialize the container */
1184
1185         ZERO_STRUCT( messages );
1186         notify_msg_ctr_init( &messages );
1187
1188         /*
1189          * build message groups for each printer identified
1190          * in a change_notify msg.  Remember that a PCN message
1191          * includes the handle returned for the srv_spoolss_replyopenprinter()
1192          * call.  Therefore messages are grouped according to printer handle.
1193          */
1194
1195         for ( i=0; i<msg_count; i++ ) {
1196                 struct timeval msg_tv;
1197
1198                 if (msg_ptr + 4 - buf > data->length) {
1199                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200                         return;
1201                 }
1202
1203                 msg_len = IVAL(msg_ptr,0);
1204                 msg_ptr += 4;
1205
1206                 if (msg_ptr + msg_len - buf > data->length) {
1207                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208                         return;
1209                 }
1210
1211                 /* unpack messages */
1212
1213                 ZERO_STRUCT( notify );
1214                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215                 msg_ptr += msg_len;
1216
1217                 /* add to correct list in container */
1218
1219                 notify_msg_ctr_addmsg( &messages, &notify );
1220
1221                 /* free memory that might have been allocated by notify2_unpack_msg() */
1222
1223                 if ( notify.len != 0 )
1224                         SAFE_FREE( notify.notify.data );
1225         }
1226
1227         /* process each group of messages */
1228
1229         num_groups = notify_msg_ctr_numgroups( &messages );
1230         for ( i=0; i<num_groups; i++ )
1231                 send_notify2_changes( &messages, i );
1232
1233
1234         /* cleanup */
1235
1236         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237                 (uint32_t)msg_count ));
1238
1239         notify_msg_ctr_destroy( &messages );
1240
1241         return;
1242 }
1243
1244 /********************************************************************
1245  Send a message to ourself about new driver being installed
1246  so we can upgrade the information for each printer bound to this
1247  driver
1248  ********************************************************************/
1249
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1251 {
1252         int len = strlen(drivername);
1253
1254         if (!len)
1255                 return false;
1256
1257         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258                 drivername));
1259
1260         messaging_send_buf(smbd_messaging_context(), procid_self(),
1261                            MSG_PRINTER_DRVUPGRADE,
1262                            (uint8_t *)drivername, len+1);
1263
1264         return true;
1265 }
1266
1267 /**********************************************************************
1268  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269  over all printers, upgrading ones as necessary
1270  **********************************************************************/
1271
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1273                             void *private_data,
1274                             uint32_t msg_type,
1275                             struct server_id server_id,
1276                             DATA_BLOB *data)
1277 {
1278         fstring drivername;
1279         int snum;
1280         int n_services = lp_numservices();
1281         size_t len;
1282
1283         len = MIN(data->length,sizeof(drivername)-1);
1284         strncpy(drivername, (const char *)data->data, len);
1285
1286         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287
1288         /* Iterate the printer list */
1289
1290         for (snum=0; snum<n_services; snum++)
1291         {
1292                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293                 {
1294                         WERROR result;
1295                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1296
1297                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298                         if (!W_ERROR_IS_OK(result))
1299                                 continue;
1300
1301                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302                         {
1303                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304
1305                                 /* all we care about currently is the change_id */
1306
1307                                 result = mod_a_printer(printer, 2);
1308                                 if (!W_ERROR_IS_OK(result)) {
1309                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310                                                 win_errstr(result)));
1311                                 }
1312                         }
1313
1314                         free_a_printer(&printer, 2);
1315                 }
1316         }
1317
1318         /* all done */
1319 }
1320
1321 /********************************************************************
1322  Update the cache for all printq's with a registered client
1323  connection
1324  ********************************************************************/
1325
1326 void update_monitored_printq_cache( void )
1327 {
1328         Printer_entry *printer = printers_list;
1329         int snum;
1330
1331         /* loop through all printers and update the cache where
1332            client_connected == true */
1333         while ( printer )
1334         {
1335                 if ( (printer->printer_type == SPLHND_PRINTER)
1336                         && printer->notify.client_connected )
1337                 {
1338                         snum = print_queue_snum(printer->sharename);
1339                         print_queue_status( snum, NULL, NULL );
1340                 }
1341
1342                 printer = printer->next;
1343         }
1344
1345         return;
1346 }
1347 /********************************************************************
1348  Send a message to ourself about new driver being installed
1349  so we can upgrade the information for each printer bound to this
1350  driver
1351  ********************************************************************/
1352
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 {
1355         int len = strlen(drivername);
1356
1357         if (!len)
1358                 return false;
1359
1360         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361                 drivername));
1362
1363         messaging_send_buf(smbd_messaging_context(), procid_self(),
1364                            MSG_PRINTERDATA_INIT_RESET,
1365                            (uint8_t *)drivername, len+1);
1366
1367         return true;
1368 }
1369
1370 /**********************************************************************
1371  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372  over all printers, resetting printer data as neessary
1373  **********************************************************************/
1374
1375 void reset_all_printerdata(struct messaging_context *msg,
1376                            void *private_data,
1377                            uint32_t msg_type,
1378                            struct server_id server_id,
1379                            DATA_BLOB *data)
1380 {
1381         fstring drivername;
1382         int snum;
1383         int n_services = lp_numservices();
1384         size_t len;
1385
1386         len = MIN( data->length, sizeof(drivername)-1 );
1387         strncpy( drivername, (const char *)data->data, len );
1388
1389         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390
1391         /* Iterate the printer list */
1392
1393         for ( snum=0; snum<n_services; snum++ )
1394         {
1395                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396                 {
1397                         WERROR result;
1398                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1399
1400                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401                         if ( !W_ERROR_IS_OK(result) )
1402                                 continue;
1403
1404                         /*
1405                          * if the printer is bound to the driver,
1406                          * then reset to the new driver initdata
1407                          */
1408
1409                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410                         {
1411                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412
1413                                 if ( !set_driver_init(printer, 2) ) {
1414                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415                                                 printer->info_2->printername, printer->info_2->drivername));
1416                                 }
1417
1418                                 result = mod_a_printer( printer, 2 );
1419                                 if ( !W_ERROR_IS_OK(result) ) {
1420                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1421                                                 get_dos_error_msg(result)));
1422                                 }
1423                         }
1424
1425                         free_a_printer( &printer, 2 );
1426                 }
1427         }
1428
1429         /* all done */
1430
1431         return;
1432 }
1433
1434 /****************************************************************
1435  _spoolss_OpenPrinter
1436 ****************************************************************/
1437
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439                             struct spoolss_OpenPrinter *r)
1440 {
1441         struct spoolss_OpenPrinterEx e;
1442         WERROR werr;
1443
1444         ZERO_STRUCT(e.in.userlevel);
1445
1446         e.in.printername        = r->in.printername;
1447         e.in.datatype           = r->in.datatype;
1448         e.in.devmode_ctr        = r->in.devmode_ctr;
1449         e.in.access_mask        = r->in.access_mask;
1450         e.in.level              = 0;
1451
1452         e.out.handle            = r->out.handle;
1453
1454         werr = _spoolss_OpenPrinterEx(p, &e);
1455
1456         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457                 /* OpenPrinterEx returns this for a bad
1458                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1459                  * instead.
1460                  */
1461                 werr = WERR_INVALID_PRINTER_NAME;
1462         }
1463
1464         return werr;
1465 }
1466
1467 /********************************************************************
1468  ********************************************************************/
1469
1470 bool convert_devicemode(const char *printername,
1471                         const struct spoolss_DeviceMode *devmode,
1472                         NT_DEVICEMODE **pp_nt_devmode)
1473 {
1474         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475
1476         /*
1477          * Ensure nt_devmode is a valid pointer
1478          * as we will be overwriting it.
1479          */
1480
1481         if (nt_devmode == NULL) {
1482                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484                         return false;
1485         }
1486
1487         fstrcpy(nt_devmode->devicename, devmode->devicename);
1488         fstrcpy(nt_devmode->formname, devmode->formname);
1489
1490         nt_devmode->devicename[31] = '\0';
1491         nt_devmode->formname[31] = '\0';
1492
1493         nt_devmode->specversion         = devmode->specversion;
1494         nt_devmode->driverversion       = devmode->driverversion;
1495         nt_devmode->size                = devmode->size;
1496         nt_devmode->fields              = devmode->fields;
1497         nt_devmode->orientation         = devmode->orientation;
1498         nt_devmode->papersize           = devmode->papersize;
1499         nt_devmode->paperlength         = devmode->paperlength;
1500         nt_devmode->paperwidth          = devmode->paperwidth;
1501         nt_devmode->scale               = devmode->scale;
1502         nt_devmode->copies              = devmode->copies;
1503         nt_devmode->defaultsource       = devmode->defaultsource;
1504         nt_devmode->printquality        = devmode->printquality;
1505         nt_devmode->color               = devmode->color;
1506         nt_devmode->duplex              = devmode->duplex;
1507         nt_devmode->yresolution         = devmode->yresolution;
1508         nt_devmode->ttoption            = devmode->ttoption;
1509         nt_devmode->collate             = devmode->collate;
1510
1511         nt_devmode->logpixels           = devmode->logpixels;
1512         nt_devmode->bitsperpel          = devmode->bitsperpel;
1513         nt_devmode->pelswidth           = devmode->pelswidth;
1514         nt_devmode->pelsheight          = devmode->pelsheight;
1515         nt_devmode->displayflags        = devmode->displayflags;
1516         nt_devmode->displayfrequency    = devmode->displayfrequency;
1517         nt_devmode->icmmethod           = devmode->icmmethod;
1518         nt_devmode->icmintent           = devmode->icmintent;
1519         nt_devmode->mediatype           = devmode->mediatype;
1520         nt_devmode->dithertype          = devmode->dithertype;
1521         nt_devmode->reserved1           = devmode->reserved1;
1522         nt_devmode->reserved2           = devmode->reserved2;
1523         nt_devmode->panningwidth        = devmode->panningwidth;
1524         nt_devmode->panningheight       = devmode->panningheight;
1525
1526         /*
1527          * Only change private and driverextra if the incoming devmode
1528          * has a new one. JRA.
1529          */
1530
1531         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532                 SAFE_FREE(nt_devmode->nt_dev_private);
1533                 nt_devmode->driverextra = devmode->__driverextra_length;
1534                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1535                         return false;
1536                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1537         }
1538
1539         *pp_nt_devmode = nt_devmode;
1540
1541         return true;
1542 }
1543
1544 /****************************************************************
1545  _spoolss_OpenPrinterEx
1546 ****************************************************************/
1547
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549                               struct spoolss_OpenPrinterEx *r)
1550 {
1551         int snum;
1552         Printer_entry *Printer=NULL;
1553
1554         if (!r->in.printername) {
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         /* some sanity check because you can open a printer or a print server */
1559         /* aka: \\server\printer or \\server */
1560
1561         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1562
1563         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564                 ZERO_STRUCTP(r->out.handle);
1565                 return WERR_INVALID_PARAM;
1566         }
1567
1568         Printer = find_printer_index_by_hnd(p, r->out.handle);
1569         if ( !Printer ) {
1570                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1571                         "handle we created for printer %s\n", r->in.printername));
1572                 close_printer_handle(p, r->out.handle);
1573                 ZERO_STRUCTP(r->out.handle);
1574                 return WERR_INVALID_PARAM;
1575         }
1576
1577         /*
1578          * First case: the user is opening the print server:
1579          *
1580          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1582          *
1583          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585          * or if the user is listed in the smb.conf printer admin parameter.
1586          *
1587          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588          * client view printer folder, but does not show the MSAPW.
1589          *
1590          * Note: this test needs code to check access rights here too. Jeremy
1591          * could you look at this?
1592          *
1593          * Second case: the user is opening a printer:
1594          * NT doesn't let us connect to a printer if the connecting user
1595          * doesn't have print permission.
1596          *
1597          * Third case: user is opening a Port Monitor
1598          * access checks same as opening a handle to the print server.
1599          */
1600
1601         switch (Printer->printer_type )
1602         {
1603         case SPLHND_SERVER:
1604         case SPLHND_PORTMON_TCP:
1605         case SPLHND_PORTMON_LOCAL:
1606                 /* Printserver handles use global struct... */
1607
1608                 snum = -1;
1609
1610                 /* Map standard access rights to object specific access rights */
1611
1612                 se_map_standard(&r->in.access_mask,
1613                                 &printserver_std_mapping);
1614
1615                 /* Deny any object specific bits that don't apply to print
1616                    servers (i.e printer and job specific bits) */
1617
1618                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1619
1620                 if (r->in.access_mask &
1621                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623                         close_printer_handle(p, r->out.handle);
1624                         ZERO_STRUCTP(r->out.handle);
1625                         return WERR_ACCESS_DENIED;
1626                 }
1627
1628                 /* Allow admin access */
1629
1630                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1631                 {
1632                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1633
1634                         if (!lp_ms_add_printer_wizard()) {
1635                                 close_printer_handle(p, r->out.handle);
1636                                 ZERO_STRUCTP(r->out.handle);
1637                                 return WERR_ACCESS_DENIED;
1638                         }
1639
1640                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641                            and not a printer admin, then fail */
1642
1643                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644                             !user_has_privileges(p->server_info->ptok,
1645                                                  &se_printop ) &&
1646                             !token_contains_name_in_list(
1647                                     uidtoname(p->server_info->utok.uid),
1648                                     NULL, NULL,
1649                                     p->server_info->ptok,
1650                                     lp_printer_admin(snum))) {
1651                                 close_printer_handle(p, r->out.handle);
1652                                 ZERO_STRUCTP(r->out.handle);
1653                                 return WERR_ACCESS_DENIED;
1654                         }
1655
1656                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657                 }
1658                 else
1659                 {
1660                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661                 }
1662
1663                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1665
1666                 /* We fall through to return WERR_OK */
1667                 break;
1668
1669         case SPLHND_PRINTER:
1670                 /* NT doesn't let us connect to a printer if the connecting user
1671                    doesn't have print permission.  */
1672
1673                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674                         close_printer_handle(p, r->out.handle);
1675                         ZERO_STRUCTP(r->out.handle);
1676                         return WERR_BADFID;
1677                 }
1678
1679                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681                 }
1682
1683                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1684
1685                 /* map an empty access mask to the minimum access mask */
1686                 if (r->in.access_mask == 0x0)
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688
1689                 /*
1690                  * If we are not serving the printer driver for this printer,
1691                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1692                  * will keep NT clients happy  --jerry
1693                  */
1694
1695                 if (lp_use_client_driver(snum)
1696                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1697                 {
1698                         r->in.access_mask = PRINTER_ACCESS_USE;
1699                 }
1700
1701                 /* check smb.conf parameters and the the sec_desc */
1702
1703                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708
1709                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710                                    p->server_info->ptok, snum) ||
1711                     !print_access_check(p->server_info, snum,
1712                                         r->in.access_mask)) {
1713                         DEBUG(3, ("access DENIED for printer open\n"));
1714                         close_printer_handle(p, r->out.handle);
1715                         ZERO_STRUCTP(r->out.handle);
1716                         return WERR_ACCESS_DENIED;
1717                 }
1718
1719                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721                         close_printer_handle(p, r->out.handle);
1722                         ZERO_STRUCTP(r->out.handle);
1723                         return WERR_ACCESS_DENIED;
1724                 }
1725
1726                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1728                 else
1729                         r->in.access_mask = PRINTER_ACCESS_USE;
1730
1731                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1733
1734                 break;
1735
1736         default:
1737                 /* sanity check to prevent programmer error */
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_BADFID;
1740         }
1741
1742         Printer->access_granted = r->in.access_mask;
1743
1744         /*
1745          * If the client sent a devmode in the OpenPrinter() call, then
1746          * save it here in case we get a job submission on this handle
1747          */
1748
1749          if ((Printer->printer_type != SPLHND_SERVER) &&
1750              r->in.devmode_ctr.devmode) {
1751                 convert_devicemode(Printer->sharename,
1752                                    r->in.devmode_ctr.devmode,
1753                                    &Printer->nt_devmode);
1754          }
1755
1756 #if 0   /* JERRY -- I'm doubtful this is really effective */
1757         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758            optimization in Windows 2000 clients  --jerry */
1759
1760         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761                 && (RA_WIN2K == get_remote_arch()) )
1762         {
1763                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764                 sys_usleep( 500000 );
1765         }
1766 #endif
1767
1768         return WERR_OK;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775                                               NT_PRINTER_INFO_LEVEL_2 *d)
1776 {
1777         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1778
1779         if (!r || !d) {
1780                 return false;
1781         }
1782
1783         d->attributes           = r->attributes;
1784         d->priority             = r->priority;
1785         d->default_priority     = r->defaultpriority;
1786         d->starttime            = r->starttime;
1787         d->untiltime            = r->untiltime;
1788         d->status               = r->status;
1789         d->cjobs                = r->cjobs;
1790
1791         fstrcpy(d->servername,  r->servername);
1792         fstrcpy(d->printername, r->printername);
1793         fstrcpy(d->sharename,   r->sharename);
1794         fstrcpy(d->portname,    r->portname);
1795         fstrcpy(d->drivername,  r->drivername);
1796         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797         fstrcpy(d->location,    r->location);
1798         fstrcpy(d->sepfile,     r->sepfile);
1799         fstrcpy(d->printprocessor, r->printprocessor);
1800         fstrcpy(d->datatype,    r->datatype);
1801         fstrcpy(d->parameters,  r->parameters);
1802
1803         return true;
1804 }
1805
1806 /****************************************************************************
1807 ****************************************************************************/
1808
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810                                  NT_PRINTER_INFO_LEVEL *printer)
1811 {
1812         bool ret;
1813
1814         switch (info_ctr->level) {
1815         case 2:
1816                 /* allocate memory if needed.  Messy because
1817                    convert_printer_info is used to update an existing
1818                    printer or build a new one */
1819
1820                 if (!printer->info_2) {
1821                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822                         if (!printer->info_2) {
1823                                 DEBUG(0,("convert_printer_info: "
1824                                         "talloc() failed!\n"));
1825                                 return false;
1826                         }
1827                 }
1828
1829                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1830                                                         printer->info_2);
1831                 printer->info_2->setuptime = time(NULL);
1832                 return ret;
1833         }
1834
1835         return false;
1836 }
1837
1838 /****************************************************************
1839  _spoolss_ClosePrinter
1840 ****************************************************************/
1841
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843                              struct spoolss_ClosePrinter *r)
1844 {
1845         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1846
1847         if (Printer && Printer->document_started) {
1848                 struct spoolss_EndDocPrinter e;
1849
1850                 e.in.handle = r->in.handle;
1851
1852                 _spoolss_EndDocPrinter(p, &e);
1853         }
1854
1855         if (!close_printer_handle(p, r->in.handle))
1856                 return WERR_BADFID;
1857
1858         /* clear the returned printer handle.  Observed behavior
1859            from Win2k server.  Don't think this really matters.
1860            Previous code just copied the value of the closed
1861            handle.    --jerry */
1862
1863         ZERO_STRUCTP(r->out.handle);
1864
1865         return WERR_OK;
1866 }
1867
1868 /****************************************************************
1869  _spoolss_DeletePrinter
1870 ****************************************************************/
1871
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873                               struct spoolss_DeletePrinter *r)
1874 {
1875         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1876         WERROR result;
1877
1878         if (Printer && Printer->document_started) {
1879                 struct spoolss_EndDocPrinter e;
1880
1881                 e.in.handle = r->in.handle;
1882
1883                 _spoolss_EndDocPrinter(p, &e);
1884         }
1885
1886         result = delete_printer_handle(p, r->in.handle);
1887
1888         update_c_setprinter(false);
1889
1890         return result;
1891 }
1892
1893 /*******************************************************************
1894  * static function to lookup the version id corresponding to an
1895  * long architecture string
1896  ******************************************************************/
1897
1898 static const struct print_architecture_table_node archi_table[]= {
1899
1900         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1901         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1902         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1903         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1904         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1905         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1906         {"Windows x64",          SPL_ARCH_X64,          3 },
1907         {NULL,                   "",            -1 }
1908 };
1909
1910 static int get_version_id(const char *arch)
1911 {
1912         int i;
1913
1914         for (i=0; archi_table[i].long_archi != NULL; i++)
1915         {
1916                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917                         return (archi_table[i].version);
1918         }
1919
1920         return -1;
1921 }
1922
1923 /****************************************************************
1924  _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1926
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928                                     struct spoolss_DeletePrinterDriver *r)
1929 {
1930
1931         struct spoolss_DriverInfo8 *info = NULL;
1932         struct spoolss_DriverInfo8 *info_win2k = NULL;
1933         int                             version;
1934         WERROR                          status;
1935         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1936         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1937
1938         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1939            and not a printer admin, then fail */
1940
1941         if ( (p->server_info->utok.uid != sec_initial_uid())
1942                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1943                 && !token_contains_name_in_list(
1944                         uidtoname(p->server_info->utok.uid), NULL,
1945                         NULL, p->server_info->ptok,
1946                         lp_printer_admin(-1)) )
1947         {
1948                 return WERR_ACCESS_DENIED;
1949         }
1950
1951         /* check that we have a valid driver name first */
1952
1953         if ((version = get_version_id(r->in.architecture)) == -1)
1954                 return WERR_INVALID_ENVIRONMENT;
1955
1956         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1957                                                 r->in.architecture,
1958                                                 version)))
1959         {
1960                 /* try for Win2k driver if "Windows NT x86" */
1961
1962                 if ( version == 2 ) {
1963                         version = 3;
1964                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1965                                                                 &info,
1966                                                                 r->in.driver,
1967                                                                 r->in.architecture,
1968                                                                 version))) {
1969                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970                                 goto done;
1971                         }
1972                 }
1973                 /* otherwise it was a failure */
1974                 else {
1975                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1976                         goto done;
1977                 }
1978
1979         }
1980
1981         if (printer_driver_in_use(info)) {
1982                 status = WERR_PRINTER_DRIVER_IN_USE;
1983                 goto done;
1984         }
1985
1986         if ( version == 2 )
1987         {
1988                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1989                                                        &info_win2k,
1990                                                        r->in.driver,
1991                                                        r->in.architecture, 3)))
1992                 {
1993                         /* if we get to here, we now have 2 driver info structures to remove */
1994                         /* remove the Win2k driver first*/
1995
1996                         status_win2k = delete_printer_driver(
1997                                 p, info_win2k, 3, false);
1998                         free_a_printer_driver(info_win2k);
1999
2000                         /* this should not have failed---if it did, report to client */
2001                         if ( !W_ERROR_IS_OK(status_win2k) )
2002                         {
2003                                 status = status_win2k;
2004                                 goto done;
2005                         }
2006                 }
2007         }
2008
2009         status = delete_printer_driver(p, info, version, false);
2010
2011         /* if at least one of the deletes succeeded return OK */
2012
2013         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2014                 status = WERR_OK;
2015
2016 done:
2017         free_a_printer_driver(info);
2018
2019         return status;
2020 }
2021
2022 /****************************************************************
2023  _spoolss_DeletePrinterDriverEx
2024 ****************************************************************/
2025
2026 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2027                                       struct spoolss_DeletePrinterDriverEx *r)
2028 {
2029         struct spoolss_DriverInfo8      *info = NULL;
2030         struct spoolss_DriverInfo8      *info_win2k = NULL;
2031         int                             version;
2032         bool                            delete_files;
2033         WERROR                          status;
2034         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2035         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2036
2037         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038            and not a printer admin, then fail */
2039
2040         if ( (p->server_info->utok.uid != sec_initial_uid())
2041                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2042                 && !token_contains_name_in_list(
2043                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2044                         p->server_info->ptok, lp_printer_admin(-1)) )
2045         {
2046                 return WERR_ACCESS_DENIED;
2047         }
2048
2049         /* check that we have a valid driver name first */
2050         if ((version = get_version_id(r->in.architecture)) == -1) {
2051                 /* this is what NT returns */
2052                 return WERR_INVALID_ENVIRONMENT;
2053         }
2054
2055         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2056                 version = r->in.version;
2057
2058         status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2059                                       r->in.architecture, version);
2060
2061         if ( !W_ERROR_IS_OK(status) )
2062         {
2063                 /*
2064                  * if the client asked for a specific version,
2065                  * or this is something other than Windows NT x86,
2066                  * then we've failed
2067                  */
2068
2069                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2070                         goto done;
2071
2072                 /* try for Win2k driver if "Windows NT x86" */
2073
2074                 version = 3;
2075                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2076                                                         r->in.architecture,
2077                                                         version))) {
2078                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2079                         goto done;
2080                 }
2081         }
2082
2083         if (printer_driver_in_use(info)) {
2084                 status = WERR_PRINTER_DRIVER_IN_USE;
2085                 goto done;
2086         }
2087
2088         /*
2089          * we have a couple of cases to consider.
2090          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2091          *     then the delete should fail if **any** files overlap with
2092          *     other drivers
2093          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094          *     non-overlapping files
2095          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096          *     is set, the do not delete any files
2097          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2098          */
2099
2100         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2101
2102         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2103
2104         if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2105                 /* no idea of the correct error here */
2106                 status = WERR_ACCESS_DENIED;
2107                 goto done;
2108         }
2109
2110
2111         /* also check for W32X86/3 if necessary; maybe we already have? */
2112
2113         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2114                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2115                                                        r->in.driver,
2116                                                        r->in.architecture, 3)))
2117                 {
2118
2119                         if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2120                                 /* no idea of the correct error here */
2121                                 free_a_printer_driver(info_win2k);
2122                                 status = WERR_ACCESS_DENIED;
2123                                 goto done;
2124                         }
2125
2126                         /* if we get to here, we now have 2 driver info structures to remove */
2127                         /* remove the Win2k driver first*/
2128
2129                         status_win2k = delete_printer_driver(
2130                                 p, info_win2k, 3, delete_files);
2131                         free_a_printer_driver(info_win2k);
2132
2133                         /* this should not have failed---if it did, report to client */
2134
2135                         if ( !W_ERROR_IS_OK(status_win2k) )
2136                                 goto done;
2137                 }
2138         }
2139
2140         status = delete_printer_driver(p, info, version, delete_files);
2141
2142         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2143                 status = WERR_OK;
2144 done:
2145         free_a_printer_driver(info);
2146
2147         return status;
2148 }
2149
2150
2151 /****************************************************************************
2152  Internal routine for removing printerdata
2153  ***************************************************************************/
2154
2155 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2156 {
2157         return delete_printer_data( printer->info_2, key, value );
2158 }
2159
2160 /****************************************************************************
2161  Internal routine for storing printerdata
2162  ***************************************************************************/
2163
2164 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2165                           const char *key, const char *value,
2166                           uint32_t type, uint8_t *data, int real_len)
2167 {
2168         /* the registry objects enforce uniqueness based on value name */
2169
2170         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2171 }
2172
2173 /********************************************************************
2174  GetPrinterData on a printer server Handle.
2175 ********************************************************************/
2176
2177 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2178                                             const char *value,
2179                                             enum winreg_Type *type,
2180                                             union spoolss_PrinterData *data)
2181 {
2182         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2183
2184         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2185                 *type = REG_DWORD;
2186                 data->value = 0x00;
2187                 return WERR_OK;
2188         }
2189
2190         if (!StrCaseCmp(value, "BeepEnabled")) {
2191                 *type = REG_DWORD;
2192                 data->value = 0x00;
2193                 return WERR_OK;
2194         }
2195
2196         if (!StrCaseCmp(value, "EventLog")) {
2197                 *type = REG_DWORD;
2198                 /* formally was 0x1b */
2199                 data->value = 0x00;
2200                 return WERR_OK;
2201         }
2202
2203         if (!StrCaseCmp(value, "NetPopup")) {
2204                 *type = REG_DWORD;
2205                 data->value = 0x00;
2206                 return WERR_OK;
2207         }
2208
2209         if (!StrCaseCmp(value, "MajorVersion")) {
2210                 *type = REG_DWORD;
2211
2212                 /* Windows NT 4.0 seems to not allow uploading of drivers
2213                    to a server that reports 0x3 as the MajorVersion.
2214                    need to investigate more how Win2k gets around this .
2215                    -- jerry */
2216
2217                 if (RA_WINNT == get_remote_arch()) {
2218                         data->value = 0x02;
2219                 } else {
2220                         data->value = 0x03;
2221                 }
2222
2223                 return WERR_OK;
2224         }
2225
2226         if (!StrCaseCmp(value, "MinorVersion")) {
2227                 *type = REG_DWORD;
2228                 data->value = 0x00;
2229                 return WERR_OK;
2230         }
2231
2232         /* REG_BINARY
2233          *  uint32_t size        = 0x114
2234          *  uint32_t major       = 5
2235          *  uint32_t minor       = [0|1]
2236          *  uint32_t build       = [2195|2600]
2237          *  extra unicode string = e.g. "Service Pack 3"
2238          */
2239         if (!StrCaseCmp(value, "OSVersion")) {
2240                 DATA_BLOB blob;
2241                 enum ndr_err_code ndr_err;
2242                 struct spoolss_OSVersion os;
2243
2244                 os.major                = 5;    /* Windows 2000 == 5.0 */
2245                 os.minor                = 0;
2246                 os.build                = 2195; /* build */
2247                 os.extra_string         = "";   /* leave extra string empty */
2248
2249                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2250                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2251                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2252                         return WERR_GENERAL_FAILURE;
2253                 }
2254
2255                 *type = REG_BINARY;
2256                 data->binary = blob;
2257
2258                 return WERR_OK;
2259         }
2260
2261
2262         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2263                 *type = REG_SZ;
2264
2265                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2266                 W_ERROR_HAVE_NO_MEMORY(data->string);
2267
2268                 return WERR_OK;
2269         }
2270
2271         if (!StrCaseCmp(value, "Architecture")) {
2272                 *type = REG_SZ;
2273
2274                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2275                 W_ERROR_HAVE_NO_MEMORY(data->string);
2276
2277                 return WERR_OK;
2278         }
2279
2280         if (!StrCaseCmp(value, "DsPresent")) {
2281                 *type = REG_DWORD;
2282
2283                 /* only show the publish check box if we are a
2284                    member of a AD domain */
2285
2286                 if (lp_security() == SEC_ADS) {
2287                         data->value = 0x01;
2288                 } else {
2289                         data->value = 0x00;
2290                 }
2291                 return WERR_OK;
2292         }
2293
2294         if (!StrCaseCmp(value, "DNSMachineName")) {
2295                 const char *hostname = get_mydnsfullname();
2296
2297                 if (!hostname) {
2298                         return WERR_BADFILE;
2299                 }
2300
2301                 *type = REG_SZ;
2302                 data->string = talloc_strdup(mem_ctx, hostname);
2303                 W_ERROR_HAVE_NO_MEMORY(data->string);
2304
2305                 return WERR_OK;
2306         }
2307
2308         *type = REG_NONE;
2309
2310         return WERR_INVALID_PARAM;
2311 }
2312
2313 /****************************************************************
2314  _spoolss_GetPrinterData
2315 ****************************************************************/
2316
2317 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2318                                struct spoolss_GetPrinterData *r)
2319 {
2320         struct spoolss_GetPrinterDataEx r2;
2321
2322         r2.in.handle            = r->in.handle;
2323         r2.in.key_name          = "PrinterDriverData";
2324         r2.in.value_name        = r->in.value_name;
2325         r2.in.offered           = r->in.offered;
2326         r2.out.type             = r->out.type;
2327         r2.out.data             = r->out.data;
2328         r2.out.needed           = r->out.needed;
2329
2330         return _spoolss_GetPrinterDataEx(p, &r2);
2331 }
2332
2333 /*********************************************************
2334  Connect to the client machine.
2335 **********************************************************/
2336
2337 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2338                         struct sockaddr_storage *client_ss, const char *remote_machine)
2339 {
2340         NTSTATUS ret;
2341         struct cli_state *the_cli;
2342         struct sockaddr_storage rm_addr;
2343
2344         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2345                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2346                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2347                         return false;
2348                 }
2349
2350                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2351                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2352                         return false;
2353                 }
2354         } else {
2355                 char addr[INET6_ADDRSTRLEN];
2356                 rm_addr = *client_ss;
2357                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2358                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2359                         addr));
2360         }
2361
2362         /* setup the connection */
2363
2364         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2365                 &rm_addr, 0, "IPC$", "IPC",
2366                 "", /* username */
2367                 "", /* domain */
2368                 "", /* password */
2369                 0, lp_client_signing(), NULL );
2370
2371         if ( !NT_STATUS_IS_OK( ret ) ) {
2372                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2373                         remote_machine ));
2374                 return false;
2375         }
2376
2377         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2378                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2379                 cli_shutdown(the_cli);
2380                 return false;
2381         }
2382
2383         /*
2384          * Ok - we have an anonymous connection to the IPC$ share.
2385          * Now start the NT Domain stuff :-).
2386          */
2387
2388         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2389         if (!NT_STATUS_IS_OK(ret)) {
2390                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2391                         remote_machine, nt_errstr(ret)));
2392                 cli_shutdown(the_cli);
2393                 return false;
2394         }
2395
2396         return true;
2397 }
2398
2399 /***************************************************************************
2400  Connect to the client.
2401 ****************************************************************************/
2402
2403 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2404                                         uint32_t localprinter, uint32_t type,
2405                                         struct policy_handle *handle,
2406                                         struct sockaddr_storage *client_ss)
2407 {
2408         WERROR result;
2409         NTSTATUS status;
2410
2411         /*
2412          * If it's the first connection, contact the client
2413          * and connect to the IPC$ share anonymously
2414          */
2415         if (smb_connections==0) {
2416                 fstring unix_printer;
2417
2418                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2419
2420                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2421                         return false;
2422
2423                 messaging_register(smbd_messaging_context(), NULL,
2424                                    MSG_PRINTER_NOTIFY2,
2425                                    receive_notify2_message_list);
2426                 /* Tell the connections db we're now interested in printer
2427                  * notify messages. */
2428                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2429         }
2430
2431         /*
2432          * Tell the specific printing tdb we want messages for this printer
2433          * by registering our PID.
2434          */
2435
2436         if (!print_notify_register_pid(snum))
2437                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2438
2439         smb_connections++;
2440
2441         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2442                                                  printer,
2443                                                  localprinter,
2444                                                  type,
2445                                                  0,
2446                                                  NULL,
2447                                                  handle,
2448                                                  &result);
2449         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2450                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2451                         win_errstr(result)));
2452
2453         return (W_ERROR_IS_OK(result));
2454 }
2455
2456 /****************************************************************
2457  ****************************************************************/
2458
2459 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2460                                                              const struct spoolss_NotifyOption *r)
2461 {
2462         struct spoolss_NotifyOption *option;
2463         uint32_t i,k;
2464
2465         if (!r) {
2466                 return NULL;
2467         }
2468
2469         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2470         if (!option) {
2471                 return NULL;
2472         }
2473
2474         *option = *r;
2475
2476         if (!option->count) {
2477                 return option;
2478         }
2479
2480         option->types = talloc_zero_array(option,
2481                 struct spoolss_NotifyOptionType, option->count);
2482         if (!option->types) {
2483                 talloc_free(option);
2484                 return NULL;
2485         }
2486
2487         for (i=0; i < option->count; i++) {
2488                 option->types[i] = r->types[i];
2489
2490                 if (option->types[i].count) {
2491                         option->types[i].fields = talloc_zero_array(option,
2492                                 union spoolss_Field, option->types[i].count);
2493                         if (!option->types[i].fields) {
2494                                 talloc_free(option);
2495                                 return NULL;
2496                         }
2497                         for (k=0; k<option->types[i].count; k++) {
2498                                 option->types[i].fields[k] =
2499                                         r->types[i].fields[k];
2500                         }
2501                 }
2502         }
2503
2504         return option;
2505 }
2506
2507 /****************************************************************
2508  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2509  *
2510  * before replying OK: status=0 a rpc call is made to the workstation
2511  * asking ReplyOpenPrinter
2512  *
2513  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2514  * called from api_spoolss_rffpcnex
2515 ****************************************************************/
2516
2517 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2518                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2519 {
2520         int snum = -1;
2521         struct spoolss_NotifyOption *option = r->in.notify_options;
2522         struct sockaddr_storage client_ss;
2523
2524         /* store the notify value in the printer struct */
2525
2526         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2527
2528         if (!Printer) {
2529                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2530                         "Invalid handle (%s:%u:%u).\n",
2531                         OUR_HANDLE(r->in.handle)));
2532                 return WERR_BADFID;
2533         }
2534
2535         Printer->notify.flags           = r->in.flags;
2536         Printer->notify.options         = r->in.options;
2537         Printer->notify.printerlocal    = r->in.printer_local;
2538
2539         TALLOC_FREE(Printer->notify.option);
2540         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2541
2542         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2543
2544         /* Connect to the client machine and send a ReplyOpenPrinter */
2545
2546         if ( Printer->printer_type == SPLHND_SERVER)
2547                 snum = -1;
2548         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2549                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2550                 return WERR_BADFID;
2551
2552         if (!interpret_string_addr(&client_ss, p->client_address,
2553                                    AI_NUMERICHOST)) {
2554                 return WERR_SERVER_UNAVAILABLE;
2555         }
2556
2557         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2558                                         Printer->notify.printerlocal, 1,
2559                                         &Printer->notify.client_hnd, &client_ss))
2560                 return WERR_SERVER_UNAVAILABLE;
2561
2562         Printer->notify.client_connected = true;
2563
2564         return WERR_OK;
2565 }
2566
2567 /*******************************************************************
2568  * fill a notify_info_data with the servername
2569  ********************************************************************/
2570
2571 void spoolss_notify_server_name(int snum,
2572                                        struct spoolss_Notify *data,
2573                                        print_queue_struct *queue,
2574                                        NT_PRINTER_INFO_LEVEL *printer,
2575                                        TALLOC_CTX *mem_ctx)
2576 {
2577         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2578 }
2579
2580 /*******************************************************************
2581  * fill a notify_info_data with the printername (not including the servername).
2582  ********************************************************************/
2583
2584 void spoolss_notify_printer_name(int snum,
2585                                         struct spoolss_Notify *data,
2586                                         print_queue_struct *queue,
2587                                         NT_PRINTER_INFO_LEVEL *printer,
2588                                         TALLOC_CTX *mem_ctx)
2589 {
2590         /* the notify name should not contain the \\server\ part */
2591         char *p = strrchr(printer->info_2->printername, '\\');
2592
2593         if (!p) {
2594                 p = printer->info_2->printername;
2595         } else {
2596                 p++;
2597         }
2598
2599         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2600 }
2601
2602 /*******************************************************************
2603  * fill a notify_info_data with the servicename
2604  ********************************************************************/
2605
2606 void spoolss_notify_share_name(int snum,
2607                                       struct spoolss_Notify *data,
2608                                       print_queue_struct *queue,
2609                                       NT_PRINTER_INFO_LEVEL *printer,
2610                                       TALLOC_CTX *mem_ctx)
2611 {
2612         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2613 }
2614
2615 /*******************************************************************
2616  * fill a notify_info_data with the port name
2617  ********************************************************************/
2618
2619 void spoolss_notify_port_name(int snum,
2620                                      struct spoolss_Notify *data,
2621                                      print_queue_struct *queue,
2622                                      NT_PRINTER_INFO_LEVEL *printer,
2623                                      TALLOC_CTX *mem_ctx)
2624 {
2625         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2626 }
2627
2628 /*******************************************************************
2629  * fill a notify_info_data with the printername
2630  * but it doesn't exist, have to see what to do
2631  ********************************************************************/
2632
2633 void spoolss_notify_driver_name(int snum,
2634                                        struct spoolss_Notify *data,
2635                                        print_queue_struct *queue,
2636                                        NT_PRINTER_INFO_LEVEL *printer,
2637                                        TALLOC_CTX *mem_ctx)
2638 {
2639         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2640 }
2641
2642 /*******************************************************************
2643  * fill a notify_info_data with the comment
2644  ********************************************************************/
2645
2646 void spoolss_notify_comment(int snum,
2647                                    struct spoolss_Notify *data,
2648                                    print_queue_struct *queue,
2649                                    NT_PRINTER_INFO_LEVEL *printer,
2650                                    TALLOC_CTX *mem_ctx)
2651 {
2652         char *p;
2653
2654         if (*printer->info_2->comment == '\0') {
2655                 p = lp_comment(snum);
2656         } else {
2657                 p = printer->info_2->comment;
2658         }
2659
2660         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2661 }
2662
2663 /*******************************************************************
2664  * fill a notify_info_data with the comment
2665  * location = "Room 1, floor 2, building 3"
2666  ********************************************************************/
2667
2668 void spoolss_notify_location(int snum,
2669                                     struct spoolss_Notify *data,
2670                                     print_queue_struct *queue,
2671                                     NT_PRINTER_INFO_LEVEL *printer,
2672                                     TALLOC_CTX *mem_ctx)
2673 {
2674         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2675 }
2676
2677 /*******************************************************************
2678  * fill a notify_info_data with the device mode
2679  * jfm:xxxx don't to it for know but that's a real problem !!!
2680  ********************************************************************/
2681
2682 static void spoolss_notify_devmode(int snum,
2683                                    struct spoolss_Notify *data,
2684                                    print_queue_struct *queue,
2685                                    NT_PRINTER_INFO_LEVEL *printer,
2686                                    TALLOC_CTX *mem_ctx)
2687 {
2688         /* for a dummy implementation we have to zero the fields */
2689         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2690 }
2691
2692 /*******************************************************************
2693  * fill a notify_info_data with the separator file name
2694  ********************************************************************/
2695
2696 void spoolss_notify_sepfile(int snum,
2697                                    struct spoolss_Notify *data,
2698                                    print_queue_struct *queue,
2699                                    NT_PRINTER_INFO_LEVEL *printer,
2700                                    TALLOC_CTX *mem_ctx)
2701 {
2702         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2703 }
2704
2705 /*******************************************************************
2706  * fill a notify_info_data with the print processor
2707  * jfm:xxxx return always winprint to indicate we don't do anything to it
2708  ********************************************************************/
2709
2710 void spoolss_notify_print_processor(int snum,
2711                                            struct spoolss_Notify *data,
2712                                            print_queue_struct *queue,
2713                                            NT_PRINTER_INFO_LEVEL *printer,
2714                                            TALLOC_CTX *mem_ctx)
2715 {
2716         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2717 }
2718
2719 /*******************************************************************
2720  * fill a notify_info_data with the print processor options
2721  * jfm:xxxx send an empty string
2722  ********************************************************************/
2723
2724 void spoolss_notify_parameters(int snum,
2725                                       struct spoolss_Notify *data,
2726                                       print_queue_struct *queue,
2727                                       NT_PRINTER_INFO_LEVEL *printer,
2728                                       TALLOC_CTX *mem_ctx)
2729 {
2730         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2731 }
2732
2733 /*******************************************************************
2734  * fill a notify_info_data with the data type
2735  * jfm:xxxx always send RAW as data type
2736  ********************************************************************/
2737
2738 void spoolss_notify_datatype(int snum,
2739                                     struct spoolss_Notify *data,
2740                                     print_queue_struct *queue,
2741                                     NT_PRINTER_INFO_LEVEL *printer,
2742                                     TALLOC_CTX *mem_ctx)
2743 {
2744         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2745 }
2746
2747 /*******************************************************************
2748  * fill a notify_info_data with the security descriptor
2749  * jfm:xxxx send an null pointer to say no security desc
2750  * have to implement security before !
2751  ********************************************************************/
2752
2753 static void spoolss_notify_security_desc(int snum,
2754                                          struct spoolss_Notify *data,
2755                                          print_queue_struct *queue,
2756                                          NT_PRINTER_INFO_LEVEL *printer,
2757                                          TALLOC_CTX *mem_ctx)
2758 {
2759         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2760                                           printer->info_2->secdesc_buf->sd_size,
2761                                           printer->info_2->secdesc_buf->sd);
2762 }
2763
2764 /*******************************************************************
2765  * fill a notify_info_data with the attributes
2766  * jfm:xxxx a samba printer is always shared
2767  ********************************************************************/
2768
2769 void spoolss_notify_attributes(int snum,
2770                                       struct spoolss_Notify *data,
2771                                       print_queue_struct *queue,
2772                                       NT_PRINTER_INFO_LEVEL *printer,
2773                                       TALLOC_CTX *mem_ctx)
2774 {
2775         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2776 }
2777
2778 /*******************************************************************
2779  * fill a notify_info_data with the priority
2780  ********************************************************************/
2781
2782 static void spoolss_notify_priority(int snum,
2783                                     struct spoolss_Notify *data,
2784                                     print_queue_struct *queue,
2785                                     NT_PRINTER_INFO_LEVEL *printer,
2786                                     TALLOC_CTX *mem_ctx)
2787 {
2788         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the default priority
2793  ********************************************************************/
2794
2795 static void spoolss_notify_default_priority(int snum,
2796                                             struct spoolss_Notify *data,
2797                                             print_queue_struct *queue,
2798                                             NT_PRINTER_INFO_LEVEL *printer,
2799                                             TALLOC_CTX *mem_ctx)
2800 {
2801         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2802 }
2803
2804 /*******************************************************************
2805  * fill a notify_info_data with the start time
2806  ********************************************************************/
2807
2808 static void spoolss_notify_start_time(int snum,
2809                                       struct spoolss_Notify *data,
2810                                       print_queue_struct *queue,
2811                                       NT_PRINTER_INFO_LEVEL *printer,
2812                                       TALLOC_CTX *mem_ctx)
2813 {
2814         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the until time
2819  ********************************************************************/
2820
2821 static void spoolss_notify_until_time(int snum,
2822                                       struct spoolss_Notify *data,
2823                                       print_queue_struct *queue,
2824                                       NT_PRINTER_INFO_LEVEL *printer,
2825                                       TALLOC_CTX *mem_ctx)
2826 {
2827         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2828 }
2829
2830 /*******************************************************************
2831  * fill a notify_info_data with the status
2832  ********************************************************************/
2833
2834 static void spoolss_notify_status(int snum,
2835                                   struct spoolss_Notify *data,
2836                                   print_queue_struct *queue,
2837                                   NT_PRINTER_INFO_LEVEL *printer,
2838                                   TALLOC_CTX *mem_ctx)
2839 {
2840         print_status_struct status;
2841
2842         print_queue_length(snum, &status);
2843         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the number of jobs queued
2848  ********************************************************************/
2849
2850 void spoolss_notify_cjobs(int snum,
2851                                  struct spoolss_Notify *data,
2852                                  print_queue_struct *queue,
2853                                  NT_PRINTER_INFO_LEVEL *printer,
2854                                  TALLOC_CTX *mem_ctx)
2855 {
2856         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2857 }
2858
2859 /*******************************************************************
2860  * fill a notify_info_data with the average ppm
2861  ********************************************************************/
2862
2863 static void spoolss_notify_average_ppm(int snum,
2864                                        struct spoolss_Notify *data,
2865                                        print_queue_struct *queue,
2866                                        NT_PRINTER_INFO_LEVEL *printer,
2867                                        TALLOC_CTX *mem_ctx)
2868 {
2869         /* always respond 8 pages per minutes */
2870         /* a little hard ! */
2871         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2872 }
2873
2874 /*******************************************************************
2875  * fill a notify_info_data with username
2876  ********************************************************************/
2877
2878 static void spoolss_notify_username(int snum,
2879                                     struct spoolss_Notify *data,
2880                                     print_queue_struct *queue,
2881                                     NT_PRINTER_INFO_LEVEL *printer,
2882                                     TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with job status
2889  ********************************************************************/
2890
2891 static void spoolss_notify_job_status(int snum,
2892                                       struct spoolss_Notify *data,
2893                                       print_queue_struct *queue,
2894                                       NT_PRINTER_INFO_LEVEL *printer,
2895                                       TALLOC_CTX *mem_ctx)
2896 {
2897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2898 }
2899
2900 /*******************************************************************
2901  * fill a notify_info_data with job name
2902  ********************************************************************/
2903
2904 static void spoolss_notify_job_name(int snum,
2905                                     struct spoolss_Notify *data,
2906                                     print_queue_struct *queue,
2907                                     NT_PRINTER_INFO_LEVEL *printer,
2908                                     TALLOC_CTX *mem_ctx)
2909 {
2910         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2911 }
2912
2913 /*******************************************************************
2914  * fill a notify_info_data with job status
2915  ********************************************************************/
2916
2917 static void spoolss_notify_job_status_string(int snum,
2918                                              struct spoolss_Notify *data,
2919                                              print_queue_struct *queue,
2920                                              NT_PRINTER_INFO_LEVEL *printer,
2921                                              TALLOC_CTX *mem_ctx)
2922 {
2923         /*
2924          * Now we're returning job status codes we just return a "" here. JRA.
2925          */
2926
2927         const char *p = "";
2928
2929 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2930         p = "unknown";
2931
2932         switch (queue->status) {
2933         case LPQ_QUEUED:
2934                 p = "Queued";
2935                 break;
2936         case LPQ_PAUSED:
2937                 p = "";    /* NT provides the paused string */
2938                 break;
2939         case LPQ_SPOOLING:
2940                 p = "Spooling";
2941                 break;
2942         case LPQ_PRINTING:
2943                 p = "Printing";
2944                 break;
2945         }
2946 #endif /* NO LONGER NEEDED. */
2947
2948         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2949 }
2950
2951 /*******************************************************************
2952  * fill a notify_info_data with job time
2953  ********************************************************************/
2954
2955 static void spoolss_notify_job_time(int snum,
2956                                     struct spoolss_Notify *data,
2957                                     print_queue_struct *queue,
2958                                     NT_PRINTER_INFO_LEVEL *printer,
2959                                     TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with job size
2966  ********************************************************************/
2967
2968 static void spoolss_notify_job_size(int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     NT_PRINTER_INFO_LEVEL *printer,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with page info
2979  ********************************************************************/
2980 static void spoolss_notify_total_pages(int snum,
2981                                 struct spoolss_Notify *data,
2982                                 print_queue_struct *queue,
2983                                 NT_PRINTER_INFO_LEVEL *printer,
2984                                 TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with pages printed info.
2991  ********************************************************************/
2992 static void spoolss_notify_pages_printed(int snum,
2993                                 struct spoolss_Notify *data,
2994                                 print_queue_struct *queue,
2995                                 NT_PRINTER_INFO_LEVEL *printer,
2996                                 TALLOC_CTX *mem_ctx)
2997 {
2998         /* Add code when back-end tracks this */
2999         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3000 }
3001
3002 /*******************************************************************
3003  Fill a notify_info_data with job position.
3004  ********************************************************************/
3005
3006 static void spoolss_notify_job_position(int snum,
3007                                         struct spoolss_Notify *data,
3008                                         print_queue_struct *queue,
3009                                         NT_PRINTER_INFO_LEVEL *printer,
3010                                         TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3013 }
3014
3015 /*******************************************************************
3016  Fill a notify_info_data with submitted time.
3017  ********************************************************************/
3018
3019 static void spoolss_notify_submitted_time(int snum,
3020                                           struct spoolss_Notify *data,
3021                                           print_queue_struct *queue,
3022                                           NT_PRINTER_INFO_LEVEL *printer,
3023                                           TALLOC_CTX *mem_ctx)
3024 {
3025         data->data.string.string = NULL;
3026         data->data.string.size = 0;
3027
3028         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3029                                &data->data.string.string,
3030                                &data->data.string.size);
3031
3032 }
3033
3034 struct s_notify_info_data_table
3035 {
3036         enum spoolss_NotifyType type;
3037         uint16_t field;
3038         const char *name;
3039         enum spoolss_NotifyTable variable_type;
3040         void (*fn) (int snum, struct spoolss_Notify *data,
3041                     print_queue_struct *queue,
3042                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3043 };
3044
3045 /* A table describing the various print notification constants and
3046    whether the notification data is a pointer to a variable sized
3047    buffer, a one value uint32_t or a two value uint32_t. */
3048
3049 static const struct s_notify_info_data_table notify_info_data_table[] =
3050 {
3051 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3052 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3053 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3054 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3055 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3056 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3077 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3078 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3079 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3080 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3081 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3082 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3083 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3084 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3085 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3086 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3087 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3088 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3100 };
3101
3102 /*******************************************************************
3103  Return the variable_type of info_data structure.
3104 ********************************************************************/
3105
3106 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3107                                                   uint16_t field)
3108 {
3109         int i=0;
3110
3111         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3112                 if ( (notify_info_data_table[i].type == type) &&
3113                      (notify_info_data_table[i].field == field) ) {
3114                         return notify_info_data_table[i].variable_type;
3115                 }
3116         }
3117
3118         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3119
3120         return 0;
3121 }
3122
3123 /****************************************************************************
3124 ****************************************************************************/
3125
3126 static bool search_notify(enum spoolss_NotifyType type,
3127                           uint16_t field,
3128                           int *value)
3129 {
3130         int i;
3131
3132         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3133                 if (notify_info_data_table[i].type == type &&
3134                     notify_info_data_table[i].field == field &&
3135                     notify_info_data_table[i].fn != NULL) {
3136                         *value = i;
3137                         return true;
3138                 }
3139         }
3140
3141         return false;
3142 }
3143
3144 /****************************************************************************
3145 ****************************************************************************/
3146
3147 void construct_info_data(struct spoolss_Notify *info_data,
3148                          enum spoolss_NotifyType type,
3149                          uint16_t field,
3150                          int id)
3151 {
3152         info_data->type                 = type;
3153         info_data->field.field          = field;
3154         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3155         info_data->job_id               = id;
3156 }
3157
3158 /*******************************************************************
3159  *
3160  * fill a notify_info struct with info asked
3161  *
3162  ********************************************************************/
3163
3164 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3165                                           struct spoolss_NotifyInfo *info,
3166                                           int snum,
3167                                           const struct spoolss_NotifyOptionType *option_type,
3168                                           uint32_t id,
3169                                           TALLOC_CTX *mem_ctx)
3170 {
3171         int field_num,j;
3172         enum spoolss_NotifyType type;
3173         uint16_t field;
3174
3175         struct spoolss_Notify *current_data;
3176         NT_PRINTER_INFO_LEVEL *printer = NULL;
3177         print_queue_struct *queue=NULL;
3178
3179         type = option_type->type;
3180
3181         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3182                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3183                 option_type->count, lp_servicename(snum)));
3184
3185         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3186                 return false;
3187
3188         for(field_num=0; field_num < option_type->count; field_num++) {
3189                 field = option_type->fields[field_num].field;
3190
3191                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3192
3193                 if (!search_notify(type, field, &j) )
3194                         continue;
3195
3196                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3197                                                       struct spoolss_Notify,
3198                                                       info->count + 1);
3199                 if (info->notifies == NULL) {
3200                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3201                         free_a_printer(&printer, 2);
3202                         return false;
3203                 }
3204
3205                 current_data = &info->notifies[info->count];
3206
3207                 construct_info_data(current_data, type, field, id);
3208
3209                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3210                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3211
3212                 notify_info_data_table[j].fn(snum, current_data, queue,
3213                                              printer, mem_ctx);
3214
3215                 info->count++;
3216         }
3217
3218         free_a_printer(&printer, 2);
3219         return true;
3220 }
3221
3222 /*******************************************************************
3223  *
3224  * fill a notify_info struct with info asked
3225  *
3226  ********************************************************************/
3227
3228 static bool construct_notify_jobs_info(print_queue_struct *queue,
3229                                        struct spoolss_NotifyInfo *info,
3230                                        NT_PRINTER_INFO_LEVEL *printer,
3231                                        int snum,
3232                                        const struct spoolss_NotifyOptionType *option_type,
3233                                        uint32_t id,
3234                                        TALLOC_CTX *mem_ctx)
3235 {
3236         int field_num,j;
3237         enum spoolss_NotifyType type;
3238         uint16_t field;
3239         struct spoolss_Notify *current_data;
3240
3241         DEBUG(4,("construct_notify_jobs_info\n"));
3242
3243         type = option_type->type;
3244
3245         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3246                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3247                 option_type->count));
3248
3249         for(field_num=0; field_num<option_type->count; field_num++) {
3250                 field = option_type->fields[field_num].field;
3251
3252                 if (!search_notify(type, field, &j) )
3253                         continue;
3254
3255                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3256                                                       struct spoolss_Notify,
3257                                                       info->count + 1);
3258                 if (info->notifies == NULL) {
3259                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3260                         return false;
3261                 }
3262
3263                 current_data=&(info->notifies[info->count]);
3264
3265                 construct_info_data(current_data, type, field, id);
3266                 notify_info_data_table[j].fn(snum, current_data, queue,
3267                                              printer, mem_ctx);
3268                 info->count++;
3269         }
3270
3271         return true;
3272 }
3273
3274 /*
3275  * JFM: The enumeration is not that simple, it's even non obvious.
3276  *
3277  * let's take an example: I want to monitor the PRINTER SERVER for
3278  * the printer's name and the number of jobs currently queued.
3279  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3280  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3281  *
3282  * I have 3 printers on the back of my server.
3283  *
3284  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3285  * structures.
3286  *   Number     Data                    Id
3287  *      1       printer 1 name          1
3288  *      2       printer 1 cjob          1
3289  *      3       printer 2 name          2
3290  *      4       printer 2 cjob          2
3291  *      5       printer 3 name          3
3292  *      6       printer 3 name          3
3293  *
3294  * that's the print server case, the printer case is even worse.
3295  */
3296
3297 /*******************************************************************
3298  *
3299  * enumerate all printers on the printserver
3300  * fill a notify_info struct with info asked
3301  *
3302  ********************************************************************/
3303
3304 static WERROR printserver_notify_info(pipes_struct *p,
3305                                       struct policy_handle *hnd,
3306                                       struct spoolss_NotifyInfo *info,
3307                                       TALLOC_CTX *mem_ctx)
3308 {
3309         int snum;
3310         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3311         int n_services=lp_numservices();
3312         int i;
3313         struct spoolss_NotifyOption *option;
3314         struct spoolss_NotifyOptionType option_type;
3315
3316         DEBUG(4,("printserver_notify_info\n"));
3317
3318         if (!Printer)
3319                 return WERR_BADFID;
3320
3321         option = Printer->notify.option;
3322
3323         info->version   = 2;
3324         info->notifies  = NULL;
3325         info->count     = 0;
3326
3327         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3328            sending a ffpcn() request first */
3329
3330         if ( !option )
3331                 return WERR_BADFID;
3332
3333         for (i=0; i<option->count; i++) {
3334                 option_type = option->types[i];
3335
3336                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3337                         continue;
3338
3339                 for (snum=0; snum<n_services; snum++)
3340                 {
3341                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3342                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3343                 }
3344         }
3345
3346 #if 0
3347         /*
3348          * Debugging information, don't delete.
3349          */
3350
3351         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3352         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3353         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3354
3355         for (i=0; i<info->count; i++) {
3356                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3357                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3358                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3359         }
3360 #endif
3361
3362         return WERR_OK;
3363 }
3364
3365 /*******************************************************************
3366  *
3367  * fill a notify_info struct with info asked
3368  *
3369  ********************************************************************/
3370
3371 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3372                                   struct spoolss_NotifyInfo *info,
3373                                   TALLOC_CTX *mem_ctx)
3374 {
3375         int snum;
3376         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3377         int i;
3378         uint32_t id;
3379         struct spoolss_NotifyOption *option;
3380         struct spoolss_NotifyOptionType option_type;
3381         int count,j;
3382         print_queue_struct *queue=NULL;
3383         print_status_struct status;
3384
3385         DEBUG(4,("printer_notify_info\n"));
3386
3387         if (!Printer)
3388                 return WERR_BADFID;
3389
3390         option = Printer->notify.option;
3391         id = 0x0;
3392
3393         info->version   = 2;
3394         info->notifies  = NULL;
3395         info->count     = 0;
3396
3397         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3398            sending a ffpcn() request first */
3399
3400         if ( !option )
3401                 return WERR_BADFID;
3402
3403         get_printer_snum(p, hnd, &snum, NULL);
3404
3405         for (i=0; i<option->count; i++) {
3406                 option_type = option->types[i];
3407
3408                 switch (option_type.type) {
3409                 case PRINTER_NOTIFY_TYPE:
3410                         if(construct_notify_printer_info(Printer, info, snum,
3411                                                          &option_type, id,
3412                                                          mem_ctx))
3413                                 id--;
3414                         break;
3415
3416                 case JOB_NOTIFY_TYPE: {
3417                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3418
3419                         count = print_queue_status(snum, &queue, &status);
3420
3421                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3422                                 goto done;
3423
3424                         for (j=0; j<count; j++) {
3425                                 construct_notify_jobs_info(&queue[j], info,
3426                                                            printer, snum,
3427                                                            &option_type,
3428                                                            queue[j].job,
3429                                                            mem_ctx);
3430                         }
3431
3432                         free_a_printer(&printer, 2);
3433
3434                 done:
3435                         SAFE_FREE(queue);
3436                         break;
3437                 }
3438                 }
3439         }
3440
3441         /*
3442          * Debugging information, don't delete.
3443          */
3444         /*
3445         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3446         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3447         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3448
3449         for (i=0; i<info->count; i++) {
3450                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3451                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3452                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3453         }
3454         */
3455         return WERR_OK;
3456 }
3457
3458 /****************************************************************
3459  _spoolss_RouterRefreshPrinterChangeNotify
3460 ****************************************************************/
3461
3462 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3463                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3464 {
3465         struct spoolss_NotifyInfo *info;
3466
3467         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3468         WERROR result = WERR_BADFID;
3469
3470         /* we always have a spoolss_NotifyInfo struct */
3471         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3472         if (!info) {
3473                 result = WERR_NOMEM;
3474                 goto done;
3475         }
3476
3477         *r->out.info = info;
3478
3479         if (!Printer) {
3480                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3481                         "Invalid handle (%s:%u:%u).\n",
3482                         OUR_HANDLE(r->in.handle)));
3483                 goto done;
3484         }
3485
3486         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3487
3488         /*
3489          *      We are now using the change value, and
3490          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3491          *      I don't have a global notification system, I'm sending back all the
3492          *      informations even when _NOTHING_ has changed.
3493          */
3494
3495         /* We need to keep track of the change value to send back in
3496            RRPCN replies otherwise our updates are ignored. */
3497
3498         Printer->notify.fnpcn = true;
3499
3500         if (Printer->notify.client_connected) {
3501                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3502                         "Saving change value in request [%x]\n",
3503                         r->in.change_low));
3504                 Printer->notify.change = r->in.change_low;
3505         }
3506
3507         /* just ignore the spoolss_NotifyOption */
3508
3509         switch (Printer->printer_type) {
3510                 case SPLHND_SERVER:
3511                         result = printserver_notify_info(p, r->in.handle,
3512                                                          info, p->mem_ctx);
3513                         break;
3514
3515                 case SPLHND_PRINTER:
3516                         result = printer_notify_info(p, r->in.handle,
3517                                                      info, p->mem_ctx);
3518                         break;
3519         }
3520
3521         Printer->notify.fnpcn = false;
3522
3523 done:
3524         return result;
3525 }
3526
3527 /********************************************************************
3528  * construct_printer_info_0
3529  * fill a printer_info_0 struct
3530  ********************************************************************/
3531
3532 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3533                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3534                                       struct spoolss_PrinterInfo0 *r,
3535                                       int snum)
3536 {
3537         int count;
3538         counter_printer_0 *session_counter;
3539         time_t setuptime;
3540         print_status_struct status;
3541
3542         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3543         W_ERROR_HAVE_NO_MEMORY(r->printername);
3544
3545         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3546         W_ERROR_HAVE_NO_MEMORY(r->servername);
3547
3548         count = print_queue_length(snum, &status);
3549
3550         /* check if we already have a counter for this printer */
3551         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3552                 if (session_counter->snum == snum)
3553                         break;
3554         }
3555
3556         /* it's the first time, add it to the list */
3557         if (session_counter == NULL) {
3558                 session_counter = SMB_MALLOC_P(counter_printer_0);
3559                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3560                 ZERO_STRUCTP(session_counter);
3561                 session_counter->snum           = snum;
3562                 session_counter->counter        = 0;
3563                 DLIST_ADD(counter_list, session_counter);
3564         }
3565
3566         /* increment it */
3567         session_counter->counter++;
3568
3569         r->cjobs                        = count;
3570         r->total_jobs                   = 0;
3571         r->total_bytes                  = 0;
3572
3573         setuptime = (time_t)ntprinter->info_2->setuptime;
3574
3575         init_systemtime(&r->time, gmtime(&setuptime));
3576
3577         /* JFM:
3578          * the global_counter should be stored in a TDB as it's common to all the clients
3579          * and should be zeroed on samba startup
3580          */
3581         r->global_counter               = session_counter->counter;
3582         r->total_pages                  = 0;
3583         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3584         r->version                      = 0x0005;       /* NT 5 */
3585         r->free_build                   = 0x0893;       /* build 2195 */
3586         r->spooling                     = 0;
3587         r->max_spooling                 = 0;
3588         r->session_counter              = session_counter->counter;
3589         r->num_error_out_of_paper       = 0x0;
3590         r->num_error_not_ready          = 0x0;          /* number of print failure */
3591         r->job_error                    = 0x0;
3592         r->number_of_processors         = 0x1;
3593         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3594         r->high_part_total_bytes        = 0x0;
3595         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3596         r->last_error                   = WERR_OK;
3597         r->status                       = nt_printq_status(status.status);
3598         r->enumerate_network_printers   = 0x0;
3599         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3600         r->processor_architecture       = 0x0;
3601         r->processor_level              = 0x6;          /* 6  ???*/
3602         r->ref_ic                       = 0;
3603         r->reserved2                    = 0;
3604         r->reserved3                    = 0;
3605
3606         return WERR_OK;
3607 }
3608
3609 /****************************************************************************
3610  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3611  should be valid upon entry
3612 ****************************************************************************/
3613
3614 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3615                                     struct spoolss_DeviceMode *r,
3616                                     const NT_DEVICEMODE *ntdevmode)
3617 {
3618         if (!r || !ntdevmode) {
3619                 return WERR_INVALID_PARAM;
3620         }
3621
3622         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3623         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3624
3625         r->specversion          = ntdevmode->specversion;
3626         r->driverversion        = ntdevmode->driverversion;
3627         r->size                 = ntdevmode->size;
3628         r->__driverextra_length = ntdevmode->driverextra;
3629         r->fields               = ntdevmode->fields;
3630
3631         r->orientation          = ntdevmode->orientation;
3632         r->papersize            = ntdevmode->papersize;
3633         r->paperlength          = ntdevmode->paperlength;
3634         r->paperwidth           = ntdevmode->paperwidth;
3635         r->scale                = ntdevmode->scale;
3636         r->copies               = ntdevmode->copies;
3637         r->defaultsource        = ntdevmode->defaultsource;
3638         r->printquality         = ntdevmode->printquality;
3639         r->color                = ntdevmode->color;
3640         r->duplex               = ntdevmode->duplex;
3641         r->yresolution          = ntdevmode->yresolution;
3642         r->ttoption             = ntdevmode->ttoption;
3643         r->collate              = ntdevmode->collate;
3644
3645         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3646         W_ERROR_HAVE_NO_MEMORY(r->formname);
3647
3648         /* all 0 below are values that have not been set in the old parsing/copy
3649          * function, maybe they should... - gd */
3650
3651         r->logpixels            = 0;
3652         r->bitsperpel           = 0;
3653         r->pelswidth            = 0;
3654         r->pelsheight           = 0;
3655         r->displayflags         = 0;
3656         r->displayfrequency     = 0;
3657         r->icmmethod            = ntdevmode->icmmethod;
3658         r->icmintent            = ntdevmode->icmintent;
3659         r->mediatype            = ntdevmode->mediatype;
3660         r->dithertype           = ntdevmode->dithertype;
3661         r->reserved1            = 0;
3662         r->reserved2            = 0;
3663         r->panningwidth         = 0;
3664         r->panningheight        = 0;
3665
3666         if (ntdevmode->nt_dev_private != NULL) {
3667                 r->driverextra_data = data_blob_talloc(mem_ctx,
3668                         ntdevmode->nt_dev_private,
3669                         ntdevmode->driverextra);
3670                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3671         }
3672
3673         return WERR_OK;
3674 }
3675
3676
3677 /****************************************************************************
3678  Create a spoolss_DeviceMode struct. Returns talloced memory.
3679 ****************************************************************************/
3680
3681 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3682                                               const char *servicename)
3683 {
3684         WERROR result;
3685         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3686         struct spoolss_DeviceMode *devmode = NULL;
3687
3688         DEBUG(7,("construct_dev_mode\n"));
3689
3690         DEBUGADD(8,("getting printer characteristics\n"));
3691
3692         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3693                 return NULL;
3694
3695         if (!printer->info_2->devmode) {
3696                 DEBUG(5, ("BONG! There was no device mode!\n"));
3697                 goto done;
3698         }
3699
3700         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3701         if (!devmode) {
3702                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3703                 goto done;
3704         }
3705
3706         DEBUGADD(8,("loading DEVICEMODE\n"));
3707
3708         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3709         if (!W_ERROR_IS_OK(result)) {
3710                 TALLOC_FREE(devmode);
3711         }
3712
3713 done:
3714         free_a_printer(&printer,2);
3715
3716         return devmode;
3717 }
3718
3719 /********************************************************************
3720  * construct_printer_info1
3721  * fill a spoolss_PrinterInfo1 struct
3722 ********************************************************************/
3723
3724 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3725                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3726                                       uint32_t flags,
3727                                       struct spoolss_PrinterInfo1 *r,
3728                                       int snum)
3729 {
3730         r->flags                = flags;
3731
3732         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3733                                                   ntprinter->info_2->printername,
3734                                                   ntprinter->info_2->drivername,
3735                                                   ntprinter->info_2->location);
3736         W_ERROR_HAVE_NO_MEMORY(r->description);
3737
3738         if (*ntprinter->info_2->comment == '\0') {
3739                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3740         } else {
3741                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3742         }
3743         W_ERROR_HAVE_NO_MEMORY(r->comment);
3744
3745         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3746         W_ERROR_HAVE_NO_MEMORY(r->name);
3747
3748         return WERR_OK;
3749 }
3750
3751 /********************************************************************
3752  * construct_printer_info2
3753  * fill a spoolss_PrinterInfo2 struct
3754 ********************************************************************/
3755
3756 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3757                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3758                                       struct spoolss_PrinterInfo2 *r,
3759                                       int snum)
3760 {
3761         int count;
3762
3763         print_status_struct status;
3764
3765         count = print_queue_length(snum, &status);
3766
3767         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3768         W_ERROR_HAVE_NO_MEMORY(r->servername);
3769         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3770         W_ERROR_HAVE_NO_MEMORY(r->printername);
3771         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3772         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3773         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3774         W_ERROR_HAVE_NO_MEMORY(r->portname);
3775         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3776         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3777
3778         if (*ntprinter->info_2->comment == '\0') {
3779                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3780         } else {
3781                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3782         }
3783         W_ERROR_HAVE_NO_MEMORY(r->comment);
3784
3785         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3786         W_ERROR_HAVE_NO_MEMORY(r->location);
3787         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3788         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3789         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3790         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3791         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3792         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3793         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3794         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3795
3796         r->attributes           = ntprinter->info_2->attributes;
3797
3798         r->priority             = ntprinter->info_2->priority;
3799         r->defaultpriority      = ntprinter->info_2->default_priority;
3800         r->starttime            = ntprinter->info_2->starttime;
3801         r->untiltime            = ntprinter->info_2->untiltime;
3802         r->status               = nt_printq_status(status.status);
3803         r->cjobs                = count;
3804         r->averageppm           = ntprinter->info_2->averageppm;
3805
3806         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3807         if (!r->devmode) {
3808                 DEBUG(8,("Returning NULL Devicemode!\n"));
3809         }
3810
3811         r->secdesc              = NULL;
3812
3813         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3814                 /* don't use talloc_steal() here unless you do a deep steal of all
3815                    the SEC_DESC members */
3816
3817                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3818         }
3819
3820         return WERR_OK;
3821 }
3822
3823 /********************************************************************
3824  * construct_printer_info3
3825  * fill a spoolss_PrinterInfo3 struct
3826  ********************************************************************/
3827
3828 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3829                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3830                                       struct spoolss_PrinterInfo3 *r,
3831                                       int snum)
3832 {
3833         /* These are the components of the SD we are returning. */
3834
3835         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3836                 /* don't use talloc_steal() here unless you do a deep steal of all
3837                    the SEC_DESC members */
3838
3839                 r->secdesc = dup_sec_desc(mem_ctx,
3840                                           ntprinter->info_2->secdesc_buf->sd);
3841                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3842         }
3843
3844         return WERR_OK;
3845 }
3846
3847 /********************************************************************
3848  * construct_printer_info4
3849  * fill a spoolss_PrinterInfo4 struct
3850  ********************************************************************/
3851
3852 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3853                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3854                                       struct spoolss_PrinterInfo4 *r,
3855                                       int snum)
3856 {
3857         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3858         W_ERROR_HAVE_NO_MEMORY(r->printername);
3859         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3860         W_ERROR_HAVE_NO_MEMORY(r->servername);
3861
3862         r->attributes   = ntprinter->info_2->attributes;
3863
3864         return WERR_OK;
3865 }
3866
3867 /********************************************************************
3868  * construct_printer_info5
3869  * fill a spoolss_PrinterInfo5 struct
3870  ********************************************************************/
3871
3872 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3873                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3874                                       struct spoolss_PrinterInfo5 *r,
3875                                       int snum)
3876 {
3877         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3878         W_ERROR_HAVE_NO_MEMORY(r->printername);
3879         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3880         W_ERROR_HAVE_NO_MEMORY(r->portname);
3881
3882         r->attributes   = ntprinter->info_2->attributes;
3883
3884         /* these two are not used by NT+ according to MSDN */
3885
3886         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3887         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3888
3889         return WERR_OK;
3890 }
3891
3892 /********************************************************************
3893  * construct_printer_info_6
3894  * fill a spoolss_PrinterInfo6 struct
3895  ********************************************************************/
3896
3897 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3898                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3899                                       struct spoolss_PrinterInfo6 *r,
3900                                       int snum)
3901 {
3902         int count;
3903         print_status_struct status;
3904
3905         count = print_queue_length(snum, &status);
3906
3907         r->status = nt_printq_status(status.status);
3908
3909         return WERR_OK;
3910 }
3911
3912 /********************************************************************
3913  * construct_printer_info7
3914  * fill a spoolss_PrinterInfo7 struct
3915  ********************************************************************/
3916
3917 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3918                                       Printer_entry *print_hnd,
3919                                       struct spoolss_PrinterInfo7 *r,
3920                                       int snum)
3921 {
3922         struct GUID guid;
3923
3924         if (is_printer_published(print_hnd, snum, &guid)) {
3925                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3926                 r->action = DSPRINT_PUBLISH;
3927         } else {
3928                 r->guid = talloc_strdup(mem_ctx, "");
3929                 r->action = DSPRINT_UNPUBLISH;
3930         }
3931         W_ERROR_HAVE_NO_MEMORY(r->guid);
3932
3933         return WERR_OK;
3934 }
3935
3936 /********************************************************************
3937  * construct_printer_info8
3938  * fill a spoolss_PrinterInfo8 struct
3939  ********************************************************************/
3940
3941 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3942                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3943                                       struct spoolss_DeviceModeInfo *r,
3944                                       int snum)
3945 {
3946         struct spoolss_DeviceMode *devmode;
3947         WERROR result;
3948
3949         if (!ntprinter->info_2->devmode) {
3950                 r->devmode = NULL;
3951                 return WERR_OK;
3952         }
3953
3954         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3955         W_ERROR_HAVE_NO_MEMORY(devmode);
3956
3957         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
3958         if (!W_ERROR_IS_OK(result)) {
3959                 TALLOC_FREE(devmode);
3960                 return result;
3961         }
3962
3963         r->devmode      = devmode;
3964
3965         return WERR_OK;
3966 }
3967
3968
3969 /********************************************************************
3970 ********************************************************************/
3971
3972 static bool snum_is_shared_printer(int snum)
3973 {
3974         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3975 }
3976
3977 /********************************************************************
3978  Spoolss_enumprinters.
3979 ********************************************************************/
3980
3981 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3982                                            uint32_t level,
3983                                            uint32_t flags,
3984                                            union spoolss_PrinterInfo **info_p,
3985                                            uint32_t *count_p)
3986 {
3987         int snum;
3988         int n_services = lp_numservices();
3989         union spoolss_PrinterInfo *info = NULL;
3990         uint32_t count = 0;
3991         WERROR result = WERR_OK;
3992
3993         *count_p = 0;
3994         *info_p = NULL;
3995
3996         for (snum = 0; snum < n_services; snum++) {
3997
3998                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999
4000                 if (!snum_is_shared_printer(snum)) {
4001                         continue;
4002                 }
4003
4004                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4005                         lp_servicename(snum), snum));
4006
4007                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4008                                             union spoolss_PrinterInfo,
4009                                             count + 1);
4010                 if (!info) {
4011                         result = WERR_NOMEM;
4012                         goto out;
4013                 }
4014
4015                 result = get_a_printer(NULL, &ntprinter, 2,
4016                                        lp_const_servicename(snum));
4017                 if (!W_ERROR_IS_OK(result)) {
4018                         goto out;
4019                 }
4020
4021                 switch (level) {
4022                 case 0:
4023                         result = construct_printer_info0(info, ntprinter,
4024                                                          &info[count].info0, snum);
4025                         break;
4026                 case 1:
4027                         result = construct_printer_info1(info, ntprinter, flags,
4028                                                          &info[count].info1, snum);
4029                         break;
4030                 case 2:
4031                         result = construct_printer_info2(info, ntprinter,
4032                                                          &info[count].info2, snum);
4033                         break;
4034                 case 4:
4035                         result = construct_printer_info4(info, ntprinter,
4036                                                          &info[count].info4, snum);
4037                         break;
4038                 case 5:
4039                         result = construct_printer_info5(info, ntprinter,
4040                                                          &info[count].info5, snum);
4041                         break;
4042
4043                 default:
4044                         result = WERR_UNKNOWN_LEVEL;
4045                         free_a_printer(&ntprinter, 2);
4046                         goto out;
4047                 }
4048
4049                 free_a_printer(&ntprinter, 2);
4050                 if (!W_ERROR_IS_OK(result)) {
4051                         goto out;
4052                 }
4053
4054                 count++;
4055         }
4056
4057         *count_p = count;
4058         *info_p = info;
4059
4060  out:
4061         if (!W_ERROR_IS_OK(result)) {
4062                 TALLOC_FREE(info);
4063                 return result;
4064         }
4065
4066         *info_p = info;
4067
4068         return WERR_OK;
4069 }
4070
4071 /********************************************************************
4072  * handle enumeration of printers at level 0
4073  ********************************************************************/
4074
4075 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4076                                   uint32_t flags,
4077                                   const char *servername,
4078                                   union spoolss_PrinterInfo **info,
4079                                   uint32_t *count)
4080 {
4081         DEBUG(4,("enum_all_printers_info_0\n"));
4082
4083         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4084 }
4085
4086
4087 /********************************************************************
4088 ********************************************************************/
4089
4090 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4091                                        uint32_t flags,
4092                                        union spoolss_PrinterInfo **info,
4093                                        uint32_t *count)
4094 {
4095         DEBUG(4,("enum_all_printers_info_1\n"));
4096
4097         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4098 }
4099
4100 /********************************************************************
4101  enum_all_printers_info_1_local.
4102 *********************************************************************/
4103
4104 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4105                                              union spoolss_PrinterInfo **info,
4106                                              uint32_t *count)
4107 {
4108         DEBUG(4,("enum_all_printers_info_1_local\n"));
4109
4110         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4111 }
4112
4113 /********************************************************************
4114  enum_all_printers_info_1_name.
4115 *********************************************************************/
4116
4117 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4118                                             const char *name,
4119                                             union spoolss_PrinterInfo **info,
4120                                             uint32_t *count)
4121 {
4122         const char *s = name;
4123
4124         DEBUG(4,("enum_all_printers_info_1_name\n"));
4125
4126         if ((name[0] == '\\') && (name[1] == '\\')) {
4127                 s = name + 2;
4128         }
4129
4130         if (!is_myname_or_ipaddr(s)) {
4131                 return WERR_INVALID_NAME;
4132         }
4133
4134         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4135 }
4136
4137 /********************************************************************
4138  enum_all_printers_info_1_network.
4139 *********************************************************************/
4140
4141 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4142                                                const char *name,
4143                                                union spoolss_PrinterInfo **info,
4144                                                uint32_t *count)
4145 {
4146         const char *s = name;
4147
4148         DEBUG(4,("enum_all_printers_info_1_network\n"));
4149
4150         /* If we respond to a enum_printers level 1 on our name with flags
4151            set to PRINTER_ENUM_REMOTE with a list of printers then these
4152            printers incorrectly appear in the APW browse list.
4153            Specifically the printers for the server appear at the workgroup
4154            level where all the other servers in the domain are
4155            listed. Windows responds to this call with a
4156            WERR_CAN_NOT_COMPLETE so we should do the same. */
4157
4158         if (name[0] == '\\' && name[1] == '\\') {
4159                  s = name + 2;
4160         }
4161
4162         if (is_myname_or_ipaddr(s)) {
4163                  return WERR_CAN_NOT_COMPLETE;
4164         }
4165
4166         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4167 }
4168
4169 /********************************************************************
4170  * api_spoolss_enumprinters
4171  *
4172  * called from api_spoolss_enumprinters (see this to understand)
4173  ********************************************************************/
4174
4175 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4176                                        union spoolss_PrinterInfo **info,
4177                                        uint32_t *count)
4178 {
4179         DEBUG(4,("enum_all_printers_info_2\n"));
4180
4181         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4182 }
4183
4184 /********************************************************************
4185  * handle enumeration of printers at level 1
4186  ********************************************************************/
4187
4188 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4189                                   uint32_t flags,
4190                                   const char *name,
4191                                   union spoolss_PrinterInfo **info,
4192                                   uint32_t *count)
4193 {
4194         /* Not all the flags are equals */
4195
4196         if (flags & PRINTER_ENUM_LOCAL) {
4197                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4198         }
4199
4200         if (flags & PRINTER_ENUM_NAME) {
4201                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4202         }
4203
4204         if (flags & PRINTER_ENUM_NETWORK) {
4205                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4206         }
4207
4208         return WERR_OK; /* NT4sp5 does that */
4209 }
4210
4211 /********************************************************************
4212  * handle enumeration of printers at level 2
4213  ********************************************************************/
4214
4215 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4216                                   uint32_t flags,
4217                                   const char *servername,
4218                                   union spoolss_PrinterInfo **info,
4219                                   uint32_t *count)
4220 {
4221         if (flags & PRINTER_ENUM_LOCAL) {
4222                 return enum_all_printers_info_2(mem_ctx, info, count);
4223         }
4224
4225         if (flags & PRINTER_ENUM_NAME) {
4226                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4227                         return WERR_INVALID_NAME;
4228                 }
4229
4230                 return enum_all_printers_info_2(mem_ctx, info, count);
4231         }
4232
4233         if (flags & PRINTER_ENUM_REMOTE) {
4234                 return WERR_UNKNOWN_LEVEL;
4235         }
4236
4237         return WERR_OK;
4238 }
4239
4240 /********************************************************************
4241  * handle enumeration of printers at level 4
4242  ********************************************************************/
4243
4244 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4245                                   uint32_t flags,
4246                                   const char *servername,
4247                                   union spoolss_PrinterInfo **info,
4248                                   uint32_t *count)
4249 {
4250         DEBUG(4,("enum_all_printers_info_4\n"));
4251
4252         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4253 }
4254
4255
4256 /********************************************************************
4257  * handle enumeration of printers at level 5
4258  ********************************************************************/
4259
4260 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4261                                   uint32_t flags,
4262                                   const char *servername,
4263                                   union spoolss_PrinterInfo **info,
4264                                   uint32_t *count)
4265 {
4266         DEBUG(4,("enum_all_printers_info_5\n"));
4267
4268         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4269 }
4270
4271 /****************************************************************
4272  _spoolss_EnumPrinters
4273 ****************************************************************/
4274
4275 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4276                              struct spoolss_EnumPrinters *r)
4277 {
4278         const char *name;
4279         WERROR result;
4280
4281         /* that's an [in out] buffer */
4282
4283         if (!r->in.buffer && (r->in.offered != 0)) {
4284                 return WERR_INVALID_PARAM;
4285         }
4286
4287         DEBUG(4,("_spoolss_EnumPrinters\n"));
4288
4289         *r->out.needed = 0;
4290         *r->out.count = 0;
4291         *r->out.info = NULL;
4292
4293         /*
4294          * Level 1:
4295          *          flags==PRINTER_ENUM_NAME
4296          *           if name=="" then enumerates all printers
4297          *           if name!="" then enumerate the printer
4298          *          flags==PRINTER_ENUM_REMOTE
4299          *          name is NULL, enumerate printers
4300          * Level 2: name!="" enumerates printers, name can't be NULL
4301          * Level 3: doesn't exist
4302          * Level 4: does a local registry lookup
4303          * Level 5: same as Level 2
4304          */
4305
4306         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4307         W_ERROR_HAVE_NO_MEMORY(name);
4308
4309         switch (r->in.level) {
4310         case 0:
4311                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4312                                              r->out.info, r->out.count);
4313                 break;
4314         case 1:
4315                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4316                                              r->out.info, r->out.count);
4317                 break;
4318         case 2:
4319                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4320                                              r->out.info, r->out.count);
4321                 break;
4322         case 4:
4323                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4324                                              r->out.info, r->out.count);
4325                 break;
4326         case 5:
4327                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4328                                              r->out.info, r->out.count);
4329                 break;
4330         default:
4331                 return WERR_UNKNOWN_LEVEL;
4332         }
4333
4334         if (!W_ERROR_IS_OK(result)) {
4335                 return result;
4336         }
4337
4338         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4339                                                      spoolss_EnumPrinters, NULL,
4340                                                      *r->out.info, r->in.level,
4341                                                      *r->out.count);
4342         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4343         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4344
4345         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4346 }
4347
4348 /****************************************************************
4349  _spoolss_GetPrinter
4350 ****************************************************************/
4351
4352 WERROR _spoolss_GetPrinter(pipes_struct *p,
4353                            struct spoolss_GetPrinter *r)
4354 {
4355         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4356         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4357         WERROR result = WERR_OK;
4358
4359         int snum;
4360
4361         /* that's an [in out] buffer */
4362
4363         if (!r->in.buffer && (r->in.offered != 0)) {
4364                 return WERR_INVALID_PARAM;
4365         }
4366
4367         *r->out.needed = 0;
4368
4369         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4370                 return WERR_BADFID;
4371         }
4372
4373         result = get_a_printer(Printer, &ntprinter, 2,
4374                                lp_const_servicename(snum));
4375         if (!W_ERROR_IS_OK(result)) {
4376                 return result;
4377         }
4378
4379         switch (r->in.level) {
4380         case 0:
4381                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4382                                                  &r->out.info->info0, snum);
4383                 break;
4384         case 1:
4385                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4386                                                  PRINTER_ENUM_ICON8,
4387                                                  &r->out.info->info1, snum);
4388                 break;
4389         case 2:
4390                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4391                                                  &r->out.info->info2, snum);
4392                 break;
4393         case 3:
4394                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4395                                                  &r->out.info->info3, snum);
4396                 break;
4397         case 4:
4398                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4399                                                  &r->out.info->info4, snum);
4400                 break;
4401         case 5:
4402                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4403                                                  &r->out.info->info5, snum);
4404                 break;
4405         case 6:
4406                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4407                                                  &r->out.info->info6, snum);
4408                 break;
4409         case 7:
4410                 result = construct_printer_info7(p->mem_ctx, Printer,
4411                                                  &r->out.info->info7, snum);
4412                 break;
4413         case 8:
4414                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4415                                                  &r->out.info->info8, snum);
4416                 break;
4417         default:
4418                 result = WERR_UNKNOWN_LEVEL;
4419                 break;
4420         }
4421
4422         free_a_printer(&ntprinter, 2);
4423
4424         if (!W_ERROR_IS_OK(result)) {
4425                 TALLOC_FREE(r->out.info);
4426                 return result;
4427         }
4428
4429         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4430                                                r->out.info, r->in.level);
4431         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4432
4433         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4434 }
4435
4436 /********************************************************************
4437  ********************************************************************/
4438
4439 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4440                                                   const char **string_array,
4441                                                   const char *cservername)
4442 {
4443         int i, num_strings = 0;
4444         const char **array = NULL;
4445
4446         if (!string_array) {
4447                 return NULL;
4448         }
4449
4450         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4451
4452                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4453                                                   cservername, string_array[i]);
4454                 if (!str) {
4455                         TALLOC_FREE(array);
4456                         return NULL;
4457                 }
4458
4459
4460                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4461                         TALLOC_FREE(array);
4462                         return NULL;
4463                 }
4464         }
4465
4466         if (i > 0) {
4467                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4468                              &array, &num_strings);
4469         }
4470
4471         return array;
4472 }
4473
4474 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4475         do { \
4476                 if (in && strlen(in)) { \
4477                         out = talloc_strdup(mem_ctx, in); \
4478                         W_ERROR_HAVE_NO_MEMORY(out); \
4479                 } else { \
4480                         out = NULL; \
4481                 } \
4482         } while (0);
4483
4484 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4485         do { \
4486                 if (in && strlen(in)) { \
4487                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4488                 } else { \
4489                         out = talloc_strdup(mem_ctx, ""); \
4490                 } \
4491                 W_ERROR_HAVE_NO_MEMORY(out); \
4492         } while (0);
4493
4494 /********************************************************************
4495  * fill a spoolss_DriverInfo1 struct
4496  ********************************************************************/
4497
4498 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4499                                         struct spoolss_DriverInfo1 *r,
4500                                         const struct spoolss_DriverInfo8 *driver,
4501                                         const char *servername)
4502 {
4503         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4504         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4505
4506         return WERR_OK;
4507 }
4508
4509 /********************************************************************
4510  * fill a spoolss_DriverInfo2 struct
4511  ********************************************************************/
4512
4513 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4514                                         struct spoolss_DriverInfo2 *r,
4515                                         const struct spoolss_DriverInfo8 *driver,
4516                                         const char *servername)
4517
4518 {
4519         const char *cservername = canon_servername(servername);
4520
4521         r->version              = driver->version;
4522
4523         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4524         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4525         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4526         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4527
4528         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4529                                driver->driver_path,
4530                                r->driver_path);
4531
4532         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4533                                driver->data_file,
4534                                r->data_file);
4535
4536         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4537                                driver->config_file,
4538                                r->config_file);
4539
4540         return WERR_OK;
4541 }
4542
4543 /********************************************************************
4544  * fill a spoolss_DriverInfo3 struct
4545  ********************************************************************/
4546
4547 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4548                                         struct spoolss_DriverInfo3 *r,
4549                                         const struct spoolss_DriverInfo8 *driver,
4550                                         const char *servername)
4551 {
4552         const char *cservername = canon_servername(servername);
4553
4554         r->version              = driver->version;
4555
4556         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4557         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4558         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4559         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4560
4561         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4562                                driver->driver_path,
4563                                r->driver_path);
4564
4565         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4566                                driver->data_file,
4567                                r->data_file);
4568
4569         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4570                                driver->config_file,
4571                                r->config_file);
4572
4573         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4574                                driver->help_file,
4575                                r->help_file);
4576
4577         FILL_DRIVER_STRING(mem_ctx,
4578                            driver->monitor_name,
4579                            r->monitor_name);
4580
4581         FILL_DRIVER_STRING(mem_ctx,
4582                            driver->default_datatype,
4583                            r->default_datatype);
4584
4585         r->dependent_files = string_array_from_driver_info(mem_ctx,
4586                                                            driver->dependent_files,
4587                                                            cservername);
4588         return WERR_OK;
4589 }
4590
4591 /********************************************************************
4592  * fill a spoolss_DriverInfo4 struct
4593  ********************************************************************/
4594
4595 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4596                                         struct spoolss_DriverInfo4 *r,
4597                                         const struct spoolss_DriverInfo8 *driver,
4598                                         const char *servername)
4599 {
4600         const char *cservername = canon_servername(servername);
4601
4602         r->version              = driver->version;
4603
4604         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4605         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4606         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4607         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4608
4609         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4610                                driver->driver_path,
4611                                r->driver_path);
4612
4613         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4614                                driver->data_file,
4615                                r->data_file);
4616
4617         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4618                                driver->config_file,
4619                                r->config_file);
4620
4621         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4622                                driver->help_file,
4623                                r->help_file);
4624
4625         r->dependent_files = string_array_from_driver_info(mem_ctx,
4626                                                            driver->dependent_files,
4627                                                            cservername);
4628
4629         FILL_DRIVER_STRING(mem_ctx,
4630                            driver->monitor_name,
4631                            r->monitor_name);
4632
4633         FILL_DRIVER_STRING(mem_ctx,
4634                            driver->default_datatype,
4635                            r->default_datatype);
4636
4637         r->previous_names = string_array_from_driver_info(mem_ctx,
4638                                                           driver->previous_names,
4639                                                           cservername);
4640
4641         return WERR_OK;
4642 }
4643
4644 /********************************************************************
4645  * fill a spoolss_DriverInfo5 struct
4646  ********************************************************************/
4647
4648 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4649                                         struct spoolss_DriverInfo5 *r,
4650                                         const struct spoolss_DriverInfo8 *driver,
4651                                         const char *servername)
4652 {
4653         const char *cservername = canon_servername(servername);
4654
4655         r->version              = driver->version;
4656
4657         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4658         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4659         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4660         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4661
4662         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4663                                driver->driver_path,
4664                                r->driver_path);
4665
4666         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4667                                driver->data_file,
4668                                r->data_file);
4669
4670         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4671                                driver->config_file,
4672                                r->config_file);
4673
4674         r->driver_attributes    = 0;
4675         r->config_version       = 0;
4676         r->driver_version       = 0;
4677
4678         return WERR_OK;
4679 }
4680 /********************************************************************
4681  * fill a spoolss_DriverInfo6 struct
4682  ********************************************************************/
4683
4684 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4685                                         struct spoolss_DriverInfo6 *r,
4686                                         const struct spoolss_DriverInfo8 *driver,
4687                                         const char *servername)
4688 {
4689         const char *cservername = canon_servername(servername);
4690
4691         r->version              = driver->version;
4692
4693         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4694         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4695         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4696         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4697
4698         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4699                                driver->driver_path,
4700                                r->driver_path);
4701
4702         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4703                                driver->data_file,
4704                                r->data_file);
4705
4706         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4707                                driver->config_file,
4708                                r->config_file);
4709
4710         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4711                                driver->help_file,
4712                                r->help_file);
4713
4714         FILL_DRIVER_STRING(mem_ctx,
4715                            driver->monitor_name,
4716                            r->monitor_name);
4717
4718         FILL_DRIVER_STRING(mem_ctx,
4719                            driver->default_datatype,
4720                            r->default_datatype);
4721
4722         r->dependent_files = string_array_from_driver_info(mem_ctx,
4723                                                            driver->dependent_files,
4724                                                            cservername);
4725         r->previous_names = string_array_from_driver_info(mem_ctx,
4726                                                           driver->previous_names,
4727                                                           cservername);
4728
4729         r->driver_date          = driver->driver_date;
4730         r->driver_version       = driver->driver_version;
4731
4732         FILL_DRIVER_STRING(mem_ctx,
4733                            driver->manufacturer_name,
4734                            r->manufacturer_name);
4735         FILL_DRIVER_STRING(mem_ctx,
4736                            driver->manufacturer_url,
4737                            r->manufacturer_url);
4738         FILL_DRIVER_STRING(mem_ctx,
4739                            driver->hardware_id,
4740                            r->hardware_id);
4741         FILL_DRIVER_STRING(mem_ctx,
4742                            driver->provider,
4743                            r->provider);
4744
4745         return WERR_OK;
4746 }
4747
4748 /********************************************************************
4749  * fill a spoolss_DriverInfo8 struct
4750  ********************************************************************/
4751
4752 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4753                                         struct spoolss_DriverInfo8 *r,
4754                                         const struct spoolss_DriverInfo8 *driver,
4755                                         const char *servername)
4756 {
4757         const char *cservername = canon_servername(servername);
4758
4759         r->version              = driver->version;
4760
4761         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4762         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4763         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4764         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4765
4766         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4767                                driver->driver_path,
4768                                r->driver_path);
4769
4770         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4771                                driver->data_file,
4772                                r->data_file);
4773
4774         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4775                                driver->config_file,
4776                                r->config_file);
4777
4778         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4779                                driver->help_file,
4780                                r->help_file);
4781
4782         FILL_DRIVER_STRING(mem_ctx,
4783                            driver->monitor_name,
4784                            r->monitor_name);
4785
4786         FILL_DRIVER_STRING(mem_ctx,
4787                            driver->default_datatype,
4788                            r->default_datatype);
4789
4790         r->dependent_files = string_array_from_driver_info(mem_ctx,
4791                                                            driver->dependent_files,
4792                                                            cservername);
4793         r->previous_names = string_array_from_driver_info(mem_ctx,
4794                                                           driver->previous_names,
4795                                                           cservername);
4796
4797         r->driver_date          = driver->driver_date;
4798         r->driver_version       = driver->driver_version;
4799
4800         FILL_DRIVER_STRING(mem_ctx,
4801                            driver->manufacturer_name,
4802                            r->manufacturer_name);
4803         FILL_DRIVER_STRING(mem_ctx,
4804                            driver->manufacturer_url,
4805                            r->manufacturer_url);
4806         FILL_DRIVER_STRING(mem_ctx,
4807                            driver->hardware_id,
4808                            r->hardware_id);
4809         FILL_DRIVER_STRING(mem_ctx,
4810                            driver->provider,
4811                            r->provider);
4812
4813         FILL_DRIVER_STRING(mem_ctx,
4814                            driver->print_processor,
4815                            r->print_processor);
4816         FILL_DRIVER_STRING(mem_ctx,
4817                            driver->vendor_setup,
4818                            r->vendor_setup);
4819
4820         r->color_profiles = string_array_from_driver_info(mem_ctx,
4821                                                           driver->color_profiles,
4822                                                           cservername);
4823
4824         FILL_DRIVER_STRING(mem_ctx,
4825                            driver->inf_path,
4826                            r->inf_path);
4827
4828         r->printer_driver_attributes    = driver->printer_driver_attributes;
4829
4830         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4831                                                                     driver->core_driver_dependencies,
4832                                                                     cservername);
4833
4834         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4835         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4836
4837         return WERR_OK;
4838 }
4839 /********************************************************************
4840  ********************************************************************/
4841
4842 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4843                                           struct spoolss_DriverFileInfo *r,
4844                                           const char *cservername,
4845                                           const char *file_name,
4846                                           enum spoolss_DriverFileType file_type,
4847                                           uint32_t file_version)
4848 {
4849         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4850                                           cservername, file_name);
4851         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4852         r->file_type    = file_type;
4853         r->file_version = file_version;
4854
4855         return WERR_OK;
4856 }
4857
4858 /********************************************************************
4859  ********************************************************************/
4860
4861 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4862                                                  const struct spoolss_DriverInfo8 *driver,
4863                                                  const char *cservername,
4864                                                  struct spoolss_DriverFileInfo **info_p,
4865                                                  uint32_t *count_p)
4866 {
4867         struct spoolss_DriverFileInfo *info = NULL;
4868         uint32_t count = 0;
4869         WERROR result;
4870         uint32_t i;
4871
4872         *info_p = NULL;
4873         *count_p = 0;
4874
4875         if (strlen(driver->driver_path)) {
4876                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4877                                             struct spoolss_DriverFileInfo,
4878                                             count + 1);
4879                 W_ERROR_HAVE_NO_MEMORY(info);
4880                 result = fill_spoolss_DriverFileInfo(info,
4881                                                      &info[count],
4882                                                      cservername,
4883                                                      driver->driver_path,
4884                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4885                                                      0);
4886                 W_ERROR_NOT_OK_RETURN(result);
4887                 count++;
4888         }
4889
4890         if (strlen(driver->config_file)) {
4891                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4892                                             struct spoolss_DriverFileInfo,
4893                                             count + 1);
4894                 W_ERROR_HAVE_NO_MEMORY(info);
4895                 result = fill_spoolss_DriverFileInfo(info,
4896                                                      &info[count],
4897                                                      cservername,
4898                                                      driver->config_file,
4899                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4900                                                      0);
4901                 W_ERROR_NOT_OK_RETURN(result);
4902                 count++;
4903         }
4904
4905         if (strlen(driver->data_file)) {
4906                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4907                                             struct spoolss_DriverFileInfo,
4908                                             count + 1);
4909                 W_ERROR_HAVE_NO_MEMORY(info);
4910                 result = fill_spoolss_DriverFileInfo(info,
4911                                                      &info[count],
4912                                                      cservername,
4913                                                      driver->data_file,
4914                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4915                                                      0);
4916                 W_ERROR_NOT_OK_RETURN(result);
4917                 count++;
4918         }
4919
4920         if (strlen(driver->help_file)) {
4921                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4922                                             struct spoolss_DriverFileInfo,
4923                                             count + 1);
4924                 W_ERROR_HAVE_NO_MEMORY(info);
4925                 result = fill_spoolss_DriverFileInfo(info,
4926                                                      &info[count],
4927                                                      cservername,
4928                                                      driver->help_file,
4929                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4930                                                      0);
4931                 W_ERROR_NOT_OK_RETURN(result);
4932                 count++;
4933         }
4934
4935         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4936                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4937                                             struct spoolss_DriverFileInfo,
4938                                             count + 1);
4939                 W_ERROR_HAVE_NO_MEMORY(info);
4940                 result = fill_spoolss_DriverFileInfo(info,
4941                                                      &info[count],
4942                                                      cservername,
4943                                                      driver->dependent_files[i],
4944                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4945                                                      0);
4946                 W_ERROR_NOT_OK_RETURN(result);
4947                 count++;
4948         }
4949
4950         *info_p = info;
4951         *count_p = count;
4952
4953         return WERR_OK;
4954 }
4955
4956 /********************************************************************
4957  * fill a spoolss_DriverInfo101 sttruct
4958  ********************************************************************/
4959
4960 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4961                                           struct spoolss_DriverInfo101 *r,
4962                                           const struct spoolss_DriverInfo8 *driver,
4963                                           const char *servername)
4964 {
4965         const char *cservername = canon_servername(servername);
4966         WERROR result;
4967
4968         r->version              = driver->version;
4969
4970         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4971         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4972         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4973         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4974
4975         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4976                                                     cservername,
4977                                                     &r->file_info,
4978                                                     &r->file_count);
4979         if (!W_ERROR_IS_OK(result)) {
4980                 return result;
4981         }
4982
4983         FILL_DRIVER_STRING(mem_ctx,
4984                            driver->monitor_name,
4985                            r->monitor_name);
4986
4987         FILL_DRIVER_STRING(mem_ctx,
4988                            driver->default_datatype,
4989                            r->default_datatype);
4990
4991         r->previous_names = string_array_from_driver_info(mem_ctx,
4992                                                           driver->previous_names,
4993                                                           cservername);
4994         r->driver_date          = driver->driver_date;
4995         r->driver_version       = driver->driver_version;
4996
4997         FILL_DRIVER_STRING(mem_ctx,
4998                            driver->manufacturer_name,
4999                            r->manufacturer_name);
5000         FILL_DRIVER_STRING(mem_ctx,
5001                            driver->manufacturer_url,
5002                            r->manufacturer_url);
5003         FILL_DRIVER_STRING(mem_ctx,
5004                            driver->hardware_id,
5005                            r->hardware_id);
5006         FILL_DRIVER_STRING(mem_ctx,
5007                            driver->provider,
5008                            r->provider);
5009
5010         return WERR_OK;
5011 }
5012
5013 /********************************************************************
5014  ********************************************************************/
5015
5016 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5017                                                   uint32_t level,
5018                                                   union spoolss_DriverInfo *r,
5019                                                   int snum,
5020                                                   const char *servername,
5021                                                   const char *architecture,
5022                                                   uint32_t version)
5023 {
5024         NT_PRINTER_INFO_LEVEL *printer = NULL;
5025         struct spoolss_DriverInfo8 *driver;
5026         WERROR result;
5027
5028         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5029
5030         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5031                 win_errstr(result)));
5032
5033         if (!W_ERROR_IS_OK(result)) {
5034                 return WERR_INVALID_PRINTER_NAME;
5035         }
5036
5037         result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5038                                       architecture, version);
5039
5040         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5041                 win_errstr(result)));
5042
5043         if (!W_ERROR_IS_OK(result)) {
5044                 /*
5045                  * Is this a W2k client ?
5046                  */
5047
5048                 if (version < 3) {
5049                         free_a_printer(&printer, 2);
5050                         return WERR_UNKNOWN_PRINTER_DRIVER;
5051                 }
5052
5053                 /* Yes - try again with a WinNT driver. */
5054                 version = 2;
5055                 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
5056                                               architecture, version);
5057                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5058                         win_errstr(result)));
5059                 if (!W_ERROR_IS_OK(result)) {
5060                         free_a_printer(&printer, 2);
5061                         return WERR_UNKNOWN_PRINTER_DRIVER;
5062                 }
5063         }
5064
5065         switch (level) {
5066         case 1:
5067                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5068                 break;
5069         case 2:
5070                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5071                 break;
5072         case 3:
5073                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5074                 break;
5075         case 4:
5076                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5077                 break;
5078         case 5:
5079                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5080                 break;
5081         case 6:
5082                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5083                 break;
5084         case 8:
5085                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5086                 break;
5087         case 101:
5088                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5089                 break;
5090         default:
5091                 result = WERR_UNKNOWN_LEVEL;
5092                 break;
5093         }
5094
5095         free_a_printer(&printer, 2);
5096         free_a_printer_driver(driver);
5097
5098         return result;
5099 }
5100
5101 /****************************************************************
5102  _spoolss_GetPrinterDriver2
5103 ****************************************************************/
5104
5105 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5106                                   struct spoolss_GetPrinterDriver2 *r)
5107 {
5108         Printer_entry *printer;
5109         WERROR result;
5110
5111         const char *servername;
5112         int snum;
5113
5114         /* that's an [in out] buffer */
5115
5116         if (!r->in.buffer && (r->in.offered != 0)) {
5117                 return WERR_INVALID_PARAM;
5118         }
5119
5120         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5121
5122         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5123                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5124                 return WERR_INVALID_PRINTER_NAME;
5125         }
5126
5127         *r->out.needed = 0;
5128         *r->out.server_major_version = 0;
5129         *r->out.server_minor_version = 0;
5130
5131         servername = get_server_name(printer);
5132
5133         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5134                 return WERR_BADFID;
5135         }
5136
5137         result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
5138                                                      r->out.info, snum,
5139                                                      servername,
5140                                                      r->in.architecture,
5141                                                      r->in.client_major_version);
5142         if (!W_ERROR_IS_OK(result)) {
5143                 TALLOC_FREE(r->out.info);
5144                 return result;
5145         }
5146
5147         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5148                                                r->out.info, r->in.level);
5149         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5150
5151         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5152 }
5153
5154
5155 /****************************************************************
5156  _spoolss_StartPagePrinter
5157 ****************************************************************/
5158
5159 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5160                                  struct spoolss_StartPagePrinter *r)
5161 {
5162         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5163
5164         if (!Printer) {
5165                 DEBUG(3,("_spoolss_StartPagePrinter: "
5166                         "Error in startpageprinter printer handle\n"));
5167                 return WERR_BADFID;
5168         }
5169
5170         Printer->page_started = true;
5171         return WERR_OK;
5172 }
5173
5174 /****************************************************************
5175  _spoolss_EndPagePrinter
5176 ****************************************************************/
5177
5178 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5179                                struct spoolss_EndPagePrinter *r)
5180 {
5181         int snum;
5182
5183         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5184
5185         if (!Printer) {
5186                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5187                         OUR_HANDLE(r->in.handle)));
5188                 return WERR_BADFID;
5189         }
5190
5191         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5192                 return WERR_BADFID;
5193
5194         Printer->page_started = false;
5195         print_job_endpage(snum, Printer->jobid);
5196
5197         return WERR_OK;
5198 }
5199
5200 /****************************************************************
5201  _spoolss_StartDocPrinter
5202 ****************************************************************/
5203
5204 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5205                                 struct spoolss_StartDocPrinter *r)
5206 {
5207         struct spoolss_DocumentInfo1 *info_1;
5208         int snum;
5209         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5210
5211         if (!Printer) {
5212                 DEBUG(2,("_spoolss_StartDocPrinter: "
5213                         "Invalid handle (%s:%u:%u)\n",
5214                         OUR_HANDLE(r->in.handle)));
5215                 return WERR_BADFID;
5216         }
5217
5218         if (r->in.level != 1) {
5219                 return WERR_UNKNOWN_LEVEL;
5220         }
5221
5222         info_1 = r->in.info.info1;
5223
5224         /*
5225          * a nice thing with NT is it doesn't listen to what you tell it.
5226          * when asked to send _only_ RAW datas, it tries to send datas
5227          * in EMF format.
5228          *
5229          * So I add checks like in NT Server ...
5230          */
5231
5232         if (info_1->datatype) {
5233                 if (strcmp(info_1->datatype, "RAW") != 0) {
5234                         *r->out.job_id = 0;
5235                         return WERR_INVALID_DATATYPE;
5236                 }
5237         }
5238
5239         /* get the share number of the printer */
5240         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5241                 return WERR_BADFID;
5242         }
5243
5244         Printer->jobid = print_job_start(p->server_info, snum,
5245                                          info_1->document_name,
5246                                          Printer->nt_devmode);
5247
5248         /* An error occured in print_job_start() so return an appropriate
5249            NT error code. */
5250
5251         if (Printer->jobid == -1) {
5252                 return map_werror_from_unix(errno);
5253         }
5254
5255         Printer->document_started = true;
5256         *r->out.job_id = Printer->jobid;
5257
5258         return WERR_OK;
5259 }
5260
5261 /****************************************************************
5262  _spoolss_EndDocPrinter
5263 ****************************************************************/
5264
5265 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5266                               struct spoolss_EndDocPrinter *r)
5267 {
5268         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5269         int snum;
5270
5271         if (!Printer) {
5272                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5273                         OUR_HANDLE(r->in.handle)));
5274                 return WERR_BADFID;
5275         }
5276
5277         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5278                 return WERR_BADFID;
5279         }
5280
5281         Printer->document_started = false;
5282         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5283         /* error codes unhandled so far ... */
5284
5285         return WERR_OK;
5286 }
5287
5288 /****************************************************************
5289  _spoolss_WritePrinter
5290 ****************************************************************/
5291
5292 WERROR _spoolss_WritePrinter(pipes_struct *p,
5293                              struct spoolss_WritePrinter *r)
5294 {
5295         uint32_t buffer_written;
5296         int snum;
5297         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5298
5299         if (!Printer) {
5300                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5301                         OUR_HANDLE(r->in.handle)));
5302                 *r->out.num_written = r->in._data_size;
5303                 return WERR_BADFID;
5304         }
5305
5306         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5307                 return WERR_BADFID;
5308
5309         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5310                                                    (const char *)r->in.data.data,
5311                                                    (SMB_OFF_T)-1,
5312                                                    (size_t)r->in._data_size);
5313         if (buffer_written == (uint32_t)-1) {
5314                 *r->out.num_written = 0;
5315                 if (errno == ENOSPC)
5316                         return WERR_NO_SPOOL_SPACE;
5317                 else
5318                         return WERR_ACCESS_DENIED;
5319         }
5320
5321         *r->out.num_written = r->in._data_size;
5322
5323         return WERR_OK;
5324 }
5325
5326 /********************************************************************
5327  * api_spoolss_getprinter
5328  * called from the spoolss dispatcher
5329  *
5330  ********************************************************************/
5331
5332 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5333                               pipes_struct *p)
5334 {
5335         int snum;
5336         WERROR errcode = WERR_BADFUNC;
5337         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5338
5339         if (!Printer) {
5340                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5341                         OUR_HANDLE(handle)));
5342                 return WERR_BADFID;
5343         }
5344
5345         if (!get_printer_snum(p, handle, &snum, NULL))
5346                 return WERR_BADFID;
5347
5348         switch (command) {
5349         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5350                 errcode = print_queue_pause(p->server_info, snum);
5351                 break;
5352         case SPOOLSS_PRINTER_CONTROL_RESUME:
5353         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5354                 errcode = print_queue_resume(p->server_info, snum);
5355                 break;
5356         case SPOOLSS_PRINTER_CONTROL_PURGE:
5357                 errcode = print_queue_purge(p->server_info, snum);
5358                 break;
5359         default:
5360                 return WERR_UNKNOWN_LEVEL;
5361         }
5362
5363         return errcode;
5364 }
5365
5366
5367 /****************************************************************
5368  _spoolss_AbortPrinter
5369  * From MSDN: "Deletes printer's spool file if printer is configured
5370  * for spooling"
5371 ****************************************************************/
5372
5373 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5374                              struct spoolss_AbortPrinter *r)
5375 {
5376         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5377         int             snum;
5378         WERROR          errcode = WERR_OK;
5379
5380         if (!Printer) {
5381                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5382                         OUR_HANDLE(r->in.handle)));
5383                 return WERR_BADFID;
5384         }
5385
5386         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5387                 return WERR_BADFID;
5388
5389         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5390
5391         return errcode;
5392 }
5393
5394 /********************************************************************
5395  * called by spoolss_api_setprinter
5396  * when updating a printer description
5397  ********************************************************************/
5398
5399 static WERROR update_printer_sec(struct policy_handle *handle,
5400                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5401 {
5402         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5403         WERROR result;
5404         int snum;
5405
5406         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5407
5408         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5409                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5410                          OUR_HANDLE(handle)));
5411
5412                 result = WERR_BADFID;
5413                 goto done;
5414         }
5415
5416         if (!secdesc_ctr) {
5417                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5418                 result = WERR_INVALID_PARAM;
5419                 goto done;
5420         }
5421
5422         /* Check the user has permissions to change the security
5423            descriptor.  By experimentation with two NT machines, the user
5424            requires Full Access to the printer to change security
5425            information. */
5426
5427         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5428                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5429                 result = WERR_ACCESS_DENIED;
5430                 goto done;
5431         }
5432
5433         /* NT seems to like setting the security descriptor even though
5434            nothing may have actually changed. */
5435
5436         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5437                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5438                 result = WERR_BADFID;
5439                 goto done;
5440         }
5441
5442         if (DEBUGLEVEL >= 10) {
5443                 SEC_ACL *the_acl;
5444                 int i;
5445
5446                 the_acl = old_secdesc_ctr->sd->dacl;
5447                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5448                            PRINTERNAME(snum), the_acl->num_aces));
5449
5450                 for (i = 0; i < the_acl->num_aces; i++) {
5451                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5452                                            &the_acl->aces[i].trustee),
5453                                   the_acl->aces[i].access_mask));
5454                 }
5455
5456                 the_acl = secdesc_ctr->sd->dacl;
5457
5458                 if (the_acl) {
5459                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5460                                    PRINTERNAME(snum), the_acl->num_aces));
5461
5462                         for (i = 0; i < the_acl->num_aces; i++) {
5463                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5464                                                    &the_acl->aces[i].trustee),
5465                                            the_acl->aces[i].access_mask));
5466                         }
5467                 } else {
5468                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5469                 }
5470         }
5471
5472         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5473         if (!new_secdesc_ctr) {
5474                 result = WERR_NOMEM;
5475                 goto done;
5476         }
5477
5478         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5479                 result = WERR_OK;
5480                 goto done;
5481         }
5482
5483         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5484
5485  done:
5486
5487         return result;
5488 }
5489
5490 /********************************************************************
5491  Canonicalize printer info from a client
5492
5493  ATTN: It does not matter what we set the servername to hear
5494  since we do the necessary work in get_a_printer() to set it to
5495  the correct value based on what the client sent in the
5496  _spoolss_open_printer_ex().
5497  ********************************************************************/
5498
5499 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5500 {
5501         fstring printername;
5502         const char *p;
5503
5504         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5505                 "portname=%s drivername=%s comment=%s location=%s\n",
5506                 info->servername, info->printername, info->sharename,
5507                 info->portname, info->drivername, info->comment, info->location));
5508
5509         /* we force some elements to "correct" values */
5510         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5511         fstrcpy(info->sharename, lp_servicename(snum));
5512
5513         /* check to see if we allow printername != sharename */
5514
5515         if ( lp_force_printername(snum) ) {
5516                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5517                         global_myname(), info->sharename );
5518         } else {
5519
5520                 /* make sure printername is in \\server\printername format */
5521
5522                 fstrcpy( printername, info->printername );
5523                 p = printername;
5524                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5525                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5526                                 p++;
5527                 }
5528
5529                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5530                          global_myname(), p );
5531         }
5532
5533         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5534         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5535
5536
5537
5538         return true;
5539 }
5540
5541 /****************************************************************************
5542 ****************************************************************************/
5543
5544 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5545 {
5546         char *cmd = lp_addport_cmd();
5547         char *command = NULL;
5548         int ret;
5549         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5550         bool is_print_op = false;
5551
5552         if ( !*cmd ) {
5553                 return WERR_ACCESS_DENIED;
5554         }
5555
5556         command = talloc_asprintf(ctx,
5557                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5558         if (!command) {
5559                 return WERR_NOMEM;
5560         }
5561
5562         if ( token )
5563                 is_print_op = user_has_privileges( token, &se_printop );
5564
5565         DEBUG(10,("Running [%s]\n", command));
5566
5567         /********* BEGIN SePrintOperatorPrivilege **********/
5568
5569         if ( is_print_op )
5570                 become_root();
5571
5572         ret = smbrun(command, NULL);
5573
5574         if ( is_print_op )
5575                 unbecome_root();
5576
5577         /********* END SePrintOperatorPrivilege **********/
5578
5579         DEBUGADD(10,("returned [%d]\n", ret));
5580
5581         TALLOC_FREE(command);
5582
5583         if ( ret != 0 ) {
5584                 return WERR_ACCESS_DENIED;
5585         }
5586
5587         return WERR_OK;
5588 }
5589
5590 /****************************************************************************
5591 ****************************************************************************/
5592
5593 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5594 {
5595         char *cmd = lp_addprinter_cmd();
5596         char **qlines;
5597         char *command = NULL;
5598         int numlines;
5599         int ret;
5600         int fd;
5601         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5602         bool is_print_op = false;
5603         char *remote_machine = talloc_strdup(ctx, "%m");
5604
5605         if (!remote_machine) {
5606                 return false;
5607         }
5608         remote_machine = talloc_sub_basic(ctx,
5609                                 current_user_info.smb_name,
5610                                 current_user_info.domain,
5611                                 remote_machine);
5612         if (!remote_machine) {
5613                 return false;
5614         }
5615
5616         command = talloc_asprintf(ctx,
5617                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5618                         cmd, printer->info_2->printername, printer->info_2->sharename,
5619                         printer->info_2->portname, printer->info_2->drivername,
5620                         printer->info_2->location, printer->info_2->comment, remote_machine);
5621         if (!command) {
5622                 return false;
5623         }
5624
5625         if ( token )
5626                 is_print_op = user_has_privileges( token, &se_printop );
5627
5628         DEBUG(10,("Running [%s]\n", command));
5629
5630         /********* BEGIN SePrintOperatorPrivilege **********/
5631
5632         if ( is_print_op )
5633                 become_root();
5634
5635         if ( (ret = smbrun(command, &fd)) == 0 ) {
5636                 /* Tell everyone we updated smb.conf. */
5637                 message_send_all(smbd_messaging_context(),
5638                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5639         }
5640
5641         if ( is_print_op )
5642                 unbecome_root();
5643
5644         /********* END SePrintOperatorPrivilege **********/
5645
5646         DEBUGADD(10,("returned [%d]\n", ret));
5647
5648         TALLOC_FREE(command);
5649         TALLOC_FREE(remote_machine);
5650
5651         if ( ret != 0 ) {
5652                 if (fd != -1)
5653                         close(fd);
5654                 return false;
5655         }
5656
5657         /* reload our services immediately */
5658         become_root();
5659         reload_services(false);
5660         unbecome_root();
5661
5662         numlines = 0;
5663         /* Get lines and convert them back to dos-codepage */
5664         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5665         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5666         close(fd);
5667
5668         /* Set the portname to what the script says the portname should be. */
5669         /* but don't require anything to be return from the script exit a good error code */
5670
5671         if (numlines) {
5672                 /* Set the portname to what the script says the portname should be. */
5673                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5674                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5675         }
5676
5677         TALLOC_FREE(qlines);
5678         return true;
5679 }
5680
5681
5682 /********************************************************************
5683  * Called by spoolss_api_setprinter
5684  * when updating a printer description.
5685  ********************************************************************/
5686
5687 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5688                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5689                              struct spoolss_DeviceMode *devmode)
5690 {
5691         int snum;
5692         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5693         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5694         WERROR result;
5695         DATA_BLOB buffer;
5696         fstring asc_buffer;
5697
5698         DEBUG(8,("update_printer\n"));
5699
5700         result = WERR_OK;
5701
5702         if (!Printer) {
5703                 result = WERR_BADFID;
5704                 goto done;
5705         }
5706
5707         if (!get_printer_snum(p, handle, &snum, NULL)) {
5708                 result = WERR_BADFID;
5709                 goto done;
5710         }
5711
5712         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5713             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5714                 result = WERR_BADFID;
5715                 goto done;
5716         }
5717
5718         DEBUGADD(8,("Converting info_2 struct\n"));
5719
5720         /*
5721          * convert_printer_info converts the incoming
5722          * info from the client and overwrites the info
5723          * just read from the tdb in the pointer 'printer'.
5724          */
5725
5726         if (!convert_printer_info(info_ctr, printer)) {
5727                 result =  WERR_NOMEM;
5728                 goto done;
5729         }
5730
5731         if (devmode) {
5732                 /* we have a valid devmode
5733                    convert it and link it*/
5734
5735                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5736                 if (!convert_devicemode(printer->info_2->printername, devmode,
5737                                         &printer->info_2->devmode)) {
5738                         result =  WERR_NOMEM;
5739                         goto done;
5740                 }
5741         }
5742
5743         /* Do sanity check on the requested changes for Samba */
5744
5745         if (!check_printer_ok(printer->info_2, snum)) {
5746                 result = WERR_INVALID_PARAM;
5747                 goto done;
5748         }
5749
5750         /* FIXME!!! If the driver has changed we really should verify that
5751            it is installed before doing much else   --jerry */
5752
5753         /* Check calling user has permission to update printer description */
5754
5755         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5756                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5757                 result = WERR_ACCESS_DENIED;
5758                 goto done;
5759         }
5760
5761         /* Call addprinter hook */
5762         /* Check changes to see if this is really needed */
5763
5764         if ( *lp_addprinter_cmd()
5765                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5766                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5767                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5768                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5769         {
5770                 /* add_printer_hook() will call reload_services() */
5771
5772                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5773                                        printer) ) {
5774                         result = WERR_ACCESS_DENIED;
5775                         goto done;
5776                 }
5777         }
5778
5779         /*
5780          * When a *new* driver is bound to a printer, the drivername is used to
5781          * lookup previously saved driver initialization info, which is then
5782          * bound to the printer, simulating what happens in the Windows arch.
5783          */
5784         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5785         {
5786                 if (!set_driver_init(printer, 2))
5787                 {
5788                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5789                                 printer->info_2->drivername));
5790                 }
5791
5792                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5793                         printer->info_2->drivername));
5794
5795                 notify_printer_driver(snum, printer->info_2->drivername);
5796         }
5797
5798         /*
5799          * flag which changes actually occured.  This is a small subset of
5800          * all the possible changes.  We also have to update things in the
5801          * DsSpooler key.
5802          */
5803
5804         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5805                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5806                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5807                         REG_SZ, buffer.data, buffer.length);
5808
5809                 notify_printer_comment(snum, printer->info_2->comment);
5810         }
5811
5812         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5813                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5814                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5815                         REG_SZ, buffer.data, buffer.length);
5816
5817                 notify_printer_sharename(snum, printer->info_2->sharename);
5818         }
5819
5820         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5821                 char *pname;
5822
5823                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5824                         pname++;
5825                 else
5826                         pname = printer->info_2->printername;
5827
5828
5829                 push_reg_sz(talloc_tos(), &buffer, pname);
5830                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5831                         REG_SZ, buffer.data, buffer.length);
5832
5833                 notify_printer_printername( snum, pname );
5834         }
5835
5836         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5837                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5838                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5839                         REG_SZ, buffer.data, buffer.length);
5840
5841                 notify_printer_port(snum, printer->info_2->portname);
5842         }
5843
5844         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5845                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5846                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5847                         REG_SZ, buffer.data, buffer.length);
5848
5849                 notify_printer_location(snum, printer->info_2->location);
5850         }
5851
5852         /* here we need to update some more DsSpooler keys */
5853         /* uNCName, serverName, shortServerName */
5854
5855         push_reg_sz(talloc_tos(), &buffer, global_myname());
5856         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5857                 REG_SZ, buffer.data, buffer.length);
5858         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5859                 REG_SZ, buffer.data, buffer.length);
5860
5861         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5862                  global_myname(), printer->info_2->sharename );
5863         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5864         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5865                 REG_SZ, buffer.data, buffer.length);
5866
5867         /* Update printer info */
5868         result = mod_a_printer(printer, 2);
5869
5870 done:
5871         free_a_printer(&printer, 2);
5872         free_a_printer(&old_printer, 2);
5873
5874
5875         return result;
5876 }
5877
5878 /****************************************************************************
5879 ****************************************************************************/
5880 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5881                                            struct policy_handle *handle,
5882                                            struct spoolss_SetPrinterInfo7 *info7)
5883 {
5884 #ifdef HAVE_ADS
5885         int snum;
5886         Printer_entry *Printer;
5887
5888         if ( lp_security() != SEC_ADS ) {
5889                 return WERR_UNKNOWN_LEVEL;
5890         }
5891
5892         Printer = find_printer_index_by_hnd(p, handle);
5893
5894         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5895
5896         if (!Printer)
5897                 return WERR_BADFID;
5898
5899         if (!get_printer_snum(p, handle, &snum, NULL))
5900                 return WERR_BADFID;
5901
5902         nt_printer_publish(Printer, snum, info7->action);
5903
5904         return WERR_OK;
5905 #else
5906         return WERR_UNKNOWN_LEVEL;
5907 #endif
5908 }
5909
5910 /****************************************************************
5911  _spoolss_SetPrinter
5912 ****************************************************************/
5913
5914 WERROR _spoolss_SetPrinter(pipes_struct *p,
5915                            struct spoolss_SetPrinter *r)
5916 {
5917         WERROR result;
5918
5919         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5920
5921         if (!Printer) {
5922                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5923                         OUR_HANDLE(r->in.handle)));
5924                 return WERR_BADFID;
5925         }
5926
5927         /* check the level */
5928         switch (r->in.info_ctr->level) {
5929                 case 0:
5930                         return control_printer(r->in.handle, r->in.command, p);
5931                 case 2:
5932                         result = update_printer(p, r->in.handle,
5933                                                 r->in.info_ctr,
5934                                                 r->in.devmode_ctr->devmode);
5935                         if (!W_ERROR_IS_OK(result))
5936                                 return result;
5937                         if (r->in.secdesc_ctr->sd)
5938                                 result = update_printer_sec(r->in.handle, p,
5939                                                             r->in.secdesc_ctr);
5940                         return result;
5941                 case 3:
5942                         return update_printer_sec(r->in.handle, p,
5943                                                   r->in.secdesc_ctr);
5944                 case 7:
5945                         return publish_or_unpublish_printer(p, r->in.handle,
5946                                                             r->in.info_ctr->info.info7);
5947                 default:
5948                         return WERR_UNKNOWN_LEVEL;
5949         }
5950 }
5951
5952 /****************************************************************
5953  _spoolss_FindClosePrinterNotify
5954 ****************************************************************/
5955
5956 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5957                                        struct spoolss_FindClosePrinterNotify *r)
5958 {
5959         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5960
5961         if (!Printer) {
5962                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5963                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5964                 return WERR_BADFID;
5965         }
5966
5967         if (Printer->notify.client_connected == true) {
5968                 int snum = -1;
5969
5970                 if ( Printer->printer_type == SPLHND_SERVER)
5971                         snum = -1;
5972                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5973                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5974                         return WERR_BADFID;
5975
5976                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5977         }
5978
5979         Printer->notify.flags=0;
5980         Printer->notify.options=0;
5981         Printer->notify.localmachine[0]='\0';
5982         Printer->notify.printerlocal=0;
5983         TALLOC_FREE(Printer->notify.option);
5984         Printer->notify.client_connected = false;
5985
5986         return WERR_OK;
5987 }
5988
5989 /****************************************************************
5990  _spoolss_AddJob
5991 ****************************************************************/
5992
5993 WERROR _spoolss_AddJob(pipes_struct *p,
5994                        struct spoolss_AddJob *r)
5995 {
5996         if (!r->in.buffer && (r->in.offered != 0)) {
5997                 return WERR_INVALID_PARAM;
5998         }
5999
6000         /* this is what a NT server returns for AddJob. AddJob must fail on
6001          * non-local printers */
6002
6003         if (r->in.level != 1) {
6004                 return WERR_UNKNOWN_LEVEL;
6005         }
6006
6007         return WERR_INVALID_PARAM;
6008 }
6009
6010 /****************************************************************************
6011 fill_job_info1
6012 ****************************************************************************/
6013
6014 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6015                              struct spoolss_JobInfo1 *r,
6016                              const print_queue_struct *queue,
6017                              int position, int snum,
6018                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6019 {
6020         struct tm *t;
6021
6022         t = gmtime(&queue->time);
6023
6024         r->job_id               = queue->job;
6025
6026         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6027         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6028         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6029         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6030         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6031         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6032         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6033         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6034         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6035         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6036         r->text_status          = talloc_strdup(mem_ctx, "");
6037         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6038
6039         r->status               = nt_printj_status(queue->status);
6040         r->priority             = queue->priority;
6041         r->position             = position;
6042         r->total_pages          = queue->page_count;
6043         r->pages_printed        = 0; /* ??? */
6044
6045         init_systemtime(&r->submitted, t);
6046
6047         return WERR_OK;
6048 }
6049
6050 /****************************************************************************
6051 fill_job_info2
6052 ****************************************************************************/
6053
6054 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6055                              struct spoolss_JobInfo2 *r,
6056                              const print_queue_struct *queue,
6057                              int position, int snum,
6058                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6059                              struct spoolss_DeviceMode *devmode)
6060 {
6061         struct tm *t;
6062
6063         t = gmtime(&queue->time);
6064
6065         r->job_id               = queue->job;
6066
6067         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6068         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6069         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6070         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6071         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6072         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6073         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6074         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6075         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6076         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6077         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6078         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6079         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6080         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6081         r->parameters           = talloc_strdup(mem_ctx, "");
6082         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6083         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6084         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6085
6086         r->devmode              = devmode;
6087
6088         r->text_status          = talloc_strdup(mem_ctx, "");
6089         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6090
6091         r->secdesc              = NULL;
6092
6093         r->status               = nt_printj_status(queue->status);
6094         r->priority             = queue->priority;
6095         r->position             = position;
6096         r->start_time           = 0;
6097         r->until_time           = 0;
6098         r->total_pages          = queue->page_count;
6099         r->size                 = queue->size;
6100         init_systemtime(&r->submitted, t);
6101         r->time                 = 0;
6102         r->pages_printed        = 0; /* ??? */
6103
6104         return WERR_OK;
6105 }
6106
6107 /****************************************************************************
6108  Enumjobs at level 1.
6109 ****************************************************************************/
6110
6111 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6112                               const print_queue_struct *queue,
6113                               uint32_t num_queues, int snum,
6114                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6115                               union spoolss_JobInfo **info_p,
6116                               uint32_t *count)
6117 {
6118         union spoolss_JobInfo *info;
6119         int i;
6120         WERROR result = WERR_OK;
6121
6122         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6123         W_ERROR_HAVE_NO_MEMORY(info);
6124
6125         *count = num_queues;
6126
6127         for (i=0; i<*count; i++) {
6128                 result = fill_job_info1(info,
6129                                         &info[i].info1,
6130                                         &queue[i],
6131                                         i,
6132                                         snum,
6133                                         ntprinter);
6134                 if (!W_ERROR_IS_OK(result)) {
6135                         goto out;
6136                 }
6137         }
6138
6139  out:
6140         if (!W_ERROR_IS_OK(result)) {
6141                 TALLOC_FREE(info);
6142                 *count = 0;
6143                 return result;
6144         }
6145
6146         *info_p = info;
6147
6148         return WERR_OK;
6149 }
6150
6151 /****************************************************************************
6152  Enumjobs at level 2.
6153 ****************************************************************************/
6154
6155 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6156                               const print_queue_struct *queue,
6157                               uint32_t num_queues, int snum,
6158                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6159                               union spoolss_JobInfo **info_p,
6160                               uint32_t *count)
6161 {
6162         union spoolss_JobInfo *info;
6163         int i;
6164         WERROR result = WERR_OK;
6165
6166         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6167         W_ERROR_HAVE_NO_MEMORY(info);
6168
6169         *count = num_queues;
6170
6171         for (i=0; i<*count; i++) {
6172
6173                 struct spoolss_DeviceMode *devmode;
6174
6175                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6176                 if (!devmode) {
6177                         result = WERR_NOMEM;
6178                         goto out;
6179                 }
6180
6181                 result = fill_job_info2(info,
6182                                         &info[i].info2,
6183                                         &queue[i],
6184                                         i,
6185                                         snum,
6186                                         ntprinter,
6187                                         devmode);
6188                 if (!W_ERROR_IS_OK(result)) {
6189                         goto out;
6190                 }
6191         }
6192
6193  out:
6194         if (!W_ERROR_IS_OK(result)) {
6195                 TALLOC_FREE(info);
6196                 *count = 0;
6197                 return result;
6198         }
6199
6200         *info_p = info;
6201
6202         return WERR_OK;
6203 }
6204
6205 /****************************************************************
6206  _spoolss_EnumJobs
6207 ****************************************************************/
6208
6209 WERROR _spoolss_EnumJobs(pipes_struct *p,
6210                          struct spoolss_EnumJobs *r)
6211 {
6212         WERROR result;
6213         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6214         int snum;
6215         print_status_struct prt_status;
6216         print_queue_struct *queue = NULL;
6217         uint32_t count;
6218
6219         /* that's an [in out] buffer */
6220
6221         if (!r->in.buffer && (r->in.offered != 0)) {
6222                 return WERR_INVALID_PARAM;
6223         }
6224
6225         DEBUG(4,("_spoolss_EnumJobs\n"));
6226
6227         *r->out.needed = 0;
6228         *r->out.count = 0;
6229         *r->out.info = NULL;
6230
6231         /* lookup the printer snum and tdb entry */
6232
6233         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6234                 return WERR_BADFID;
6235         }
6236
6237         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6238         if (!W_ERROR_IS_OK(result)) {
6239                 return result;
6240         }
6241
6242         count = print_queue_status(snum, &queue, &prt_status);
6243         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6244                 count, prt_status.status, prt_status.message));
6245
6246         if (count == 0) {
6247                 SAFE_FREE(queue);
6248                 free_a_printer(&ntprinter, 2);
6249                 return WERR_OK;
6250         }
6251
6252         switch (r->in.level) {
6253         case 1:
6254                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6255                                          ntprinter, r->out.info, r->out.count);
6256                 break;
6257         case 2:
6258                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6259                                          ntprinter, r->out.info, r->out.count);
6260                 break;
6261         default:
6262                 result = WERR_UNKNOWN_LEVEL;
6263                 break;
6264         }
6265
6266         SAFE_FREE(queue);
6267         free_a_printer(&ntprinter, 2);
6268
6269         if (!W_ERROR_IS_OK(result)) {
6270                 return result;
6271         }
6272
6273         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6274                                                      spoolss_EnumJobs, NULL,
6275                                                      *r->out.info, r->in.level,
6276                                                      *r->out.count);
6277         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6278         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6279
6280         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6281 }
6282
6283 /****************************************************************
6284  _spoolss_ScheduleJob
6285 ****************************************************************/
6286
6287 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6288                             struct spoolss_ScheduleJob *r)
6289 {
6290         return WERR_OK;
6291 }
6292
6293 /****************************************************************
6294  _spoolss_SetJob
6295 ****************************************************************/
6296
6297 WERROR _spoolss_SetJob(pipes_struct *p,
6298                        struct spoolss_SetJob *r)
6299 {
6300         int snum;
6301         WERROR errcode = WERR_BADFUNC;
6302
6303         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6304                 return WERR_BADFID;
6305         }
6306
6307         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6308                 return WERR_INVALID_PRINTER_NAME;
6309         }
6310
6311         switch (r->in.command) {
6312         case SPOOLSS_JOB_CONTROL_CANCEL:
6313         case SPOOLSS_JOB_CONTROL_DELETE:
6314                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6315                         errcode = WERR_OK;
6316                 }
6317                 break;
6318         case SPOOLSS_JOB_CONTROL_PAUSE:
6319                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6320                         errcode = WERR_OK;
6321                 }
6322                 break;
6323         case SPOOLSS_JOB_CONTROL_RESTART:
6324         case SPOOLSS_JOB_CONTROL_RESUME:
6325                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6326                         errcode = WERR_OK;
6327                 }
6328                 break;
6329         default:
6330                 return WERR_UNKNOWN_LEVEL;
6331         }
6332
6333         return errcode;
6334 }
6335
6336 /****************************************************************************
6337  Enumerates all printer drivers by level and architecture.
6338 ****************************************************************************/
6339
6340 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6341                                                        const char *servername,
6342                                                        const char *architecture,
6343                                                        uint32_t level,
6344                                                        union spoolss_DriverInfo **info_p,
6345                                                        uint32_t *count_p)
6346 {
6347         int i;
6348         int ndrivers;
6349         uint32_t version;
6350         fstring *list = NULL;
6351         struct spoolss_DriverInfo8 *driver;
6352         union spoolss_DriverInfo *info = NULL;
6353         uint32_t count = 0;
6354         WERROR result = WERR_OK;
6355
6356         *count_p = 0;
6357         *info_p = NULL;
6358
6359         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6360                 list = NULL;
6361                 ndrivers = get_ntdrivers(&list, architecture, version);
6362                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6363                         ndrivers, architecture, version));
6364
6365                 if (ndrivers == -1) {
6366                         result = WERR_NOMEM;
6367                         goto out;
6368                 }
6369
6370                 if (ndrivers != 0) {
6371                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6372                                                     union spoolss_DriverInfo,
6373                                                     count + ndrivers);
6374                         if (!info) {
6375                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6376                                         "failed to enlarge driver info buffer!\n"));
6377                                 result = WERR_NOMEM;
6378                                 goto out;
6379                         }
6380                 }
6381
6382                 for (i=0; i<ndrivers; i++) {
6383                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6384                         ZERO_STRUCT(driver);
6385                         result = get_a_printer_driver(mem_ctx, &driver, list[i],
6386                                                       architecture, version);
6387                         if (!W_ERROR_IS_OK(result)) {
6388                                 goto out;
6389                         }
6390
6391                         switch (level) {
6392                         case 1:
6393                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6394                                                                    driver, servername);
6395                                 break;
6396                         case 2:
6397                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6398                                                                    driver, servername);
6399                                 break;
6400                         case 3:
6401                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6402                                                                    driver, servername);
6403                                 break;
6404                         case 4:
6405                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6406                                                                    driver, servername);
6407                                 break;
6408                         case 5:
6409                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6410                                                                    driver, servername);
6411                                 break;
6412                         case 6:
6413                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6414                                                                    driver, servername);
6415                                 break;
6416                         case 8:
6417                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6418                                                                    driver, servername);
6419                                 break;
6420                         default:
6421                                 result = WERR_UNKNOWN_LEVEL;
6422                                 break;
6423                         }
6424
6425                         free_a_printer_driver(driver);
6426
6427                         if (!W_ERROR_IS_OK(result)) {
6428                                 goto out;
6429                         }
6430                 }
6431
6432                 count += ndrivers;
6433                 SAFE_FREE(list);
6434         }
6435
6436  out:
6437         SAFE_FREE(list);
6438
6439         if (!W_ERROR_IS_OK(result)) {
6440                 TALLOC_FREE(info);
6441                 return result;
6442         }
6443
6444         *info_p = info;
6445         *count_p = count;
6446
6447         return WERR_OK;
6448 }
6449
6450 /****************************************************************************
6451  Enumerates all printer drivers by level.
6452 ****************************************************************************/
6453
6454 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6455                                        const char *servername,
6456                                        const char *architecture,
6457                                        uint32_t level,
6458                                        union spoolss_DriverInfo **info_p,
6459                                        uint32_t *count_p)
6460 {
6461         uint32_t a,i;
6462         WERROR result = WERR_OK;
6463
6464         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6465
6466                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6467
6468                         union spoolss_DriverInfo *info = NULL;
6469                         uint32_t count = 0;
6470
6471                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6472                                                                           servername,
6473                                                                           archi_table[a].long_archi,
6474                                                                           level,
6475                                                                           &info,
6476                                                                           &count);
6477                         if (!W_ERROR_IS_OK(result)) {
6478                                 continue;
6479                         }
6480
6481                         for (i=0; i < count; i++) {
6482                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6483                                              info[i], info_p, count_p);
6484                         }
6485                 }
6486
6487                 return result;
6488         }
6489
6490         return enumprinterdrivers_level_by_architecture(mem_ctx,
6491                                                         servername,
6492                                                         architecture,
6493                                                         level,
6494                                                         info_p,
6495                                                         count_p);
6496 }
6497
6498 /****************************************************************
6499  _spoolss_EnumPrinterDrivers
6500 ****************************************************************/
6501
6502 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6503                                    struct spoolss_EnumPrinterDrivers *r)
6504 {
6505         const char *cservername;
6506         WERROR result;
6507
6508         /* that's an [in out] buffer */
6509
6510         if (!r->in.buffer && (r->in.offered != 0)) {
6511                 return WERR_INVALID_PARAM;
6512         }
6513
6514         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6515
6516         *r->out.needed = 0;
6517         *r->out.count = 0;
6518         *r->out.info = NULL;
6519
6520         cservername = canon_servername(r->in.server);
6521
6522         if (!is_myname_or_ipaddr(cservername)) {
6523                 return WERR_UNKNOWN_PRINTER_DRIVER;
6524         }
6525
6526         result = enumprinterdrivers_level(p->mem_ctx, cservername,
6527                                           r->in.environment,
6528                                           r->in.level,
6529                                           r->out.info,
6530                                           r->out.count);
6531         if (!W_ERROR_IS_OK(result)) {
6532                 return result;
6533         }
6534
6535         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6536                                                      spoolss_EnumPrinterDrivers, NULL,
6537                                                      *r->out.info, r->in.level,
6538                                                      *r->out.count);
6539         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6540         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6541
6542         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6543 }
6544
6545 /****************************************************************************
6546 ****************************************************************************/
6547
6548 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6549                                struct spoolss_FormInfo1 *r,
6550                                const nt_forms_struct *form)
6551 {
6552         r->form_name    = talloc_strdup(mem_ctx, form->name);
6553         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6554
6555         r->flags        = form->flag;
6556         r->size.width   = form->width;
6557         r->size.height  = form->length;
6558         r->area.left    = form->left;
6559         r->area.top     = form->top;
6560         r->area.right   = form->right;
6561         r->area.bottom  = form->bottom;
6562
6563         return WERR_OK;
6564 }
6565
6566 /****************************************************************
6567  spoolss_enumforms_level1
6568 ****************************************************************/
6569
6570 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6571                                        const nt_forms_struct *builtin_forms,
6572                                        uint32_t num_builtin_forms,
6573                                        const nt_forms_struct *user_forms,
6574                                        uint32_t num_user_forms,
6575                                        union spoolss_FormInfo **info_p,
6576                                        uint32_t *count)
6577 {
6578         union spoolss_FormInfo *info;
6579         WERROR result = WERR_OK;
6580         int i;
6581
6582         *count = num_builtin_forms + num_user_forms;
6583
6584         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6585         W_ERROR_HAVE_NO_MEMORY(info);
6586
6587         /* construct the list of form structures */
6588         for (i=0; i<num_builtin_forms; i++) {
6589                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6590                 result = fill_form_info_1(info, &info[i].info1,
6591                                           &builtin_forms[i]);
6592                 if (!W_ERROR_IS_OK(result)) {
6593                         goto out;
6594                 }
6595         }
6596
6597         for (i=0; i<num_user_forms; i++) {
6598                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6599                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6600                                           &user_forms[i]);
6601                 if (!W_ERROR_IS_OK(result)) {
6602                         goto out;
6603                 }
6604         }
6605
6606  out:
6607         if (!W_ERROR_IS_OK(result)) {
6608                 TALLOC_FREE(info);
6609                 *count = 0;
6610                 return result;
6611         }
6612
6613         *info_p = info;
6614
6615         return WERR_OK;
6616 }
6617
6618 /****************************************************************
6619  _spoolss_EnumForms
6620 ****************************************************************/
6621
6622 WERROR _spoolss_EnumForms(pipes_struct *p,
6623                           struct spoolss_EnumForms *r)
6624 {
6625         WERROR result;
6626         nt_forms_struct *user_forms = NULL;
6627         nt_forms_struct *builtin_forms = NULL;
6628         uint32_t num_user_forms;
6629         uint32_t num_builtin_forms;
6630
6631         *r->out.count = 0;
6632         *r->out.needed = 0;
6633         *r->out.info = NULL;
6634
6635         /* that's an [in out] buffer */
6636
6637         if (!r->in.buffer && (r->in.offered != 0) ) {
6638                 return WERR_INVALID_PARAM;
6639         }
6640
6641         DEBUG(4,("_spoolss_EnumForms\n"));
6642         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6643         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6644
6645         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6646         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6647         num_user_forms = get_ntforms(&user_forms);
6648         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6649
6650         if (num_user_forms + num_builtin_forms == 0) {
6651                 SAFE_FREE(builtin_forms);
6652                 SAFE_FREE(user_forms);
6653                 return WERR_NO_MORE_ITEMS;
6654         }
6655
6656         switch (r->in.level) {
6657         case 1:
6658                 result = spoolss_enumforms_level1(p->mem_ctx,
6659                                                   builtin_forms,
6660                                                   num_builtin_forms,
6661                                                   user_forms,
6662                                                   num_user_forms,
6663                                                   r->out.info,
6664                                                   r->out.count);
6665                 break;
6666         default:
6667                 result = WERR_UNKNOWN_LEVEL;
6668                 break;
6669         }
6670
6671         SAFE_FREE(user_forms);
6672         SAFE_FREE(builtin_forms);
6673
6674         if (!W_ERROR_IS_OK(result)) {
6675                 return result;
6676         }
6677
6678         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6679                                                      spoolss_EnumForms, NULL,
6680                                                      *r->out.info, r->in.level,
6681                                                      *r->out.count);
6682         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6683         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6684
6685         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6686 }
6687
6688 /****************************************************************
6689 ****************************************************************/
6690
6691 static WERROR find_form_byname(const char *name,
6692                                nt_forms_struct *form)
6693 {
6694         nt_forms_struct *list = NULL;
6695         int num_forms = 0, i = 0;
6696
6697         if (get_a_builtin_ntform_by_string(name, form)) {
6698                 return WERR_OK;
6699         }
6700
6701         num_forms = get_ntforms(&list);
6702         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6703
6704         if (num_forms == 0) {
6705                 return WERR_BADFID;
6706         }
6707
6708         /* Check if the requested name is in the list of form structures */
6709         for (i = 0; i < num_forms; i++) {
6710
6711                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6712
6713                 if (strequal(name, list[i].name)) {
6714                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6715                         *form = list[i];
6716                         SAFE_FREE(list);
6717                         return WERR_OK;
6718                 }
6719         }
6720
6721         SAFE_FREE(list);
6722
6723         return WERR_BADFID;
6724 }
6725
6726 /****************************************************************
6727  _spoolss_GetForm
6728 ****************************************************************/
6729
6730 WERROR _spoolss_GetForm(pipes_struct *p,
6731                         struct spoolss_GetForm *r)
6732 {
6733         WERROR result;
6734         nt_forms_struct form;
6735
6736         /* that's an [in out] buffer */
6737
6738         if (!r->in.buffer && (r->in.offered != 0)) {
6739                 return WERR_INVALID_PARAM;
6740         }
6741
6742         DEBUG(4,("_spoolss_GetForm\n"));
6743         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6744         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6745
6746         result = find_form_byname(r->in.form_name, &form);
6747         if (!W_ERROR_IS_OK(result)) {
6748                 TALLOC_FREE(r->out.info);
6749                 return result;
6750         }
6751
6752         switch (r->in.level) {
6753         case 1:
6754                 result = fill_form_info_1(p->mem_ctx,
6755                                           &r->out.info->info1,
6756                                           &form);
6757                 break;
6758
6759         default:
6760                 result = WERR_UNKNOWN_LEVEL;
6761                 break;
6762         }
6763
6764         if (!W_ERROR_IS_OK(result)) {
6765                 TALLOC_FREE(r->out.info);
6766                 return result;
6767         }
6768
6769         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6770                                                r->out.info, r->in.level);
6771         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6772
6773         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6774 }
6775
6776 /****************************************************************************
6777 ****************************************************************************/
6778
6779 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6780                           struct spoolss_PortInfo1 *r,
6781                           const char *name)
6782 {
6783         r->port_name = talloc_strdup(mem_ctx, name);
6784         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6785
6786         return WERR_OK;
6787 }
6788
6789 /****************************************************************************
6790  TODO: This probably needs distinguish between TCP/IP and Local ports
6791  somehow.
6792 ****************************************************************************/
6793
6794 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6795                           struct spoolss_PortInfo2 *r,
6796                           const char *name)
6797 {
6798         r->port_name = talloc_strdup(mem_ctx, name);
6799         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6800
6801         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6802         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6803
6804         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6805         W_ERROR_HAVE_NO_MEMORY(r->description);
6806
6807         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6808         r->reserved = 0;
6809
6810         return WERR_OK;
6811 }
6812
6813
6814 /****************************************************************************
6815  wrapper around the enumer ports command
6816 ****************************************************************************/
6817
6818 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6819 {
6820         char *cmd = lp_enumports_cmd();
6821         char **qlines = NULL;
6822         char *command = NULL;
6823         int numlines;
6824         int ret;
6825         int fd;
6826
6827         *count = 0;
6828         *lines = NULL;
6829
6830         /* if no hook then just fill in the default port */
6831
6832         if ( !*cmd ) {
6833                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6834                         return WERR_NOMEM;
6835                 }
6836                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6837                         TALLOC_FREE(qlines);
6838                         return WERR_NOMEM;
6839                 }
6840                 qlines[1] = NULL;
6841                 numlines = 1;
6842         }
6843         else {
6844                 /* we have a valid enumport command */
6845
6846                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6847                 if (!command) {
6848                         return WERR_NOMEM;
6849                 }
6850
6851                 DEBUG(10,("Running [%s]\n", command));
6852                 ret = smbrun(command, &fd);
6853                 DEBUG(10,("Returned [%d]\n", ret));
6854                 TALLOC_FREE(command);
6855                 if (ret != 0) {
6856                         if (fd != -1) {
6857                                 close(fd);
6858                         }
6859                         return WERR_ACCESS_DENIED;
6860                 }
6861
6862                 numlines = 0;
6863                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6864                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6865                 close(fd);
6866         }
6867
6868         *count = numlines;
6869         *lines = qlines;
6870
6871         return WERR_OK;
6872 }
6873
6874 /****************************************************************************
6875  enumports level 1.
6876 ****************************************************************************/
6877
6878 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6879                                 union spoolss_PortInfo **info_p,
6880                                 uint32_t *count)
6881 {
6882         union spoolss_PortInfo *info = NULL;
6883         int i=0;
6884         WERROR result = WERR_OK;
6885         char **qlines = NULL;
6886         int numlines = 0;
6887
6888         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6889         if (!W_ERROR_IS_OK(result)) {
6890                 goto out;
6891         }
6892
6893         if (numlines) {
6894                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6895                 if (!info) {
6896                         DEBUG(10,("Returning WERR_NOMEM\n"));
6897                         result = WERR_NOMEM;
6898                         goto out;
6899                 }
6900
6901                 for (i=0; i<numlines; i++) {
6902                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6903                         result = fill_port_1(info, &info[i].info1, qlines[i]);
6904                         if (!W_ERROR_IS_OK(result)) {
6905                                 goto out;
6906                         }
6907                 }
6908         }
6909         TALLOC_FREE(qlines);
6910
6911 out:
6912         if (!W_ERROR_IS_OK(result)) {
6913                 TALLOC_FREE(info);
6914                 TALLOC_FREE(qlines);
6915                 *count = 0;
6916                 *info_p = NULL;
6917                 return result;
6918         }
6919
6920         *info_p = info;
6921         *count = numlines;
6922
6923         return WERR_OK;
6924 }
6925
6926 /****************************************************************************
6927  enumports level 2.
6928 ****************************************************************************/
6929
6930 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6931                                 union spoolss_PortInfo **info_p,
6932                                 uint32_t *count)
6933 {
6934         union spoolss_PortInfo *info = NULL;
6935         int i=0;
6936         WERROR result = WERR_OK;
6937         char **qlines = NULL;
6938         int numlines = 0;
6939
6940         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6941         if (!W_ERROR_IS_OK(result)) {
6942                 goto out;
6943         }
6944
6945         if (numlines) {
6946                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6947                 if (!info) {
6948                         DEBUG(10,("Returning WERR_NOMEM\n"));
6949                         result = WERR_NOMEM;
6950                         goto out;
6951                 }
6952
6953                 for (i=0; i<numlines; i++) {
6954                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6955                         result = fill_port_2(info, &info[i].info2, qlines[i]);
6956                         if (!W_ERROR_IS_OK(result)) {
6957                                 goto out;
6958                         }
6959                 }
6960         }
6961         TALLOC_FREE(qlines);
6962
6963 out:
6964         if (!W_ERROR_IS_OK(result)) {
6965                 TALLOC_FREE(info);
6966                 TALLOC_FREE(qlines);
6967                 *count = 0;
6968                 *info_p = NULL;
6969                 return result;
6970         }
6971
6972         *info_p = info;
6973         *count = numlines;
6974
6975         return WERR_OK;
6976 }
6977
6978 /****************************************************************
6979  _spoolss_EnumPorts
6980 ****************************************************************/
6981
6982 WERROR _spoolss_EnumPorts(pipes_struct *p,
6983                           struct spoolss_EnumPorts *r)
6984 {
6985         WERROR result;
6986
6987         /* that's an [in out] buffer */
6988
6989         if (!r->in.buffer && (r->in.offered != 0)) {
6990                 return WERR_INVALID_PARAM;
6991         }
6992
6993         DEBUG(4,("_spoolss_EnumPorts\n"));
6994
6995         *r->out.count = 0;
6996         *r->out.needed = 0;
6997         *r->out.info = NULL;
6998
6999         switch (r->in.level) {
7000         case 1:
7001                 result = enumports_level_1(p->mem_ctx, r->out.info,
7002                                            r->out.count);
7003                 break;
7004         case 2:
7005                 result = enumports_level_2(p->mem_ctx, r->out.info,
7006                                            r->out.count);
7007                 break;
7008         default:
7009                 return WERR_UNKNOWN_LEVEL;
7010         }
7011
7012         if (!W_ERROR_IS_OK(result)) {
7013                 return result;
7014         }
7015
7016         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7017                                                      spoolss_EnumPorts, NULL,
7018                                                      *r->out.info, r->in.level,
7019                                                      *r->out.count);
7020         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7021         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7022
7023         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7024 }
7025
7026 /****************************************************************************
7027 ****************************************************************************/
7028
7029 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7030                                            const char *server,
7031                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7032                                            struct spoolss_DeviceMode *devmode,
7033                                            struct security_descriptor *sec_desc,
7034                                            struct spoolss_UserLevelCtr *user_ctr,
7035                                            struct policy_handle *handle)
7036 {
7037         NT_PRINTER_INFO_LEVEL *printer = NULL;
7038         fstring name;
7039         int     snum;
7040         WERROR err = WERR_OK;
7041
7042         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7043                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7044                 return WERR_NOMEM;
7045         }
7046
7047         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7048         if (!convert_printer_info(info_ctr, printer)) {
7049                 free_a_printer(&printer, 2);
7050                 return WERR_NOMEM;
7051         }
7052
7053         /* check to see if the printer already exists */
7054
7055         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7056                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7057                         printer->info_2->sharename));
7058                 free_a_printer(&printer, 2);
7059                 return WERR_PRINTER_ALREADY_EXISTS;
7060         }
7061
7062         /* FIXME!!!  smbd should check to see if the driver is installed before
7063            trying to add a printer like this  --jerry */
7064
7065         if (*lp_addprinter_cmd() ) {
7066                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7067                                        printer) ) {
7068                         free_a_printer(&printer,2);
7069                         return WERR_ACCESS_DENIED;
7070                 }
7071         } else {
7072                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7073                         "smb.conf parameter \"addprinter command\" is defined. This"
7074                         "parameter must exist for this call to succeed\n",
7075                         printer->info_2->sharename ));
7076         }
7077
7078         /* use our primary netbios name since get_a_printer() will convert
7079            it to what the client expects on a case by case basis */
7080
7081         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7082              printer->info_2->sharename);
7083
7084
7085         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7086                 free_a_printer(&printer,2);
7087                 return WERR_ACCESS_DENIED;
7088         }
7089
7090         /* you must be a printer admin to add a new printer */
7091         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7092                 free_a_printer(&printer,2);
7093                 return WERR_ACCESS_DENIED;
7094         }
7095
7096         /*
7097          * Do sanity check on the requested changes for Samba.
7098          */
7099
7100         if (!check_printer_ok(printer->info_2, snum)) {
7101                 free_a_printer(&printer,2);
7102                 return WERR_INVALID_PARAM;
7103         }
7104
7105         /*
7106          * When a printer is created, the drivername bound to the printer is used
7107          * to lookup previously saved driver initialization info, which is then
7108          * bound to the new printer, simulating what happens in the Windows arch.
7109          */
7110
7111         if (!devmode)
7112         {
7113                 set_driver_init(printer, 2);
7114         }
7115         else
7116         {
7117                 /* A valid devmode was included, convert and link it
7118                 */
7119                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7120
7121                 if (!convert_devicemode(printer->info_2->printername, devmode,
7122                                         &printer->info_2->devmode)) {
7123                         return  WERR_NOMEM;
7124                 }
7125         }
7126
7127         /* write the ASCII on disk */
7128         err = mod_a_printer(printer, 2);
7129         if (!W_ERROR_IS_OK(err)) {
7130                 free_a_printer(&printer,2);
7131                 return err;
7132         }
7133
7134         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7135                 /* Handle open failed - remove addition. */
7136                 del_a_printer(printer->info_2->sharename);
7137                 free_a_printer(&printer,2);
7138                 ZERO_STRUCTP(handle);
7139                 return WERR_ACCESS_DENIED;
7140         }
7141
7142         update_c_setprinter(false);
7143         free_a_printer(&printer,2);
7144
7145         return WERR_OK;
7146 }
7147
7148 /****************************************************************
7149  _spoolss_AddPrinterEx
7150 ****************************************************************/
7151
7152 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7153                              struct spoolss_AddPrinterEx *r)
7154 {
7155         switch (r->in.info_ctr->level) {
7156         case 1:
7157                 /* we don't handle yet */
7158                 /* but I know what to do ... */
7159                 return WERR_UNKNOWN_LEVEL;
7160         case 2:
7161                 return spoolss_addprinterex_level_2(p, r->in.server,
7162                                                     r->in.info_ctr,
7163                                                     r->in.devmode_ctr->devmode,
7164                                                     r->in.secdesc_ctr->sd,
7165                                                     r->in.userlevel_ctr,
7166                                                     r->out.handle);
7167         default:
7168                 return WERR_UNKNOWN_LEVEL;
7169         }
7170 }
7171
7172 /****************************************************************
7173  _spoolss_AddPrinter
7174 ****************************************************************/
7175
7176 WERROR _spoolss_AddPrinter(pipes_struct *p,
7177                            struct spoolss_AddPrinter *r)
7178 {
7179         struct spoolss_AddPrinterEx a;
7180         struct spoolss_UserLevelCtr userlevel_ctr;
7181
7182         ZERO_STRUCT(userlevel_ctr);
7183
7184         userlevel_ctr.level = 1;
7185
7186         a.in.server             = r->in.server;
7187         a.in.info_ctr           = r->in.info_ctr;
7188         a.in.devmode_ctr        = r->in.devmode_ctr;
7189         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7190         a.in.userlevel_ctr      = &userlevel_ctr;
7191         a.out.handle            = r->out.handle;
7192
7193         return _spoolss_AddPrinterEx(p, &a);
7194 }
7195
7196 /****************************************************************
7197  _spoolss_AddPrinterDriver
7198 ****************************************************************/
7199
7200 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7201                                  struct spoolss_AddPrinterDriver *r)
7202 {
7203         WERROR err = WERR_OK;
7204         char *driver_name = NULL;
7205         uint32_t version;
7206         const char *fn;
7207
7208         switch (p->hdr_req.opnum) {
7209                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7210                         fn = "_spoolss_AddPrinterDriver";
7211                         break;
7212                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7213                         fn = "_spoolss_AddPrinterDriverEx";
7214                         break;
7215                 default:
7216                         return WERR_INVALID_PARAM;
7217         }
7218
7219
7220         /* FIXME */
7221         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7222                 /* Clever hack from Martin Zielinski <mz@seh.de>
7223                  * to allow downgrade from level 8 (Vista).
7224                  */
7225                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7226                         r->in.info_ctr->level));
7227                 return WERR_UNKNOWN_LEVEL;
7228         }
7229
7230         DEBUG(5,("Cleaning driver's information\n"));
7231         err = clean_up_driver_struct(p, r->in.info_ctr);
7232         if (!W_ERROR_IS_OK(err))
7233                 goto done;
7234
7235         DEBUG(5,("Moving driver to final destination\n"));
7236         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7237                                                               &err)) ) {
7238                 goto done;
7239         }
7240
7241         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7242                 err = WERR_ACCESS_DENIED;
7243                 goto done;
7244         }
7245
7246         /*
7247          * I think this is where he DrvUpgradePrinter() hook would be
7248          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7249          * server.  Right now, we just need to send ourselves a message
7250          * to update each printer bound to this driver.   --jerry
7251          */
7252
7253         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7254                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7255                         fn, driver_name));
7256         }
7257
7258         /*
7259          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7260          * decide if the driver init data should be deleted. The rules are:
7261          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7262          *  2) delete init data only if there is no 2k/Xp driver
7263          *  3) always delete init data
7264          * The generalized rule is always use init data from the highest order driver.
7265          * It is necessary to follow the driver install by an initialization step to
7266          * finish off this process.
7267         */
7268
7269         switch (version) {
7270                 /*
7271                  * 9x printer driver - never delete init data
7272                 */
7273                 case 0:
7274                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7275                                 fn, driver_name));
7276                         break;
7277
7278                 /*
7279                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7280                  * there is no 2k/Xp driver init data for this driver name.
7281                 */
7282                 case 2:
7283                 {
7284                         struct spoolss_DriverInfo8 *driver1;
7285
7286                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, driver_name, "Windows NT x86", 3))) {
7287                                 /*
7288                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7289                                 */
7290                                 if (!del_driver_init(driver_name))
7291                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7292                                                 fn, driver_name));
7293                         } else {
7294                                 /*
7295                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7296                                 */
7297                                 free_a_printer_driver(driver1);
7298                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7299                                         fn, driver_name));
7300                         }
7301                 }
7302                 break;
7303
7304                 /*
7305                  * 2k or Xp printer driver - always delete init data
7306                 */
7307                 case 3:
7308                         if (!del_driver_init(driver_name))
7309                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7310                                         fn, driver_name));
7311                         break;
7312
7313                 default:
7314                         DEBUG(0,("%s: invalid level=%d\n", fn,
7315                                 r->in.info_ctr->level));
7316                         break;
7317         }
7318
7319
7320 done:
7321         return err;
7322 }
7323
7324 /****************************************************************
7325  _spoolss_AddPrinterDriverEx
7326 ****************************************************************/
7327
7328 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7329                                    struct spoolss_AddPrinterDriverEx *r)
7330 {
7331         struct spoolss_AddPrinterDriver a;
7332
7333         /*
7334          * we only support the semantics of AddPrinterDriver()
7335          * i.e. only copy files that are newer than existing ones
7336          */
7337
7338         if (r->in.flags != APD_COPY_NEW_FILES) {
7339                 return WERR_ACCESS_DENIED;
7340         }
7341
7342         a.in.servername         = r->in.servername;
7343         a.in.info_ctr           = r->in.info_ctr;
7344
7345         return _spoolss_AddPrinterDriver(p, &a);
7346 }
7347
7348 /****************************************************************************
7349 ****************************************************************************/
7350
7351 struct _spoolss_paths {
7352         int type;
7353         const char *share;
7354         const char *dir;
7355 };
7356
7357 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7358
7359 static const struct _spoolss_paths spoolss_paths[]= {
7360         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7361         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7362 };
7363
7364 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7365                                           const char *servername,
7366                                           const char *environment,
7367                                           int component,
7368                                           char **path)
7369 {
7370         const char *pservername = NULL;
7371         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7372         const char *short_archi;
7373
7374         *path = NULL;
7375
7376         /* environment may be empty */
7377         if (environment && strlen(environment)) {
7378                 long_archi = environment;
7379         }
7380
7381         /* servername may be empty */
7382         if (servername && strlen(servername)) {
7383                 pservername = canon_servername(servername);
7384
7385                 if (!is_myname_or_ipaddr(pservername)) {
7386                         return WERR_INVALID_PARAM;
7387                 }
7388         }
7389
7390         if (!(short_archi = get_short_archi(long_archi))) {
7391                 return WERR_INVALID_ENVIRONMENT;
7392         }
7393
7394         switch (component) {
7395         case SPOOLSS_PRTPROCS_PATH:
7396         case SPOOLSS_DRIVER_PATH:
7397                 if (pservername) {
7398                         *path = talloc_asprintf(mem_ctx,
7399                                         "\\\\%s\\%s\\%s",
7400                                         pservername,
7401                                         spoolss_paths[component].share,
7402                                         short_archi);
7403                 } else {
7404                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7405                                         SPOOLSS_DEFAULT_SERVER_PATH,
7406                                         spoolss_paths[component].dir,
7407                                         short_archi);
7408                 }
7409                 break;
7410         default:
7411                 return WERR_INVALID_PARAM;
7412         }
7413
7414         if (!*path) {
7415                 return WERR_NOMEM;
7416         }
7417
7418         return WERR_OK;
7419 }
7420
7421 /****************************************************************************
7422 ****************************************************************************/
7423
7424 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7425                                           const char *servername,
7426                                           const char *environment,
7427                                           struct spoolss_DriverDirectoryInfo1 *r)
7428 {
7429         WERROR werr;
7430         char *path = NULL;
7431
7432         werr = compose_spoolss_server_path(mem_ctx,
7433                                            servername,
7434                                            environment,
7435                                            SPOOLSS_DRIVER_PATH,
7436                                            &path);
7437         if (!W_ERROR_IS_OK(werr)) {
7438                 return werr;
7439         }
7440
7441         DEBUG(4,("printer driver directory: [%s]\n", path));
7442
7443         r->directory_name = path;
7444
7445         return WERR_OK;
7446 }
7447
7448 /****************************************************************
7449  _spoolss_GetPrinterDriverDirectory
7450 ****************************************************************/
7451
7452 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7453                                           struct spoolss_GetPrinterDriverDirectory *r)
7454 {
7455         WERROR werror;
7456
7457         /* that's an [in out] buffer */
7458
7459         if (!r->in.buffer && (r->in.offered != 0)) {
7460                 return WERR_INVALID_PARAM;
7461         }
7462
7463         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7464                 r->in.level));
7465
7466         *r->out.needed = 0;
7467
7468         /* r->in.level is ignored */
7469
7470         werror = getprinterdriverdir_level_1(p->mem_ctx,
7471                                              r->in.server,
7472                                              r->in.environment,
7473                                              &r->out.info->info1);
7474         if (!W_ERROR_IS_OK(werror)) {
7475                 TALLOC_FREE(r->out.info);
7476                 return werror;
7477         }
7478
7479         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7480                                                r->out.info, r->in.level);
7481         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7482
7483         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7484 }
7485
7486 /****************************************************************
7487  _spoolss_EnumPrinterData
7488 ****************************************************************/
7489
7490 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7491                                 struct spoolss_EnumPrinterData *r)
7492 {
7493         NT_PRINTER_INFO_LEVEL *printer = NULL;
7494         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7495         int             snum;
7496         WERROR          result;
7497         struct regval_blob      *val = NULL;
7498         NT_PRINTER_DATA *p_data;
7499         int             i, key_index, num_values;
7500         int             name_length;
7501
7502         *r->out.value_needed    = 0;
7503         *r->out.type            = REG_NONE;
7504         *r->out.data_needed     = 0;
7505
7506         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7507
7508         if (!Printer) {
7509                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7510                         OUR_HANDLE(r->in.handle)));
7511                 return WERR_BADFID;
7512         }
7513
7514         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7515                 return WERR_BADFID;
7516         }
7517
7518         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7519         if (!W_ERROR_IS_OK(result)) {
7520                 return result;
7521         }
7522
7523         p_data = printer->info_2->data;
7524         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7525
7526         result = WERR_OK;
7527
7528         /*
7529          * The NT machine wants to know the biggest size of value and data
7530          *
7531          * cf: MSDN EnumPrinterData remark section
7532          */
7533
7534         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7535
7536                 uint32_t biggest_valuesize = 0;
7537                 uint32_t biggest_datasize = 0;
7538
7539                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7540
7541                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7542
7543                 for ( i=0; i<num_values; i++ )
7544                 {
7545                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7546
7547                         name_length = strlen(val->valuename);
7548                         if ( strlen(val->valuename) > biggest_valuesize )
7549                                 biggest_valuesize = name_length;
7550
7551                         if ( val->size > biggest_datasize )
7552                                 biggest_datasize = val->size;
7553
7554                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7555                                 biggest_datasize));
7556                 }
7557
7558                 /* the value is an UNICODE string but real_value_size is the length
7559                    in bytes including the trailing 0 */
7560
7561                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7562                 *r->out.data_needed  = biggest_datasize;
7563
7564                 DEBUG(6,("final values: [%d], [%d]\n",
7565                         *r->out.value_needed, *r->out.data_needed));
7566
7567                 goto done;
7568         }
7569
7570         /*
7571          * the value len is wrong in NT sp3
7572          * that's the number of bytes not the number of unicode chars
7573          */
7574
7575         if (key_index != -1) {
7576                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7577                                                 r->in.enum_index);
7578         }
7579
7580         if (!val) {
7581
7582                 /* out_value should default to "" or else NT4 has
7583                    problems unmarshalling the response */
7584
7585                 if (r->in.value_offered) {
7586                         *r->out.value_needed = 1;
7587                         r->out.value_name = talloc_strdup(r, "");
7588                         if (!r->out.value_name) {
7589                                 result = WERR_NOMEM;
7590                                 goto done;
7591                         }
7592                 } else {
7593                         r->out.value_name = NULL;
7594                         *r->out.value_needed = 0;
7595                 }
7596
7597                 /* the data is counted in bytes */
7598
7599                 *r->out.data_needed = r->in.data_offered;
7600
7601                 result = WERR_NO_MORE_ITEMS;
7602         } else {
7603                 /*
7604                  * the value is:
7605                  * - counted in bytes in the request
7606                  * - counted in UNICODE chars in the max reply
7607                  * - counted in bytes in the real size
7608                  *
7609                  * take a pause *before* coding not *during* coding
7610                  */
7611
7612                 /* name */
7613                 if (r->in.value_offered) {
7614                         r->out.value_name = talloc_strdup(r, regval_name(val));
7615                         if (!r->out.value_name) {
7616                                 result = WERR_NOMEM;
7617                                 goto done;
7618                         }
7619                         *r->out.value_needed = strlen_m(regval_name(val));
7620                 } else {
7621                         r->out.value_name = NULL;
7622                         *r->out.value_needed = 0;
7623                 }
7624
7625                 /* type */
7626
7627                 *r->out.type = regval_type(val);
7628
7629                 /* data - counted in bytes */
7630
7631                 if (r->out.data && regval_size(val)) {
7632                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
7633                 }
7634
7635                 *r->out.data_needed = regval_size(val);
7636         }
7637
7638 done:
7639         free_a_printer(&printer, 2);
7640         return result;
7641 }
7642
7643 /****************************************************************
7644  _spoolss_SetPrinterData
7645 ****************************************************************/
7646
7647 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7648                                struct spoolss_SetPrinterData *r)
7649 {
7650         struct spoolss_SetPrinterDataEx r2;
7651
7652         r2.in.handle            = r->in.handle;
7653         r2.in.key_name          = "PrinterDriverData";
7654         r2.in.value_name        = r->in.value_name;
7655         r2.in.type              = r->in.type;
7656         r2.in.data              = r->in.data;
7657         r2.in._offered          = r->in._offered;
7658
7659         return _spoolss_SetPrinterDataEx(p, &r2);
7660 }
7661
7662 /****************************************************************
7663  _spoolss_ResetPrinter
7664 ****************************************************************/
7665
7666 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7667                              struct spoolss_ResetPrinter *r)
7668 {
7669         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7670         int             snum;
7671
7672         DEBUG(5,("_spoolss_ResetPrinter\n"));
7673
7674         /*
7675          * All we do is to check to see if the handle and queue is valid.
7676          * This call really doesn't mean anything to us because we only
7677          * support RAW printing.   --jerry
7678          */
7679
7680         if (!Printer) {
7681                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7682                         OUR_HANDLE(r->in.handle)));
7683                 return WERR_BADFID;
7684         }
7685
7686         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7687                 return WERR_BADFID;
7688
7689
7690         /* blindly return success */
7691         return WERR_OK;
7692 }
7693
7694 /****************************************************************
7695  _spoolss_DeletePrinterData
7696 ****************************************************************/
7697
7698 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7699                                   struct spoolss_DeletePrinterData *r)
7700 {
7701         struct spoolss_DeletePrinterDataEx r2;
7702
7703         r2.in.handle            = r->in.handle;
7704         r2.in.key_name          = "PrinterDriverData";
7705         r2.in.value_name        = r->in.value_name;
7706
7707         return _spoolss_DeletePrinterDataEx(p, &r2);
7708 }
7709
7710 /****************************************************************
7711  _spoolss_AddForm
7712 ****************************************************************/
7713
7714 WERROR _spoolss_AddForm(pipes_struct *p,
7715                         struct spoolss_AddForm *r)
7716 {
7717         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7718         nt_forms_struct tmpForm;
7719         int snum = -1;
7720         WERROR status = WERR_OK;
7721         NT_PRINTER_INFO_LEVEL *printer = NULL;
7722         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7723
7724         int count=0;
7725         nt_forms_struct *list=NULL;
7726         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7727
7728         DEBUG(5,("_spoolss_AddForm\n"));
7729
7730         if (!Printer) {
7731                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7732                         OUR_HANDLE(r->in.handle)));
7733                 return WERR_BADFID;
7734         }
7735
7736
7737         /* forms can be added on printer of on the print server handle */
7738
7739         if ( Printer->printer_type == SPLHND_PRINTER )
7740         {
7741                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7742                         return WERR_BADFID;
7743
7744                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7745                 if (!W_ERROR_IS_OK(status))
7746                         goto done;
7747         }
7748
7749         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7750            and not a printer admin, then fail */
7751
7752         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7753              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7754              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7755                                           NULL, NULL,
7756                                           p->server_info->ptok,
7757                                           lp_printer_admin(snum))) {
7758                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7759                 return WERR_ACCESS_DENIED;
7760         }
7761
7762         /* can't add if builtin */
7763
7764         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7765                 status = WERR_FILE_EXISTS;
7766                 goto done;
7767         }
7768
7769         count = get_ntforms(&list);
7770
7771         if(!add_a_form(&list, form, &count)) {
7772                 status =  WERR_NOMEM;
7773                 goto done;
7774         }
7775
7776         become_root();
7777         write_ntforms(&list, count);
7778         unbecome_root();
7779
7780         /*
7781          * ChangeID must always be set if this is a printer
7782          */
7783
7784         if ( Printer->printer_type == SPLHND_PRINTER )
7785                 status = mod_a_printer(printer, 2);
7786
7787 done:
7788         if ( printer )
7789                 free_a_printer(&printer, 2);
7790         SAFE_FREE(list);
7791
7792         return status;
7793 }
7794
7795 /****************************************************************
7796  _spoolss_DeleteForm
7797 ****************************************************************/
7798
7799 WERROR _spoolss_DeleteForm(pipes_struct *p,
7800                            struct spoolss_DeleteForm *r)
7801 {
7802         const char *form_name = r->in.form_name;
7803         nt_forms_struct tmpForm;
7804         int count=0;
7805         nt_forms_struct *list=NULL;
7806         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7807         int snum = -1;
7808         WERROR status = WERR_OK;
7809         NT_PRINTER_INFO_LEVEL *printer = NULL;
7810         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7811         bool ret = false;
7812
7813         DEBUG(5,("_spoolss_DeleteForm\n"));
7814
7815         if (!Printer) {
7816                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7817                         OUR_HANDLE(r->in.handle)));
7818                 return WERR_BADFID;
7819         }
7820
7821         /* forms can be deleted on printer of on the print server handle */
7822
7823         if ( Printer->printer_type == SPLHND_PRINTER )
7824         {
7825                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7826                         return WERR_BADFID;
7827
7828                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7829                 if (!W_ERROR_IS_OK(status))
7830                         goto done;
7831         }
7832
7833         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7834              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7835              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7836                                           NULL, NULL,
7837                                           p->server_info->ptok,
7838                                           lp_printer_admin(snum))) {
7839                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7840                 return WERR_ACCESS_DENIED;
7841         }
7842
7843
7844         /* can't delete if builtin */
7845
7846         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7847                 status = WERR_INVALID_PARAM;
7848                 goto done;
7849         }
7850
7851         count = get_ntforms(&list);
7852
7853         become_root();
7854         ret = delete_a_form(&list, form_name, &count, &status);
7855         unbecome_root();
7856         if (ret == false) {
7857                 goto done;
7858         }
7859
7860         /*
7861          * ChangeID must always be set if this is a printer
7862          */
7863
7864         if ( Printer->printer_type == SPLHND_PRINTER )
7865                 status = mod_a_printer(printer, 2);
7866
7867 done:
7868         if ( printer )
7869                 free_a_printer(&printer, 2);
7870         SAFE_FREE(list);
7871
7872         return status;
7873 }
7874
7875 /****************************************************************
7876  _spoolss_SetForm
7877 ****************************************************************/
7878
7879 WERROR _spoolss_SetForm(pipes_struct *p,
7880                         struct spoolss_SetForm *r)
7881 {
7882         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7883         nt_forms_struct tmpForm;
7884         int snum = -1;
7885         WERROR status = WERR_OK;
7886         NT_PRINTER_INFO_LEVEL *printer = NULL;
7887         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7888
7889         int count=0;
7890         nt_forms_struct *list=NULL;
7891         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7892
7893         DEBUG(5,("_spoolss_SetForm\n"));
7894
7895         if (!Printer) {
7896                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7897                         OUR_HANDLE(r->in.handle)));
7898                 return WERR_BADFID;
7899         }
7900
7901         /* forms can be modified on printer of on the print server handle */
7902
7903         if ( Printer->printer_type == SPLHND_PRINTER )
7904         {
7905                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7906                         return WERR_BADFID;
7907
7908                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7909                 if (!W_ERROR_IS_OK(status))
7910                         goto done;
7911         }
7912
7913         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7914            and not a printer admin, then fail */
7915
7916         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7917              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7918              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7919                                           NULL, NULL,
7920                                           p->server_info->ptok,
7921                                           lp_printer_admin(snum))) {
7922                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7923                 return WERR_ACCESS_DENIED;
7924         }
7925
7926         /* can't set if builtin */
7927         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7928                 status = WERR_INVALID_PARAM;
7929                 goto done;
7930         }
7931
7932         count = get_ntforms(&list);
7933         update_a_form(&list, form, count);
7934         become_root();
7935         write_ntforms(&list, count);
7936         unbecome_root();
7937
7938         /*
7939          * ChangeID must always be set if this is a printer
7940          */
7941
7942         if ( Printer->printer_type == SPLHND_PRINTER )
7943                 status = mod_a_printer(printer, 2);
7944
7945
7946 done:
7947         if ( printer )
7948                 free_a_printer(&printer, 2);
7949         SAFE_FREE(list);
7950
7951         return status;
7952 }
7953
7954 /****************************************************************************
7955  fill_print_processor1
7956 ****************************************************************************/
7957
7958 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7959                                     struct spoolss_PrintProcessorInfo1 *r,
7960                                     const char *print_processor_name)
7961 {
7962         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7963         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7964
7965         return WERR_OK;
7966 }
7967
7968 /****************************************************************************
7969  enumprintprocessors level 1.
7970 ****************************************************************************/
7971
7972 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7973                                           union spoolss_PrintProcessorInfo **info_p,
7974                                           uint32_t *count)
7975 {
7976         union spoolss_PrintProcessorInfo *info;
7977         WERROR result;
7978
7979         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7980         W_ERROR_HAVE_NO_MEMORY(info);
7981
7982         *count = 1;
7983
7984         result = fill_print_processor1(info, &info[0].info1, "winprint");
7985         if (!W_ERROR_IS_OK(result)) {
7986                 goto out;
7987         }
7988
7989  out:
7990         if (!W_ERROR_IS_OK(result)) {
7991                 TALLOC_FREE(info);
7992                 *count = 0;
7993                 return result;
7994         }
7995
7996         *info_p = info;
7997
7998         return WERR_OK;
7999 }
8000
8001 /****************************************************************
8002  _spoolss_EnumPrintProcessors
8003 ****************************************************************/
8004
8005 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8006                                     struct spoolss_EnumPrintProcessors *r)
8007 {
8008         WERROR result;
8009
8010         /* that's an [in out] buffer */
8011
8012         if (!r->in.buffer && (r->in.offered != 0)) {
8013                 return WERR_INVALID_PARAM;
8014         }
8015
8016         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8017
8018         /*
8019          * Enumerate the print processors ...
8020          *
8021          * Just reply with "winprint", to keep NT happy
8022          * and I can use my nice printer checker.
8023          */
8024
8025         *r->out.count = 0;
8026         *r->out.needed = 0;
8027         *r->out.info = NULL;
8028
8029         switch (r->in.level) {
8030         case 1:
8031                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8032                                                      r->out.count);
8033                 break;
8034         default:
8035                 return WERR_UNKNOWN_LEVEL;
8036         }
8037
8038         if (!W_ERROR_IS_OK(result)) {
8039                 return result;
8040         }
8041
8042         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8043                                                      spoolss_EnumPrintProcessors, NULL,
8044                                                      *r->out.info, r->in.level,
8045                                                      *r->out.count);
8046         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8047         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8048
8049         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8050 }
8051
8052 /****************************************************************************
8053  fill_printprocdatatype1
8054 ****************************************************************************/
8055
8056 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8057                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8058                                       const char *name_array)
8059 {
8060         r->name_array = talloc_strdup(mem_ctx, name_array);
8061         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8062
8063         return WERR_OK;
8064 }
8065
8066 /****************************************************************************
8067  enumprintprocdatatypes level 1.
8068 ****************************************************************************/
8069
8070 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8071                                              union spoolss_PrintProcDataTypesInfo **info_p,
8072                                              uint32_t *count)
8073 {
8074         WERROR result;
8075         union spoolss_PrintProcDataTypesInfo *info;
8076
8077         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8078         W_ERROR_HAVE_NO_MEMORY(info);
8079
8080         *count = 1;
8081
8082         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8083         if (!W_ERROR_IS_OK(result)) {
8084                 goto out;
8085         }
8086
8087  out:
8088         if (!W_ERROR_IS_OK(result)) {
8089                 TALLOC_FREE(info);
8090                 *count = 0;
8091                 return result;
8092         }
8093
8094         *info_p = info;
8095
8096         return WERR_OK;
8097 }
8098
8099 /****************************************************************
8100  _spoolss_EnumPrintProcDataTypes
8101 ****************************************************************/
8102
8103 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8104                                        struct spoolss_EnumPrintProcDataTypes *r)
8105 {
8106         WERROR result;
8107
8108         /* that's an [in out] buffer */
8109
8110         if (!r->in.buffer && (r->in.offered != 0)) {
8111                 return WERR_INVALID_PARAM;
8112         }
8113
8114         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8115
8116         *r->out.count = 0;
8117         *r->out.needed = 0;
8118         *r->out.info = NULL;
8119
8120         switch (r->in.level) {
8121         case 1:
8122                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8123                                                         r->out.count);
8124                 break;
8125         default:
8126                 return WERR_UNKNOWN_LEVEL;
8127         }
8128
8129         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8130                                                      spoolss_EnumPrintProcDataTypes, NULL,
8131                                                      *r->out.info, r->in.level,
8132                                                      *r->out.count);
8133         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8134         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8135
8136         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8137 }
8138
8139 /****************************************************************************
8140  fill_monitor_1
8141 ****************************************************************************/
8142
8143 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8144                              struct spoolss_MonitorInfo1 *r,
8145                              const char *monitor_name)
8146 {
8147         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8148         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8149
8150         return WERR_OK;
8151 }
8152
8153 /****************************************************************************
8154  fill_monitor_2
8155 ****************************************************************************/
8156
8157 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8158                              struct spoolss_MonitorInfo2 *r,
8159                              const char *monitor_name,
8160                              const char *environment,
8161                              const char *dll_name)
8162 {
8163         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8164         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8165         r->environment                  = talloc_strdup(mem_ctx, environment);
8166         W_ERROR_HAVE_NO_MEMORY(r->environment);
8167         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8168         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8169
8170         return WERR_OK;
8171 }
8172
8173 /****************************************************************************
8174  enumprintmonitors level 1.
8175 ****************************************************************************/
8176
8177 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8178                                         union spoolss_MonitorInfo **info_p,
8179                                         uint32_t *count)
8180 {
8181         union spoolss_MonitorInfo *info;
8182         WERROR result = WERR_OK;
8183
8184         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8185         W_ERROR_HAVE_NO_MEMORY(info);
8186
8187         *count = 2;
8188
8189         result = fill_monitor_1(info, &info[0].info1,
8190                                 SPL_LOCAL_PORT);
8191         if (!W_ERROR_IS_OK(result)) {
8192                 goto out;
8193         }
8194
8195         result = fill_monitor_1(info, &info[1].info1,
8196                                 SPL_TCPIP_PORT);
8197         if (!W_ERROR_IS_OK(result)) {
8198                 goto out;
8199         }
8200
8201 out:
8202         if (!W_ERROR_IS_OK(result)) {
8203                 TALLOC_FREE(info);
8204                 *count = 0;
8205                 return result;
8206         }
8207
8208         *info_p = info;
8209
8210         return WERR_OK;
8211 }
8212
8213 /****************************************************************************
8214  enumprintmonitors level 2.
8215 ****************************************************************************/
8216
8217 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8218                                         union spoolss_MonitorInfo **info_p,
8219                                         uint32_t *count)
8220 {
8221         union spoolss_MonitorInfo *info;
8222         WERROR result = WERR_OK;
8223
8224         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8225         W_ERROR_HAVE_NO_MEMORY(info);
8226
8227         *count = 2;
8228
8229         result = fill_monitor_2(info, &info[0].info2,
8230                                 SPL_LOCAL_PORT,
8231                                 "Windows NT X86", /* FIXME */
8232                                 "localmon.dll");
8233         if (!W_ERROR_IS_OK(result)) {
8234                 goto out;
8235         }
8236
8237         result = fill_monitor_2(info, &info[1].info2,
8238                                 SPL_TCPIP_PORT,
8239                                 "Windows NT X86", /* FIXME */
8240                                 "tcpmon.dll");
8241         if (!W_ERROR_IS_OK(result)) {
8242                 goto out;
8243         }
8244
8245 out:
8246         if (!W_ERROR_IS_OK(result)) {
8247                 TALLOC_FREE(info);
8248                 *count = 0;
8249                 return result;
8250         }
8251
8252         *info_p = info;
8253
8254         return WERR_OK;
8255 }
8256
8257 /****************************************************************
8258  _spoolss_EnumMonitors
8259 ****************************************************************/
8260
8261 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8262                              struct spoolss_EnumMonitors *r)
8263 {
8264         WERROR result;
8265
8266         /* that's an [in out] buffer */
8267
8268         if (!r->in.buffer && (r->in.offered != 0)) {
8269                 return WERR_INVALID_PARAM;
8270         }
8271
8272         DEBUG(5,("_spoolss_EnumMonitors\n"));
8273
8274         /*
8275          * Enumerate the print monitors ...
8276          *
8277          * Just reply with "Local Port", to keep NT happy
8278          * and I can use my nice printer checker.
8279          */
8280
8281         *r->out.count = 0;
8282         *r->out.needed = 0;
8283         *r->out.info = NULL;
8284
8285         switch (r->in.level) {
8286         case 1:
8287                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8288                                                    r->out.count);
8289                 break;
8290         case 2:
8291                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8292                                                    r->out.count);
8293                 break;
8294         default:
8295                 return WERR_UNKNOWN_LEVEL;
8296         }
8297
8298         if (!W_ERROR_IS_OK(result)) {
8299                 return result;
8300         }
8301
8302         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8303                                                      spoolss_EnumMonitors, NULL,
8304                                                      *r->out.info, r->in.level,
8305                                                      *r->out.count);
8306         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8307         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8308
8309         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8310 }
8311
8312 /****************************************************************************
8313 ****************************************************************************/
8314
8315 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8316                              const print_queue_struct *queue,
8317                              int count, int snum,
8318                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8319                              uint32_t jobid,
8320                              struct spoolss_JobInfo1 *r)
8321 {
8322         int i = 0;
8323         bool found = false;
8324
8325         for (i=0; i<count && found == false; i++) {
8326                 if (queue[i].job == (int)jobid) {
8327                         found = true;
8328                 }
8329         }
8330
8331         if (found == false) {
8332                 /* NT treats not found as bad param... yet another bad choice */
8333                 return WERR_INVALID_PARAM;
8334         }
8335
8336         return fill_job_info1(mem_ctx,
8337                               r,
8338                               &queue[i-1],
8339                               i,
8340                               snum,
8341                               ntprinter);
8342 }
8343
8344 /****************************************************************************
8345 ****************************************************************************/
8346
8347 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8348                              const print_queue_struct *queue,
8349                              int count, int snum,
8350                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8351                              uint32_t jobid,
8352                              struct spoolss_JobInfo2 *r)
8353 {
8354         int i = 0;
8355         bool found = false;
8356         struct spoolss_DeviceMode *devmode;
8357         NT_DEVICEMODE *nt_devmode;
8358         WERROR result;
8359
8360         for (i=0; i<count && found == false; i++) {
8361                 if (queue[i].job == (int)jobid) {
8362                         found = true;
8363                 }
8364         }
8365
8366         if (found == false) {
8367                 /* NT treats not found as bad param... yet another bad
8368                    choice */
8369                 return WERR_INVALID_PARAM;
8370         }
8371
8372         /*
8373          * if the print job does not have a DEVMODE associated with it,
8374          * just use the one for the printer. A NULL devicemode is not
8375          *  a failure condition
8376          */
8377
8378         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8379         if (nt_devmode) {
8380                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8381                 W_ERROR_HAVE_NO_MEMORY(devmode);
8382                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8383                 if (!W_ERROR_IS_OK(result)) {
8384                         return result;
8385                 }
8386         } else {
8387                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8388                 W_ERROR_HAVE_NO_MEMORY(devmode);
8389         }
8390
8391         return fill_job_info2(mem_ctx,
8392                               r,
8393                               &queue[i-1],
8394                               i,
8395                               snum,
8396                               ntprinter,
8397                               devmode);
8398 }
8399
8400 /****************************************************************
8401  _spoolss_GetJob
8402 ****************************************************************/
8403
8404 WERROR _spoolss_GetJob(pipes_struct *p,
8405                        struct spoolss_GetJob *r)
8406 {
8407         WERROR result = WERR_OK;
8408         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8409         int snum;
8410         int count;
8411         print_queue_struct      *queue = NULL;
8412         print_status_struct prt_status;
8413
8414         /* that's an [in out] buffer */
8415
8416         if (!r->in.buffer && (r->in.offered != 0)) {
8417                 return WERR_INVALID_PARAM;
8418         }
8419
8420         DEBUG(5,("_spoolss_GetJob\n"));
8421
8422         *r->out.needed = 0;
8423
8424         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8425                 return WERR_BADFID;
8426         }
8427
8428         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8429         if (!W_ERROR_IS_OK(result)) {
8430                 return result;
8431         }
8432
8433         count = print_queue_status(snum, &queue, &prt_status);
8434
8435         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8436                      count, prt_status.status, prt_status.message));
8437
8438         switch (r->in.level) {
8439         case 1:
8440                 result = getjob_level_1(p->mem_ctx,
8441                                         queue, count, snum, ntprinter,
8442                                         r->in.job_id, &r->out.info->info1);
8443                 break;
8444         case 2:
8445                 result = getjob_level_2(p->mem_ctx,
8446                                         queue, count, snum, ntprinter,
8447                                         r->in.job_id, &r->out.info->info2);
8448                 break;
8449         default:
8450                 result = WERR_UNKNOWN_LEVEL;
8451                 break;
8452         }
8453
8454         SAFE_FREE(queue);
8455         free_a_printer(&ntprinter, 2);
8456
8457         if (!W_ERROR_IS_OK(result)) {
8458                 TALLOC_FREE(r->out.info);
8459                 return result;
8460         }
8461
8462         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8463                                                r->out.info, r->in.level);
8464         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8465
8466         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8467 }
8468
8469 /****************************************************************
8470  _spoolss_GetPrinterDataEx
8471 ****************************************************************/
8472
8473 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8474                                  struct spoolss_GetPrinterDataEx *r)
8475 {
8476
8477         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8478         struct regval_blob              *val = NULL;
8479         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8480         int                     snum = 0;
8481         WERROR result = WERR_OK;
8482         DATA_BLOB blob;
8483
8484         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8485
8486         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8487                 r->in.key_name, r->in.value_name));
8488
8489         /* in case of problem, return some default values */
8490
8491         *r->out.needed  = 0;
8492         *r->out.type    = REG_NONE;
8493
8494         if (!Printer) {
8495                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8496                         OUR_HANDLE(r->in.handle)));
8497                 result = WERR_BADFID;
8498                 goto done;
8499         }
8500
8501         /* Is the handle to a printer or to the server? */
8502
8503         if (Printer->printer_type == SPLHND_SERVER) {
8504
8505                 result = getprinterdata_printer_server(p->mem_ctx,
8506                                                        r->in.value_name,
8507                                                        r->out.type,
8508                                                        r->out.data);
8509                 goto done;
8510         }
8511
8512         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8513                 result = WERR_BADFID;
8514                 goto done;
8515         }
8516
8517         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8518         if (!W_ERROR_IS_OK(result)) {
8519                 goto done;
8520         }
8521
8522         /* check to see if the keyname is valid */
8523         if (!strlen(r->in.key_name)) {
8524                 result = WERR_INVALID_PARAM;
8525                 goto done;
8526         }
8527
8528         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8529
8530         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8531             strequal(r->in.value_name, "ChangeId")) {
8532                 *r->out.type = REG_DWORD;
8533                 *r->out.needed = 4;
8534                 r->out.data->value = printer->info_2->changeid;
8535                 result = WERR_OK;
8536                 goto done;
8537         }
8538
8539         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8540                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8541                         "Invalid keyname [%s]\n", r->in.key_name ));
8542                 result = WERR_BADFILE;
8543                 goto done;
8544         }
8545
8546         val = get_printer_data(printer->info_2,
8547                                r->in.key_name, r->in.value_name);
8548         if (!val) {
8549                 result = WERR_BADFILE;
8550                 goto done;
8551         }
8552
8553         *r->out.needed = regval_size(val);
8554         *r->out.type = regval_type(val);
8555
8556         blob = data_blob_const(regval_data_p(val), regval_size(val));
8557
8558         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
8559                                           r->out.data,
8560                                           *r->out.type);
8561
8562  done:
8563         if (printer) {
8564                 free_a_printer(&printer, 2);
8565         }
8566
8567         if (!W_ERROR_IS_OK(result)) {
8568                 return result;
8569         }
8570
8571         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
8572         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8573         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8574
8575         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8576 }
8577
8578 /****************************************************************
8579  _spoolss_SetPrinterDataEx
8580 ****************************************************************/
8581
8582 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8583                                  struct spoolss_SetPrinterDataEx *r)
8584 {
8585         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8586         int                     snum = 0;
8587         WERROR                  result = WERR_OK;
8588         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8589         char                    *oid_string;
8590         DATA_BLOB blob;
8591
8592         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8593
8594         /* From MSDN documentation of SetPrinterDataEx: pass request to
8595            SetPrinterData if key is "PrinterDriverData" */
8596
8597         if (!Printer) {
8598                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8599                         OUR_HANDLE(r->in.handle)));
8600                 return WERR_BADFID;
8601         }
8602
8603         if (Printer->printer_type == SPLHND_SERVER) {
8604                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8605                         "Not implemented for server handles yet\n"));
8606                 return WERR_INVALID_PARAM;
8607         }
8608
8609         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8610                 return WERR_BADFID;
8611         }
8612
8613         /*
8614          * Access check : NT returns "access denied" if you make a
8615          * SetPrinterData call without the necessary privildge.
8616          * we were originally returning OK if nothing changed
8617          * which made Win2k issue **a lot** of SetPrinterData
8618          * when connecting to a printer  --jerry
8619          */
8620
8621         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8622                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8623                         "change denied by handle access permissions\n"));
8624                 return WERR_ACCESS_DENIED;
8625         }
8626
8627         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8628         if (!W_ERROR_IS_OK(result)) {
8629                 return result;
8630         }
8631
8632         /* check for OID in valuename */
8633
8634         oid_string = strchr(r->in.value_name, ',');
8635         if (oid_string) {
8636                 *oid_string = '\0';
8637                 oid_string++;
8638         }
8639
8640         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8641                                           r->in.type, &r->in.data);
8642         if (!W_ERROR_IS_OK(result)) {
8643                 goto done;
8644         }
8645
8646         /*
8647          * When client side code sets a magic printer data key, detect it and save
8648          * the current printer data and the magic key's data (its the DEVMODE) for
8649          * future printer/driver initializations.
8650          */
8651         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8652                 /* Set devmode and printer initialization info */
8653                 result = save_driver_init(printer, 2, blob.data, blob.length);
8654
8655                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8656
8657                 goto done;
8658         }
8659
8660         /* save the registry data */
8661
8662         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8663                                     r->in.type, blob.data, blob.length);
8664
8665         if (W_ERROR_IS_OK(result)) {
8666                 /* save the OID if one was specified */
8667                 if (oid_string) {
8668                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8669                                 r->in.key_name, SPOOL_OID_KEY);
8670                         if (!str) {
8671                                 result = WERR_NOMEM;
8672                                 goto done;
8673                         }
8674
8675                         /*
8676                          * I'm not checking the status here on purpose.  Don't know
8677                          * if this is right, but I'm returning the status from the
8678                          * previous set_printer_dataex() call.  I have no idea if
8679                          * this is right.    --jerry
8680                          */
8681
8682                         set_printer_dataex(printer, str, r->in.value_name,
8683                                            REG_SZ, (uint8_t *)oid_string,
8684                                            strlen(oid_string)+1);
8685                 }
8686
8687                 result = mod_a_printer(printer, 2);
8688         }
8689
8690  done:
8691         free_a_printer(&printer, 2);
8692
8693         return result;
8694 }
8695
8696 /****************************************************************
8697  _spoolss_DeletePrinterDataEx
8698 ****************************************************************/
8699
8700 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8701                                     struct spoolss_DeletePrinterDataEx *r)
8702 {
8703         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8704         int             snum=0;
8705         WERROR          status = WERR_OK;
8706         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8707
8708         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8709
8710         if (!Printer) {
8711                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8712                         "Invalid handle (%s:%u:%u).\n",
8713                         OUR_HANDLE(r->in.handle)));
8714                 return WERR_BADFID;
8715         }
8716
8717         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8718                 return WERR_BADFID;
8719
8720         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8721                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8722                         "printer properties change denied by handle\n"));
8723                 return WERR_ACCESS_DENIED;
8724         }
8725
8726         if (!r->in.value_name || !r->in.key_name) {
8727                 return WERR_NOMEM;
8728         }
8729
8730         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8731         if (!W_ERROR_IS_OK(status))
8732                 return status;
8733
8734         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8735
8736         if ( W_ERROR_IS_OK(status) )
8737                 mod_a_printer( printer, 2 );
8738
8739         free_a_printer(&printer, 2);
8740
8741         return status;
8742 }
8743
8744 /****************************************************************
8745  _spoolss_EnumPrinterKey
8746 ****************************************************************/
8747
8748 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8749                                struct spoolss_EnumPrinterKey *r)
8750 {
8751         fstring         *keynames = NULL;
8752         int             num_keys;
8753         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8754         NT_PRINTER_DATA *data;
8755         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8756         int             snum = 0;
8757         WERROR          result = WERR_BADFILE;
8758         int i;
8759         const char **array = NULL;
8760         DATA_BLOB blob;
8761
8762         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8763
8764         if (!Printer) {
8765                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8766                         OUR_HANDLE(r->in.handle)));
8767                 return WERR_BADFID;
8768         }
8769
8770         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8771                 return WERR_BADFID;
8772         }
8773
8774         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8775         if (!W_ERROR_IS_OK(result)) {
8776                 return result;
8777         }
8778
8779         /* get the list of subkey names */
8780
8781         data = printer->info_2->data;
8782
8783         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8784         if (num_keys == -1) {
8785                 result = WERR_BADFILE;
8786                 goto done;
8787         }
8788
8789         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8790         if (!array) {
8791                 result = WERR_NOMEM;
8792                 goto done;
8793         }
8794
8795         if (!num_keys) {
8796                 array[0] = talloc_strdup(array, "");
8797                 if (!array[0]) {
8798                         result = WERR_NOMEM;
8799                         goto done;
8800                 }
8801         }
8802
8803         for (i=0; i < num_keys; i++) {
8804
8805                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8806                         keynames[i]));
8807
8808                 array[i] = talloc_strdup(array, keynames[i]);
8809                 if (!array[i]) {
8810                         result = WERR_NOMEM;
8811                         goto done;
8812                 }
8813         }
8814
8815         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8816                 result = WERR_NOMEM;
8817                 goto done;
8818         }
8819
8820         *r->out._ndr_size = r->in.offered / 2;
8821         *r->out.needed = blob.length;
8822
8823         if (r->in.offered < *r->out.needed) {
8824                 result = WERR_MORE_DATA;
8825         } else {
8826                 result = WERR_OK;
8827                 r->out.key_buffer->string_array = array;
8828         }
8829
8830  done:
8831         if (!W_ERROR_IS_OK(result)) {
8832                 TALLOC_FREE(array);
8833                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8834                         *r->out.needed = 0;
8835                 }
8836         }
8837
8838         free_a_printer(&printer, 2);
8839         SAFE_FREE(keynames);
8840
8841         return result;
8842 }
8843
8844 /****************************************************************
8845  _spoolss_DeletePrinterKey
8846 ****************************************************************/
8847
8848 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8849                                  struct spoolss_DeletePrinterKey *r)
8850 {
8851         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8852         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8853         int                     snum=0;
8854         WERROR                  status;
8855
8856         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8857
8858         if (!Printer) {
8859                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8860                         OUR_HANDLE(r->in.handle)));
8861                 return WERR_BADFID;
8862         }
8863
8864         /* if keyname == NULL, return error */
8865
8866         if ( !r->in.key_name )
8867                 return WERR_INVALID_PARAM;
8868
8869         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8870                 return WERR_BADFID;
8871
8872         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8873                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8874                         "printer properties change denied by handle\n"));
8875                 return WERR_ACCESS_DENIED;
8876         }
8877
8878         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8879         if (!W_ERROR_IS_OK(status))
8880                 return status;
8881
8882         /* delete the key and all subneys */
8883
8884         status = delete_all_printer_data( printer->info_2, r->in.key_name );
8885
8886         if ( W_ERROR_IS_OK(status) )
8887                 status = mod_a_printer(printer, 2);
8888
8889         free_a_printer( &printer, 2 );
8890
8891         return status;
8892 }
8893
8894 /****************************************************************
8895 ****************************************************************/
8896
8897 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8898                                                    struct regval_blob *v,
8899                                                    struct spoolss_PrinterEnumValues *r)
8900 {
8901         WERROR result;
8902
8903         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
8904         W_ERROR_HAVE_NO_MEMORY(r->data);
8905
8906         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
8907         W_ERROR_HAVE_NO_MEMORY(r->value_name);
8908
8909         r->type         = regval_type(v);
8910         r->data_length  = regval_size(v);
8911
8912         if (r->data_length) {
8913                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
8914                                                  regval_size(v));
8915                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
8916                                                   r->data,
8917                                                   r->type);
8918                 if (!W_ERROR_IS_OK(result)) {
8919                         return result;
8920                 }
8921         }
8922
8923         return WERR_OK;
8924 }
8925
8926 /****************************************************************
8927  _spoolss_EnumPrinterDataEx
8928 ****************************************************************/
8929
8930 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8931                                   struct spoolss_EnumPrinterDataEx *r)
8932 {
8933         uint32_t        count = 0;
8934         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8935         struct spoolss_PrinterEnumValues *info = NULL;
8936         NT_PRINTER_DATA         *p_data;
8937         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8938         int             snum;
8939         WERROR          result;
8940         int             key_index;
8941         int             i;
8942
8943         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8944
8945         *r->out.count = 0;
8946         *r->out.needed = 0;
8947         *r->out.info = NULL;
8948
8949         if (!Printer) {
8950                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8951                         OUR_HANDLE(r->in.handle)));
8952                 return WERR_BADFID;
8953         }
8954
8955         /*
8956          * first check for a keyname of NULL or "".  Win2k seems to send
8957          * this a lot and we should send back WERR_INVALID_PARAM
8958          * no need to spend time looking up the printer in this case.
8959          * --jerry
8960          */
8961
8962         if (!strlen(r->in.key_name)) {
8963                 result = WERR_INVALID_PARAM;
8964                 goto done;
8965         }
8966
8967         /* get the printer off of disk */
8968
8969         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8970                 return WERR_BADFID;
8971         }
8972
8973         ZERO_STRUCT(printer);
8974         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8975         if (!W_ERROR_IS_OK(result)) {
8976                 return result;
8977         }
8978
8979         /* now look for a match on the key name */
8980
8981         p_data = printer->info_2->data;
8982
8983         key_index = lookup_printerkey(p_data, r->in.key_name);
8984         if (key_index == -1) {
8985                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
8986                         r->in.key_name));
8987                 result = WERR_INVALID_PARAM;
8988                 goto done;
8989         }
8990
8991         /* allocate the memory for the array of pointers -- if necessary */
8992
8993         count = regval_ctr_numvals(p_data->keys[key_index].values);
8994         if (!count) {
8995                 result = WERR_OK; /* ??? */
8996                 goto done;
8997         }
8998
8999         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9000                                  struct spoolss_PrinterEnumValues,
9001                                  count);
9002         if (!info) {
9003                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9004                 result = WERR_NOMEM;
9005                 goto done;
9006         }
9007
9008         /*
9009          * loop through all params and build the array to pass
9010          * back to the  client
9011          */
9012
9013         for (i=0; i < count; i++) {
9014
9015                 struct regval_blob      *val;
9016
9017                 /* lookup the registry value */
9018
9019                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9020
9021                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9022
9023                 /* copy the data */
9024
9025                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9026                 if (!W_ERROR_IS_OK(result)) {
9027                         goto done;
9028                 }
9029         }
9030
9031 #if 0 /* FIXME - gd */
9032         /* housekeeping information in the reply */
9033
9034         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9035          * the hand marshalled container size is a multiple
9036          * of 4 bytes for RPC alignment.
9037          */
9038
9039         if (needed % 4) {
9040                 needed += 4-(needed % 4);
9041         }
9042 #endif
9043         *r->out.count   = count;
9044         *r->out.info    = info;
9045
9046  done:
9047
9048         if (printer) {
9049                 free_a_printer(&printer, 2);
9050         }
9051
9052         if (!W_ERROR_IS_OK(result)) {
9053                 return result;
9054         }
9055
9056         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9057                                                spoolss_EnumPrinterDataEx, NULL,
9058                                                *r->out.info,
9059                                                *r->out.count);
9060         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9061         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9062
9063         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9064 }
9065
9066 /****************************************************************************
9067 ****************************************************************************/
9068
9069 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9070                                                  const char *servername,
9071                                                  const char *environment,
9072                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9073 {
9074         WERROR werr;
9075         char *path = NULL;
9076
9077         werr = compose_spoolss_server_path(mem_ctx,
9078                                            servername,
9079                                            environment,
9080                                            SPOOLSS_PRTPROCS_PATH,
9081                                            &path);
9082         if (!W_ERROR_IS_OK(werr)) {
9083                 return werr;
9084         }
9085
9086         DEBUG(4,("print processor directory: [%s]\n", path));
9087
9088         r->directory_name = path;
9089
9090         return WERR_OK;
9091 }
9092
9093 /****************************************************************
9094  _spoolss_GetPrintProcessorDirectory
9095 ****************************************************************/
9096
9097 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9098                                            struct spoolss_GetPrintProcessorDirectory *r)
9099 {
9100         WERROR result;
9101
9102         /* that's an [in out] buffer */
9103
9104         if (!r->in.buffer && (r->in.offered != 0)) {
9105                 return WERR_INVALID_PARAM;
9106         }
9107
9108         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9109                 r->in.level));
9110
9111         *r->out.needed = 0;
9112
9113         /* r->in.level is ignored */
9114
9115         /* We always should reply with a local print processor directory so that
9116          * users are not forced to have a [prnproc$] share on the Samba spoolss
9117          * server - Guenther */
9118
9119         result = getprintprocessordirectory_level_1(p->mem_ctx,
9120                                                     NULL, /* r->in.server */
9121                                                     r->in.environment,
9122                                                     &r->out.info->info1);
9123         if (!W_ERROR_IS_OK(result)) {
9124                 TALLOC_FREE(r->out.info);
9125                 return result;
9126         }
9127
9128         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9129                                                r->out.info, r->in.level);
9130         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9131
9132         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9133 }
9134
9135 /*******************************************************************
9136  ********************************************************************/
9137
9138 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9139                                const char *dllname)
9140 {
9141         enum ndr_err_code ndr_err;
9142         struct spoolss_MonitorUi ui;
9143
9144         ui.dll_name = dllname;
9145
9146         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9147                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9148         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9149                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9150         }
9151         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9152 }
9153
9154 /*******************************************************************
9155  Streams the monitor UI DLL name in UNICODE
9156 *******************************************************************/
9157
9158 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9159                                NT_USER_TOKEN *token, DATA_BLOB *in,
9160                                DATA_BLOB *out, uint32_t *needed)
9161 {
9162         const char *dllname = "tcpmonui.dll";
9163
9164         *needed = (strlen(dllname)+1) * 2;
9165
9166         if (out->length < *needed) {
9167                 return WERR_INSUFFICIENT_BUFFER;
9168         }
9169
9170         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9171                 return WERR_NOMEM;
9172         }
9173
9174         return WERR_OK;
9175 }
9176
9177 /*******************************************************************
9178  ********************************************************************/
9179
9180 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9181                              struct spoolss_PortData1 *port1,
9182                              const DATA_BLOB *buf)
9183 {
9184         enum ndr_err_code ndr_err;
9185         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9186                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9187         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9188                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9189         }
9190         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9191 }
9192
9193 /*******************************************************************
9194  ********************************************************************/
9195
9196 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9197                              struct spoolss_PortData2 *port2,
9198                              const DATA_BLOB *buf)
9199 {
9200         enum ndr_err_code ndr_err;
9201         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9202                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9203         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9204                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9205         }
9206         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9207 }
9208
9209 /*******************************************************************
9210  Create a new TCP/IP port
9211 *******************************************************************/
9212
9213 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9214                              NT_USER_TOKEN *token, DATA_BLOB *in,
9215                              DATA_BLOB *out, uint32_t *needed)
9216 {
9217         struct spoolss_PortData1 port1;
9218         struct spoolss_PortData2 port2;
9219         char *device_uri = NULL;
9220         uint32_t version;
9221
9222         const char *portname;
9223         const char *hostaddress;
9224         const char *queue;
9225         uint32_t port_number;
9226         uint32_t protocol;
9227
9228         /* peek for spoolss_PortData version */
9229
9230         if (!in || (in->length < (128 + 4))) {
9231                 return WERR_GENERAL_FAILURE;
9232         }
9233
9234         version = IVAL(in->data, 128);
9235
9236         switch (version) {
9237                 case 1:
9238                         ZERO_STRUCT(port1);
9239
9240                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9241                                 return WERR_NOMEM;
9242                         }
9243
9244                         portname        = port1.portname;
9245                         hostaddress     = port1.hostaddress;
9246                         queue           = port1.queue;
9247                         protocol        = port1.protocol;
9248                         port_number     = port1.port_number;
9249
9250                         break;
9251                 case 2:
9252                         ZERO_STRUCT(port2);
9253
9254                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9255                                 return WERR_NOMEM;
9256                         }
9257
9258                         portname        = port2.portname;
9259                         hostaddress     = port2.hostaddress;
9260                         queue           = port2.queue;
9261                         protocol        = port2.protocol;
9262                         port_number     = port2.port_number;
9263
9264                         break;
9265                 default:
9266                         DEBUG(1,("xcvtcp_addport: "
9267                                 "unknown version of port_data: %d\n", version));
9268                         return WERR_UNKNOWN_PORT;
9269         }
9270
9271         /* create the device URI and call the add_port_hook() */
9272
9273         switch (protocol) {
9274         case PROTOCOL_RAWTCP_TYPE:
9275                 device_uri = talloc_asprintf(mem_ctx,
9276                                 "socket://%s:%d/", hostaddress,
9277                                 port_number);
9278                 break;
9279
9280         case PROTOCOL_LPR_TYPE:
9281                 device_uri = talloc_asprintf(mem_ctx,
9282                         "lpr://%s/%s", hostaddress, queue );
9283                 break;
9284
9285         default:
9286                 return WERR_UNKNOWN_PORT;
9287         }
9288
9289         if (!device_uri) {
9290                 return WERR_NOMEM;
9291         }
9292
9293         return add_port_hook(mem_ctx, token, portname, device_uri);
9294 }
9295
9296 /*******************************************************************
9297 *******************************************************************/
9298
9299 struct xcv_api_table xcvtcp_cmds[] = {
9300         { "MonitorUI",  xcvtcp_monitorui },
9301         { "AddPort",    xcvtcp_addport},
9302         { NULL,         NULL }
9303 };
9304
9305 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9306                                      NT_USER_TOKEN *token, const char *command,
9307                                      DATA_BLOB *inbuf,
9308                                      DATA_BLOB *outbuf,
9309                                      uint32_t *needed )
9310 {
9311         int i;
9312
9313         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9314
9315         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9316                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9317                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9318         }
9319
9320         return WERR_BADFUNC;
9321 }
9322
9323 /*******************************************************************
9324 *******************************************************************/
9325 #if 0   /* don't support management using the "Local Port" monitor */
9326
9327 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9328                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9329                                  DATA_BLOB *out, uint32_t *needed)
9330 {
9331         const char *dllname = "localui.dll";
9332
9333         *needed = (strlen(dllname)+1) * 2;
9334
9335         if (out->length < *needed) {
9336                 return WERR_INSUFFICIENT_BUFFER;
9337         }
9338
9339         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9340                 return WERR_NOMEM;
9341         }
9342
9343         return WERR_OK;
9344 }
9345
9346 /*******************************************************************
9347 *******************************************************************/
9348
9349 struct xcv_api_table xcvlocal_cmds[] = {
9350         { "MonitorUI",  xcvlocal_monitorui },
9351         { NULL,         NULL }
9352 };
9353 #else
9354 struct xcv_api_table xcvlocal_cmds[] = {
9355         { NULL,         NULL }
9356 };
9357 #endif
9358
9359
9360
9361 /*******************************************************************
9362 *******************************************************************/
9363
9364 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9365                                        NT_USER_TOKEN *token, const char *command,
9366                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9367                                        uint32_t *needed)
9368 {
9369         int i;
9370
9371         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9372
9373         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9374                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9375                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9376         }
9377         return WERR_BADFUNC;
9378 }
9379
9380 /****************************************************************
9381  _spoolss_XcvData
9382 ****************************************************************/
9383
9384 WERROR _spoolss_XcvData(pipes_struct *p,
9385                         struct spoolss_XcvData *r)
9386 {
9387         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9388         DATA_BLOB out_data = data_blob_null;
9389         WERROR werror;
9390
9391         if (!Printer) {
9392                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9393                         OUR_HANDLE(r->in.handle)));
9394                 return WERR_BADFID;
9395         }
9396
9397         /* Has to be a handle to the TCP/IP port monitor */
9398
9399         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9400                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9401                 return WERR_BADFID;
9402         }
9403
9404         /* requires administrative access to the server */
9405
9406         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9407                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9408                 return WERR_ACCESS_DENIED;
9409         }
9410
9411         /* Allocate the outgoing buffer */
9412
9413         if (r->in.out_data_size) {
9414                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9415                 if (out_data.data == NULL) {
9416                         return WERR_NOMEM;
9417                 }
9418         }
9419
9420         switch ( Printer->printer_type ) {
9421         case SPLHND_PORTMON_TCP:
9422                 werror = process_xcvtcp_command(p->mem_ctx,
9423                                                 p->server_info->ptok,
9424                                                 r->in.function_name,
9425                                                 &r->in.in_data, &out_data,
9426                                                 r->out.needed);
9427                 break;
9428         case SPLHND_PORTMON_LOCAL:
9429                 werror = process_xcvlocal_command(p->mem_ctx,
9430                                                   p->server_info->ptok,
9431                                                   r->in.function_name,
9432                                                   &r->in.in_data, &out_data,
9433                                                   r->out.needed);
9434                 break;
9435         default:
9436                 werror = WERR_INVALID_PRINT_MONITOR;
9437         }
9438
9439         if (!W_ERROR_IS_OK(werror)) {
9440                 return werror;
9441         }
9442
9443         *r->out.status_code = 0;
9444
9445         memcpy(r->out.out_data, out_data.data, out_data.length);
9446
9447         return WERR_OK;
9448 }
9449
9450 /****************************************************************
9451  _spoolss_AddPrintProcessor
9452 ****************************************************************/
9453
9454 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9455                                   struct spoolss_AddPrintProcessor *r)
9456 {
9457         /* for now, just indicate success and ignore the add.  We'll
9458            automatically set the winprint processor for printer
9459            entries later.  Used to debug the LexMark Optra S 1855 PCL
9460            driver --jerry */
9461
9462         return WERR_OK;
9463 }
9464
9465 /****************************************************************
9466  _spoolss_AddPort
9467 ****************************************************************/
9468
9469 WERROR _spoolss_AddPort(pipes_struct *p,
9470                         struct spoolss_AddPort *r)
9471 {
9472         /* do what w2k3 does */
9473
9474         return WERR_NOT_SUPPORTED;
9475 }
9476
9477 /****************************************************************
9478  _spoolss_GetPrinterDriver
9479 ****************************************************************/
9480
9481 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9482                                  struct spoolss_GetPrinterDriver *r)
9483 {
9484         p->rng_fault_state = true;
9485         return WERR_NOT_SUPPORTED;
9486 }
9487
9488 /****************************************************************
9489  _spoolss_ReadPrinter
9490 ****************************************************************/
9491
9492 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9493                             struct spoolss_ReadPrinter *r)
9494 {
9495         p->rng_fault_state = true;
9496         return WERR_NOT_SUPPORTED;
9497 }
9498
9499 /****************************************************************
9500  _spoolss_WaitForPrinterChange
9501 ****************************************************************/
9502
9503 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9504                                      struct spoolss_WaitForPrinterChange *r)
9505 {
9506         p->rng_fault_state = true;
9507         return WERR_NOT_SUPPORTED;
9508 }
9509
9510 /****************************************************************
9511  _spoolss_ConfigurePort
9512 ****************************************************************/
9513
9514 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9515                               struct spoolss_ConfigurePort *r)
9516 {
9517         p->rng_fault_state = true;
9518         return WERR_NOT_SUPPORTED;
9519 }
9520
9521 /****************************************************************
9522  _spoolss_DeletePort
9523 ****************************************************************/
9524
9525 WERROR _spoolss_DeletePort(pipes_struct *p,
9526                            struct spoolss_DeletePort *r)
9527 {
9528         p->rng_fault_state = true;
9529         return WERR_NOT_SUPPORTED;
9530 }
9531
9532 /****************************************************************
9533  _spoolss_CreatePrinterIC
9534 ****************************************************************/
9535
9536 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9537                                 struct spoolss_CreatePrinterIC *r)
9538 {
9539         p->rng_fault_state = true;
9540         return WERR_NOT_SUPPORTED;
9541 }
9542
9543 /****************************************************************
9544  _spoolss_PlayGDIScriptOnPrinterIC
9545 ****************************************************************/
9546
9547 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9548                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9549 {
9550         p->rng_fault_state = true;
9551         return WERR_NOT_SUPPORTED;
9552 }
9553
9554 /****************************************************************
9555  _spoolss_DeletePrinterIC
9556 ****************************************************************/
9557
9558 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9559                                 struct spoolss_DeletePrinterIC *r)
9560 {
9561         p->rng_fault_state = true;
9562         return WERR_NOT_SUPPORTED;
9563 }
9564
9565 /****************************************************************
9566  _spoolss_AddPrinterConnection
9567 ****************************************************************/
9568
9569 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9570                                      struct spoolss_AddPrinterConnection *r)
9571 {
9572         p->rng_fault_state = true;
9573         return WERR_NOT_SUPPORTED;
9574 }
9575
9576 /****************************************************************
9577  _spoolss_DeletePrinterConnection
9578 ****************************************************************/
9579
9580 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9581                                         struct spoolss_DeletePrinterConnection *r)
9582 {
9583         p->rng_fault_state = true;
9584         return WERR_NOT_SUPPORTED;
9585 }
9586
9587 /****************************************************************
9588  _spoolss_PrinterMessageBox
9589 ****************************************************************/
9590
9591 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9592                                   struct spoolss_PrinterMessageBox *r)
9593 {
9594         p->rng_fault_state = true;
9595         return WERR_NOT_SUPPORTED;
9596 }
9597
9598 /****************************************************************
9599  _spoolss_AddMonitor
9600 ****************************************************************/
9601
9602 WERROR _spoolss_AddMonitor(pipes_struct *p,
9603                            struct spoolss_AddMonitor *r)
9604 {
9605         p->rng_fault_state = true;
9606         return WERR_NOT_SUPPORTED;
9607 }
9608
9609 /****************************************************************
9610  _spoolss_DeleteMonitor
9611 ****************************************************************/
9612
9613 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9614                               struct spoolss_DeleteMonitor *r)
9615 {
9616         p->rng_fault_state = true;
9617         return WERR_NOT_SUPPORTED;
9618 }
9619
9620 /****************************************************************
9621  _spoolss_DeletePrintProcessor
9622 ****************************************************************/
9623
9624 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9625                                      struct spoolss_DeletePrintProcessor *r)
9626 {
9627         p->rng_fault_state = true;
9628         return WERR_NOT_SUPPORTED;
9629 }
9630
9631 /****************************************************************
9632  _spoolss_AddPrintProvidor
9633 ****************************************************************/
9634
9635 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9636                                  struct spoolss_AddPrintProvidor *r)
9637 {
9638         p->rng_fault_state = true;
9639         return WERR_NOT_SUPPORTED;
9640 }
9641
9642 /****************************************************************
9643  _spoolss_DeletePrintProvidor
9644 ****************************************************************/
9645
9646 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9647                                     struct spoolss_DeletePrintProvidor *r)
9648 {
9649         p->rng_fault_state = true;
9650         return WERR_NOT_SUPPORTED;
9651 }
9652
9653 /****************************************************************
9654  _spoolss_FindFirstPrinterChangeNotification
9655 ****************************************************************/
9656
9657 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9658                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9659 {
9660         p->rng_fault_state = true;
9661         return WERR_NOT_SUPPORTED;
9662 }
9663
9664 /****************************************************************
9665  _spoolss_FindNextPrinterChangeNotification
9666 ****************************************************************/
9667
9668 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9669                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9670 {
9671         p->rng_fault_state = true;
9672         return WERR_NOT_SUPPORTED;
9673 }
9674
9675 /****************************************************************
9676  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9677 ****************************************************************/
9678
9679 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9680                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9681 {
9682         p->rng_fault_state = true;
9683         return WERR_NOT_SUPPORTED;
9684 }
9685
9686 /****************************************************************
9687  _spoolss_ReplyOpenPrinter
9688 ****************************************************************/
9689
9690 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9691                                  struct spoolss_ReplyOpenPrinter *r)
9692 {
9693         p->rng_fault_state = true;
9694         return WERR_NOT_SUPPORTED;
9695 }
9696
9697 /****************************************************************
9698  _spoolss_RouterReplyPrinter
9699 ****************************************************************/
9700
9701 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9702                                    struct spoolss_RouterReplyPrinter *r)
9703 {
9704         p->rng_fault_state = true;
9705         return WERR_NOT_SUPPORTED;
9706 }
9707
9708 /****************************************************************
9709  _spoolss_ReplyClosePrinter
9710 ****************************************************************/
9711
9712 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9713                                   struct spoolss_ReplyClosePrinter *r)
9714 {
9715         p->rng_fault_state = true;
9716         return WERR_NOT_SUPPORTED;
9717 }
9718
9719 /****************************************************************
9720  _spoolss_AddPortEx
9721 ****************************************************************/
9722
9723 WERROR _spoolss_AddPortEx(pipes_struct *p,
9724                           struct spoolss_AddPortEx *r)
9725 {
9726         p->rng_fault_state = true;
9727         return WERR_NOT_SUPPORTED;
9728 }
9729
9730 /****************************************************************
9731  _spoolss_RouterFindFirstPrinterChangeNotification
9732 ****************************************************************/
9733
9734 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9735                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9736 {
9737         p->rng_fault_state = true;
9738         return WERR_NOT_SUPPORTED;
9739 }
9740
9741 /****************************************************************
9742  _spoolss_SpoolerInit
9743 ****************************************************************/
9744
9745 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9746                             struct spoolss_SpoolerInit *r)
9747 {
9748         p->rng_fault_state = true;
9749         return WERR_NOT_SUPPORTED;
9750 }
9751
9752 /****************************************************************
9753  _spoolss_ResetPrinterEx
9754 ****************************************************************/
9755
9756 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9757                                struct spoolss_ResetPrinterEx *r)
9758 {
9759         p->rng_fault_state = true;
9760         return WERR_NOT_SUPPORTED;
9761 }
9762
9763 /****************************************************************
9764  _spoolss_RouterReplyPrinterEx
9765 ****************************************************************/
9766
9767 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9768                                      struct spoolss_RouterReplyPrinterEx *r)
9769 {
9770         p->rng_fault_state = true;
9771         return WERR_NOT_SUPPORTED;
9772 }
9773
9774 /****************************************************************
9775  _spoolss_44
9776 ****************************************************************/
9777
9778 WERROR _spoolss_44(pipes_struct *p,
9779                    struct spoolss_44 *r)
9780 {
9781         p->rng_fault_state = true;
9782         return WERR_NOT_SUPPORTED;
9783 }
9784
9785 /****************************************************************
9786  _spoolss_47
9787 ****************************************************************/
9788
9789 WERROR _spoolss_47(pipes_struct *p,
9790                    struct spoolss_47 *r)
9791 {
9792         p->rng_fault_state = true;
9793         return WERR_NOT_SUPPORTED;
9794 }
9795
9796 /****************************************************************
9797  _spoolss_4a
9798 ****************************************************************/
9799
9800 WERROR _spoolss_4a(pipes_struct *p,
9801                    struct spoolss_4a *r)
9802 {
9803         p->rng_fault_state = true;
9804         return WERR_NOT_SUPPORTED;
9805 }
9806
9807 /****************************************************************
9808  _spoolss_4b
9809 ****************************************************************/
9810
9811 WERROR _spoolss_4b(pipes_struct *p,
9812                    struct spoolss_4b *r)
9813 {
9814         p->rng_fault_state = true;
9815         return WERR_NOT_SUPPORTED;
9816 }
9817
9818 /****************************************************************
9819  _spoolss_4c
9820 ****************************************************************/
9821
9822 WERROR _spoolss_4c(pipes_struct *p,
9823                    struct spoolss_4c *r)
9824 {
9825         p->rng_fault_state = true;
9826         return WERR_NOT_SUPPORTED;
9827 }
9828
9829 /****************************************************************
9830  _spoolss_53
9831 ****************************************************************/
9832
9833 WERROR _spoolss_53(pipes_struct *p,
9834                    struct spoolss_53 *r)
9835 {
9836         p->rng_fault_state = true;
9837         return WERR_NOT_SUPPORTED;
9838 }
9839
9840 /****************************************************************
9841  _spoolss_55
9842 ****************************************************************/
9843
9844 WERROR _spoolss_55(pipes_struct *p,
9845                    struct spoolss_55 *r)
9846 {
9847         p->rng_fault_state = true;
9848         return WERR_NOT_SUPPORTED;
9849 }
9850
9851 /****************************************************************
9852  _spoolss_56
9853 ****************************************************************/
9854
9855 WERROR _spoolss_56(pipes_struct *p,
9856                    struct spoolss_56 *r)
9857 {
9858         p->rng_fault_state = true;
9859         return WERR_NOT_SUPPORTED;
9860 }
9861
9862 /****************************************************************
9863  _spoolss_57
9864 ****************************************************************/
9865
9866 WERROR _spoolss_57(pipes_struct *p,
9867                    struct spoolss_57 *r)
9868 {
9869         p->rng_fault_state = true;
9870         return WERR_NOT_SUPPORTED;
9871 }
9872
9873 /****************************************************************
9874  _spoolss_5a
9875 ****************************************************************/
9876
9877 WERROR _spoolss_5a(pipes_struct *p,
9878                    struct spoolss_5a *r)
9879 {
9880         p->rng_fault_state = true;
9881         return WERR_NOT_SUPPORTED;
9882 }
9883
9884 /****************************************************************
9885  _spoolss_5b
9886 ****************************************************************/
9887
9888 WERROR _spoolss_5b(pipes_struct *p,
9889                    struct spoolss_5b *r)
9890 {
9891         p->rng_fault_state = true;
9892         return WERR_NOT_SUPPORTED;
9893 }
9894
9895 /****************************************************************
9896  _spoolss_5c
9897 ****************************************************************/
9898
9899 WERROR _spoolss_5c(pipes_struct *p,
9900                    struct spoolss_5c *r)
9901 {
9902         p->rng_fault_state = true;
9903         return WERR_NOT_SUPPORTED;
9904 }
9905
9906 /****************************************************************
9907  _spoolss_5d
9908 ****************************************************************/
9909
9910 WERROR _spoolss_5d(pipes_struct *p,
9911                    struct spoolss_5d *r)
9912 {
9913         p->rng_fault_state = true;
9914         return WERR_NOT_SUPPORTED;
9915 }
9916
9917 /****************************************************************
9918  _spoolss_5e
9919 ****************************************************************/
9920
9921 WERROR _spoolss_5e(pipes_struct *p,
9922                    struct spoolss_5e *r)
9923 {
9924         p->rng_fault_state = true;
9925         return WERR_NOT_SUPPORTED;
9926 }
9927
9928 /****************************************************************
9929  _spoolss_5f
9930 ****************************************************************/
9931
9932 WERROR _spoolss_5f(pipes_struct *p,
9933                    struct spoolss_5f *r)
9934 {
9935         p->rng_fault_state = true;
9936         return WERR_NOT_SUPPORTED;
9937 }
9938
9939 /****************************************************************
9940  _spoolss_60
9941 ****************************************************************/
9942
9943 WERROR _spoolss_60(pipes_struct *p,
9944                    struct spoolss_60 *r)
9945 {
9946         p->rng_fault_state = true;
9947         return WERR_NOT_SUPPORTED;
9948 }
9949
9950 /****************************************************************
9951  _spoolss_61
9952 ****************************************************************/
9953
9954 WERROR _spoolss_61(pipes_struct *p,
9955                    struct spoolss_61 *r)
9956 {
9957         p->rng_fault_state = true;
9958         return WERR_NOT_SUPPORTED;
9959 }
9960
9961 /****************************************************************
9962  _spoolss_62
9963 ****************************************************************/
9964
9965 WERROR _spoolss_62(pipes_struct *p,
9966                    struct spoolss_62 *r)
9967 {
9968         p->rng_fault_state = true;
9969         return WERR_NOT_SUPPORTED;
9970 }
9971
9972 /****************************************************************
9973  _spoolss_63
9974 ****************************************************************/
9975
9976 WERROR _spoolss_63(pipes_struct *p,
9977                    struct spoolss_63 *r)
9978 {
9979         p->rng_fault_state = true;
9980         return WERR_NOT_SUPPORTED;
9981 }
9982
9983 /****************************************************************
9984  _spoolss_64
9985 ****************************************************************/
9986
9987 WERROR _spoolss_64(pipes_struct *p,
9988                    struct spoolss_64 *r)
9989 {
9990         p->rng_fault_state = true;
9991         return WERR_NOT_SUPPORTED;
9992 }
9993
9994 /****************************************************************
9995  _spoolss_65
9996 ****************************************************************/
9997
9998 WERROR _spoolss_65(pipes_struct *p,
9999                    struct spoolss_65 *r)
10000 {
10001         p->rng_fault_state = true;
10002         return WERR_NOT_SUPPORTED;
10003 }
10004
10005 /****************************************************************
10006  _spoolss_GetCorePrinterDrivers
10007 ****************************************************************/
10008
10009 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10010                                       struct spoolss_GetCorePrinterDrivers *r)
10011 {
10012         p->rng_fault_state = true;
10013         return WERR_NOT_SUPPORTED;
10014 }
10015
10016 /****************************************************************
10017  _spoolss_67
10018 ****************************************************************/
10019
10020 WERROR _spoolss_67(pipes_struct *p,
10021                    struct spoolss_67 *r)
10022 {
10023         p->rng_fault_state = true;
10024         return WERR_NOT_SUPPORTED;
10025 }
10026
10027 /****************************************************************
10028  _spoolss_GetPrinterDriverPackagePath
10029 ****************************************************************/
10030
10031 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10032                                             struct spoolss_GetPrinterDriverPackagePath *r)
10033 {
10034         p->rng_fault_state = true;
10035         return WERR_NOT_SUPPORTED;
10036 }
10037
10038 /****************************************************************
10039  _spoolss_69
10040 ****************************************************************/
10041
10042 WERROR _spoolss_69(pipes_struct *p,
10043                    struct spoolss_69 *r)
10044 {
10045         p->rng_fault_state = true;
10046         return WERR_NOT_SUPPORTED;
10047 }
10048
10049 /****************************************************************
10050  _spoolss_6a
10051 ****************************************************************/
10052
10053 WERROR _spoolss_6a(pipes_struct *p,
10054                    struct spoolss_6a *r)
10055 {
10056         p->rng_fault_state = true;
10057         return WERR_NOT_SUPPORTED;
10058 }
10059
10060 /****************************************************************
10061  _spoolss_6b
10062 ****************************************************************/
10063
10064 WERROR _spoolss_6b(pipes_struct *p,
10065                    struct spoolss_6b *r)
10066 {
10067         p->rng_fault_state = true;
10068         return WERR_NOT_SUPPORTED;
10069 }
10070
10071 /****************************************************************
10072  _spoolss_6c
10073 ****************************************************************/
10074
10075 WERROR _spoolss_6c(pipes_struct *p,
10076                    struct spoolss_6c *r)
10077 {
10078         p->rng_fault_state = true;
10079         return WERR_NOT_SUPPORTED;
10080 }
10081
10082 /****************************************************************
10083  _spoolss_6d
10084 ****************************************************************/
10085
10086 WERROR _spoolss_6d(pipes_struct *p,
10087                    struct spoolss_6d *r)
10088 {
10089         p->rng_fault_state = true;
10090         return WERR_NOT_SUPPORTED;
10091 }