s3-spoolss: handle SEC_FLAG_MAXIMUM_ALLOWED in spoolss_OpenPrinterEx.
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35         ((info)?ndr_size_##fn(info, level, ic, 0):0)
36
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
39
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
42
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44
45
46 extern userdom_struct current_user_info;
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_RPC_SRV
50
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
53 #endif
54
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32_t counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected == true) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected = false;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231                                                 struct policy_handle *hnd)
232 {
233         Printer_entry *find_printer = NULL;
234
235         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
237                 return NULL;
238         }
239
240         return find_printer;
241 }
242
243 /****************************************************************************
244  Close printer index by handle.
245 ****************************************************************************/
246
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
248 {
249         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250
251         if (!Printer) {
252                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
253                         OUR_HANDLE(hnd)));
254                 return false;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return true;
260 }
261
262 /****************************************************************************
263  Delete a printer given a handle.
264 ****************************************************************************/
265
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
267 {
268         char *cmd = lp_deleteprinter_cmd();
269         char *command = NULL;
270         int ret;
271         SE_PRIV se_printop = SE_PRINT_OPERATOR;
272         bool is_print_op = false;
273
274         /* can't fail if we don't try */
275
276         if ( !*cmd )
277                 return WERR_OK;
278
279         command = talloc_asprintf(ctx,
280                         "%s \"%s\"",
281                         cmd, sharename);
282         if (!command) {
283                 return WERR_NOMEM;
284         }
285         if ( token )
286                 is_print_op = user_has_privileges( token, &se_printop );
287
288         DEBUG(10,("Running [%s]\n", command));
289
290         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
291
292         if ( is_print_op )
293                 become_root();
294
295         if ( (ret = smbrun(command, NULL)) == 0 ) {
296                 /* Tell everyone we updated smb.conf. */
297                 message_send_all(smbd_messaging_context(),
298                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299         }
300
301         if ( is_print_op )
302                 unbecome_root();
303
304         /********** END SePrintOperatorPrivlege BLOCK **********/
305
306         DEBUGADD(10,("returned [%d]\n", ret));
307
308         TALLOC_FREE(command);
309
310         if (ret != 0)
311                 return WERR_BADFID; /* What to return here? */
312
313         /* go ahead and re-read the services immediately */
314         become_root();
315         reload_services(false);
316         unbecome_root();
317
318         if ( lp_servicenumber( sharename )  < 0 )
319                 return WERR_ACCESS_DENIED;
320
321         return WERR_OK;
322 }
323
324 /****************************************************************************
325  Delete a printer given a handle.
326 ****************************************************************************/
327
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
329 {
330         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331
332         if (!Printer) {
333                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
334                         OUR_HANDLE(hnd)));
335                 return WERR_BADFID;
336         }
337
338         /*
339          * It turns out that Windows allows delete printer on a handle
340          * opened by an admin user, then used on a pipe handle created
341          * by an anonymous user..... but they're working on security.... riiight !
342          * JRA.
343          */
344
345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347                 return WERR_ACCESS_DENIED;
348         }
349
350         /* this does not need a become root since the access check has been
351            done on the handle already */
352
353         if (del_a_printer( Printer->sharename ) != 0) {
354                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
355                 return WERR_BADFID;
356         }
357
358         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359                                    Printer->sharename );
360 }
361
362 /****************************************************************************
363  Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
365
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367                              int *number, struct share_params **params)
368 {
369         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370
371         if (!Printer) {
372                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
373                         OUR_HANDLE(hnd)));
374                 return false;
375         }
376
377         switch (Printer->printer_type) {
378                 case SPLHND_PRINTER:
379                         DEBUG(4,("short name:%s\n", Printer->sharename));
380                         *number = print_queue_snum(Printer->sharename);
381                         return (*number != -1);
382                 case SPLHND_SERVER:
383                         return false;
384                 default:
385                         return false;
386         }
387 }
388
389 /****************************************************************************
390  Set printer handle type.
391  Check if it's \\server or \\server\printer
392 ****************************************************************************/
393
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
395 {
396         DEBUG(3,("Setting printer type=%s\n", handlename));
397
398         if ( strlen(handlename) < 3 ) {
399                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
400                 return false;
401         }
402
403         /* it's a print server */
404         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405                 DEBUGADD(4,("Printer is a print server\n"));
406                 Printer->printer_type = SPLHND_SERVER;
407         }
408         /* it's a printer (set_printer_hnd_name() will handle port monitors */
409         else {
410                 DEBUGADD(4,("Printer is a printer\n"));
411                 Printer->printer_type = SPLHND_PRINTER;
412         }
413
414         return true;
415 }
416
417 /****************************************************************************
418  Set printer handle name..  Accept names like \\server, \\server\printer,
419  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
420  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421  XcvDataPort() interface.
422 ****************************************************************************/
423
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 {
426         int snum;
427         int n_services=lp_numservices();
428         char *aprinter, *printername;
429         const char *servername;
430         fstring sname;
431         bool found = false;
432         NT_PRINTER_INFO_LEVEL *printer = NULL;
433         WERROR result;
434
435         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436                 (unsigned long)strlen(handlename)));
437
438         aprinter = CONST_DISCARD(char *, handlename);
439         if ( *handlename == '\\' ) {
440                 servername = canon_servername(handlename);
441                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
442                         *aprinter = '\0';
443                         aprinter++;
444                 }
445         } else {
446                 servername = global_myname();
447         }
448
449         /* save the servername to fill in replies on this handle */
450
451         if ( !is_myname_or_ipaddr( servername ) )
452                 return false;
453
454         fstrcpy( Printer->servername, servername );
455
456         if ( Printer->printer_type == SPLHND_SERVER )
457                 return true;
458
459         if ( Printer->printer_type != SPLHND_PRINTER )
460                 return false;
461
462         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
463
464         /* check for the Port Monitor Interface */
465
466         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467                 Printer->printer_type = SPLHND_PORTMON_TCP;
468                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469                 found = true;
470         }
471         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474                 found = true;
475         }
476
477         /* Search all sharenames first as this is easier than pulling
478            the printer_info_2 off of disk. Don't use find_service() since
479            that calls out to map_username() */
480
481         /* do another loop to look for printernames */
482
483         for (snum=0; !found && snum<n_services; snum++) {
484
485                 /* no point going on if this is not a printer */
486
487                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488                         continue;
489
490                 fstrcpy(sname, lp_servicename(snum));
491                 if ( strequal( aprinter, sname ) ) {
492                         found = true;
493                         break;
494                 }
495
496                 /* no point looking up the printer object if
497                    we aren't allowing printername != sharename */
498
499                 if ( lp_force_printername(snum) )
500                         continue;
501
502                 fstrcpy(sname, lp_servicename(snum));
503
504                 printer = NULL;
505
506                 /* This call doesn't fill in the location or comment from
507                  * a CUPS server for efficiency with large numbers of printers.
508                  * JRA.
509                  */
510
511                 result = get_a_printer_search( NULL, &printer, 2, sname );
512                 if ( !W_ERROR_IS_OK(result) ) {
513                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514                                 sname, win_errstr(result)));
515                         continue;
516                 }
517
518                 /* printername is always returned as \\server\printername */
519                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521                                 printer->info_2->printername));
522                         free_a_printer( &printer, 2);
523                         continue;
524                 }
525
526                 printername++;
527
528                 if ( strequal(printername, aprinter) ) {
529                         free_a_printer( &printer, 2);
530                         found = true;
531                         break;
532                 }
533
534                 DEBUGADD(10, ("printername: %s\n", printername));
535
536                 free_a_printer( &printer, 2);
537         }
538
539         free_a_printer( &printer, 2);
540
541         if ( !found ) {
542                 DEBUGADD(4,("Printer not found\n"));
543                 return false;
544         }
545
546         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
547
548         fstrcpy(Printer->sharename, sname);
549
550         return true;
551 }
552
553 /****************************************************************************
554  Find first available printer slot. creates a printer handle for you.
555  ****************************************************************************/
556
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558                              const char *name, uint32_t access_granted)
559 {
560         Printer_entry *new_printer;
561
562         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
563
564         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565         if (new_printer == NULL) {
566                 return false;
567         }
568         talloc_set_destructor(new_printer, printer_entry_destructor);
569
570         if (!create_policy_hnd(p, hnd, new_printer)) {
571                 TALLOC_FREE(new_printer);
572                 return false;
573         }
574
575         /* Add to the internal list. */
576         DLIST_ADD(printers_list, new_printer);
577
578         new_printer->notify.option=NULL;
579
580         if (!set_printer_hnd_printertype(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return false;
583         }
584
585         if (!set_printer_hnd_name(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         new_printer->access_granted = access_granted;
591
592         DEBUG(5, ("%d printer handles active\n",
593                   (int)num_pipe_handles(p->pipe_handles)));
594
595         return true;
596 }
597
598 /***************************************************************************
599  check to see if the client motify handle is monitoring the notification
600  given by (notify_type, notify_field).
601  **************************************************************************/
602
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604                                       uint16_t notify_field)
605 {
606         return true;
607 }
608
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610                                 uint16_t notify_field)
611 {
612         struct spoolss_NotifyOption *option = p->notify.option;
613         uint32_t i, j;
614
615         /*
616          * Flags should always be zero when the change notify
617          * is registered by the client's spooler.  A user Win32 app
618          * might use the flags though instead of the NOTIFY_OPTION_INFO
619          * --jerry
620          */
621
622         if (!option) {
623                 return false;
624         }
625
626         if (p->notify.flags)
627                 return is_monitoring_event_flags(
628                         p->notify.flags, notify_type, notify_field);
629
630         for (i = 0; i < option->count; i++) {
631
632                 /* Check match for notify_type */
633
634                 if (option->types[i].type != notify_type)
635                         continue;
636
637                 /* Check match for field */
638
639                 for (j = 0; j < option->types[i].count; j++) {
640                         if (option->types[i].fields[j].field == notify_field) {
641                                 return true;
642                         }
643                 }
644         }
645
646         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647                    p->servername, p->sharename, notify_type, notify_field));
648
649         return false;
650 }
651
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653         _data->data.integer[0] = _integer; \
654         _data->data.integer[1] = 0;
655
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659         if (!_data->data.string.string) {\
660                 _data->data.string.size = 0; \
661         } \
662         _data->data.string.size = strlen_m_term(_p) * 2;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665         _data->data.devmode.devmode = _devmode;
666
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669         if (!_data->data.sd.sd) { \
670                 _data->data.sd.sd_size = 0; \
671         } \
672         _data->data.sd.sd_size = _size;
673
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
675                                    struct tm *t,
676                                    const char **pp,
677                                    uint32_t *plen)
678 {
679         struct spoolss_Time st;
680         uint32_t len = 16;
681         char *p;
682
683         if (!init_systemtime(&st, t)) {
684                 return;
685         }
686
687         p = talloc_array(mem_ctx, char, len);
688         if (!p) {
689                 return;
690         }
691
692         /*
693          * Systemtime must be linearized as a set of UINT16's.
694          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695          */
696
697         SSVAL(p, 0, st.year);
698         SSVAL(p, 2, st.month);
699         SSVAL(p, 4, st.day_of_week);
700         SSVAL(p, 6, st.day);
701         SSVAL(p, 8, st.hour);
702         SSVAL(p, 10, st.minute);
703         SSVAL(p, 12, st.second);
704         SSVAL(p, 14, st.millisecond);
705
706         *pp = p;
707         *plen = len;
708 }
709
710 /* Convert a notification message to a struct spoolss_Notify */
711
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713                              struct spoolss_Notify *data,
714                              TALLOC_CTX *mem_ctx)
715 {
716         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 }
718
719 static void notify_string(struct spoolss_notify_msg *msg,
720                           struct spoolss_Notify *data,
721                           TALLOC_CTX *mem_ctx)
722 {
723         /* The length of the message includes the trailing \0 */
724
725         data->data.string.size = msg->len * 2;
726         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727         if (!data->data.string.string) {
728                 data->data.string.size = 0;
729                 return;
730         }
731 }
732
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734                                struct spoolss_Notify *data,
735                                TALLOC_CTX *mem_ctx)
736 {
737         data->data.string.string = NULL;
738         data->data.string.size = 0;
739
740         if (msg->len != sizeof(time_t)) {
741                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
742                           msg->len));
743                 return;
744         }
745
746         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747                                &data->data.string.string,
748                                &data->data.string.size);
749 }
750
751 struct notify2_message_table {
752         const char *name;
753         void (*fn)(struct spoolss_notify_msg *msg,
754                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 };
756
757 static struct notify2_message_table printer_notify_table[] = {
758         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 };
778
779 static struct notify2_message_table job_notify_table[] = {
780         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 };
805
806
807 /***********************************************************************
808  Allocate talloc context for container object
809  **********************************************************************/
810
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 {
813         if ( !ctr )
814                 return;
815
816         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817
818         return;
819 }
820
821 /***********************************************************************
822  release all allocated memory and zero out structure
823  **********************************************************************/
824
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 {
827         if ( !ctr )
828                 return;
829
830         if ( ctr->ctx )
831                 talloc_destroy(ctr->ctx);
832
833         ZERO_STRUCTP(ctr);
834
835         return;
836 }
837
838 /***********************************************************************
839  **********************************************************************/
840
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 {
843         if ( !ctr )
844                 return NULL;
845
846         return ctr->ctx;
847 }
848
849 /***********************************************************************
850  **********************************************************************/
851
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
853 {
854         if ( !ctr || !ctr->msg_groups )
855                 return NULL;
856
857         if ( idx >= ctr->num_groups )
858                 return NULL;
859
860         return &ctr->msg_groups[idx];
861
862 }
863
864 /***********************************************************************
865  How many groups of change messages do we have ?
866  **********************************************************************/
867
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 {
870         if ( !ctr )
871                 return 0;
872
873         return ctr->num_groups;
874 }
875
876 /***********************************************************************
877  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878  **********************************************************************/
879
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 {
882         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
883         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
884         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
885         int                             i, new_slot;
886
887         if ( !ctr || !msg )
888                 return 0;
889
890         /* loop over all groups looking for a matching printer name */
891
892         for ( i=0; i<ctr->num_groups; i++ ) {
893                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894                         break;
895         }
896
897         /* add a new group? */
898
899         if ( i == ctr->num_groups ) {
900                 ctr->num_groups++;
901
902                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904                         return 0;
905                 }
906                 ctr->msg_groups = groups;
907
908                 /* clear the new entry and set the printer name */
909
910                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912         }
913
914         /* add the change messages; 'i' is the correct index now regardless */
915
916         msg_grp = &ctr->msg_groups[i];
917
918         msg_grp->num_msgs++;
919
920         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922                 return 0;
923         }
924         msg_grp->msgs = msg_list;
925
926         new_slot = msg_grp->num_msgs-1;
927         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928
929         /* need to allocate own copy of data */
930
931         if ( msg->len != 0 )
932                 msg_grp->msgs[new_slot].notify.data = (char *)
933                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934
935         return ctr->num_groups;
936 }
937
938 /***********************************************************************
939  Send a change notication message on all handles which have a call
940  back registered
941  **********************************************************************/
942
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 {
945         Printer_entry            *p;
946         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
947         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948         SPOOLSS_NOTIFY_MSG       *messages;
949         int                      sending_msg_count;
950
951         if ( !msg_group ) {
952                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953                 return;
954         }
955
956         messages = msg_group->msgs;
957
958         if ( !messages ) {
959                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960                 return;
961         }
962
963         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964
965         /* loop over all printers */
966
967         for (p = printers_list; p; p = p->next) {
968                 struct spoolss_Notify *notifies;
969                 uint32_t count = 0;
970                 uint32_t id;
971                 int     i;
972
973                 /* Is there notification on this handle? */
974
975                 if ( !p->notify.client_connected )
976                         continue;
977
978                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979
980                 /* For this printer?  Print servers always receive
981                    notifications. */
982
983                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
984                     ( !strequal(msg_group->printername, p->sharename) ) )
985                         continue;
986
987                 DEBUG(10,("Our printer\n"));
988
989                 /* allocate the max entries possible */
990
991                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
992                 if (!notifies) {
993                         return;
994                 }
995
996                 /* build the array of change notifications */
997
998                 sending_msg_count = 0;
999
1000                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1002
1003                         /* Are we monitoring this event? */
1004
1005                         if (!is_monitoring_event(p, msg->type, msg->field))
1006                                 continue;
1007
1008                         sending_msg_count++;
1009
1010
1011                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012                                 msg->type, msg->field, p->sharename));
1013
1014                         /*
1015                          * if the is a printer notification handle and not a job notification
1016                          * type, then set the id to 0.  Other wise just use what was specified
1017                          * in the message.
1018                          *
1019                          * When registering change notification on a print server handle
1020                          * we always need to send back the id (snum) matching the printer
1021                          * for which the change took place.  For change notify registered
1022                          * on a printer handle, this does not matter and the id should be 0.
1023                          *
1024                          * --jerry
1025                          */
1026
1027                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028                                 id = 0;
1029                         else
1030                                 id = msg->id;
1031
1032
1033                         /* Convert unix jobid to smb jobid */
1034
1035                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036                                 id = sysjob_to_jobid(msg->id);
1037
1038                                 if (id == -1) {
1039                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040                                         goto done;
1041                                 }
1042                         }
1043
1044                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1045
1046                         switch(msg->type) {
1047                         case PRINTER_NOTIFY_TYPE:
1048                                 if ( printer_notify_table[msg->field].fn )
1049                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1050                                 break;
1051
1052                         case JOB_NOTIFY_TYPE:
1053                                 if ( job_notify_table[msg->field].fn )
1054                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1055                                 break;
1056
1057                         default:
1058                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059                                 goto done;
1060                         }
1061
1062                         count++;
1063                 }
1064
1065                 if ( sending_msg_count ) {
1066                         NTSTATUS status;
1067                         WERROR werr;
1068                         union spoolss_ReplyPrinterInfo info;
1069                         struct spoolss_NotifyInfo info0;
1070                         uint32_t reply_result;
1071
1072                         info0.version   = 0x2;
1073                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074                         info0.count     = count;
1075                         info0.notifies  = notifies;
1076
1077                         info.info0 = &info0;
1078
1079                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080                                                                      &p->notify.client_hnd,
1081                                                                      p->notify.change, /* color */
1082                                                                      p->notify.flags,
1083                                                                      &reply_result,
1084                                                                      0, /* reply_type, must be 0 */
1085                                                                      info,
1086                                                                      &werr);
1087                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089                                         notify_cli_pipe->srv_name_slash,
1090                                         win_errstr(werr)));
1091                         }
1092                         switch (reply_result) {
1093                                 case 0:
1094                                         break;
1095                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1096                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1098                                         break;
1099                                 default:
1100                                         break;
1101                         }
1102                 }
1103         }
1104
1105 done:
1106         DEBUG(8,("send_notify2_changes: Exit...\n"));
1107         return;
1108 }
1109
1110 /***********************************************************************
1111  **********************************************************************/
1112
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 {
1115
1116         uint32_t tv_sec, tv_usec;
1117         size_t offset = 0;
1118
1119         /* Unpack message */
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122                              msg->printer);
1123
1124         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1125                                 &tv_sec, &tv_usec,
1126                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127
1128         if (msg->len == 0)
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130                            &msg->notify.value[0], &msg->notify.value[1]);
1131         else
1132                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133                            &msg->len, &msg->notify.data);
1134
1135         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1137
1138         tv->tv_sec = tv_sec;
1139         tv->tv_usec = tv_usec;
1140
1141         if (msg->len == 0)
1142                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143                           msg->notify.value[1]));
1144         else
1145                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1146
1147         return true;
1148 }
1149
1150 /********************************************************************
1151  Receive a notify2 message list
1152  ********************************************************************/
1153
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1155                                          void *private_data,
1156                                          uint32_t msg_type,
1157                                          struct server_id server_id,
1158                                          DATA_BLOB *data)
1159 {
1160         size_t                  msg_count, i;
1161         char                    *buf = (char *)data->data;
1162         char                    *msg_ptr;
1163         size_t                  msg_len;
1164         SPOOLSS_NOTIFY_MSG      notify;
1165         SPOOLSS_NOTIFY_MSG_CTR  messages;
1166         int                     num_groups;
1167
1168         if (data->length < 4) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170                 return;
1171         }
1172
1173         msg_count = IVAL(buf, 0);
1174         msg_ptr = buf + 4;
1175
1176         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1177
1178         if (msg_count == 0) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180                 return;
1181         }
1182
1183         /* initialize the container */
1184
1185         ZERO_STRUCT( messages );
1186         notify_msg_ctr_init( &messages );
1187
1188         /*
1189          * build message groups for each printer identified
1190          * in a change_notify msg.  Remember that a PCN message
1191          * includes the handle returned for the srv_spoolss_replyopenprinter()
1192          * call.  Therefore messages are grouped according to printer handle.
1193          */
1194
1195         for ( i=0; i<msg_count; i++ ) {
1196                 struct timeval msg_tv;
1197
1198                 if (msg_ptr + 4 - buf > data->length) {
1199                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200                         return;
1201                 }
1202
1203                 msg_len = IVAL(msg_ptr,0);
1204                 msg_ptr += 4;
1205
1206                 if (msg_ptr + msg_len - buf > data->length) {
1207                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208                         return;
1209                 }
1210
1211                 /* unpack messages */
1212
1213                 ZERO_STRUCT( notify );
1214                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215                 msg_ptr += msg_len;
1216
1217                 /* add to correct list in container */
1218
1219                 notify_msg_ctr_addmsg( &messages, &notify );
1220
1221                 /* free memory that might have been allocated by notify2_unpack_msg() */
1222
1223                 if ( notify.len != 0 )
1224                         SAFE_FREE( notify.notify.data );
1225         }
1226
1227         /* process each group of messages */
1228
1229         num_groups = notify_msg_ctr_numgroups( &messages );
1230         for ( i=0; i<num_groups; i++ )
1231                 send_notify2_changes( &messages, i );
1232
1233
1234         /* cleanup */
1235
1236         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237                 (uint32_t)msg_count ));
1238
1239         notify_msg_ctr_destroy( &messages );
1240
1241         return;
1242 }
1243
1244 /********************************************************************
1245  Send a message to ourself about new driver being installed
1246  so we can upgrade the information for each printer bound to this
1247  driver
1248  ********************************************************************/
1249
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1251 {
1252         int len = strlen(drivername);
1253
1254         if (!len)
1255                 return false;
1256
1257         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258                 drivername));
1259
1260         messaging_send_buf(smbd_messaging_context(), procid_self(),
1261                            MSG_PRINTER_DRVUPGRADE,
1262                            (uint8_t *)drivername, len+1);
1263
1264         return true;
1265 }
1266
1267 /**********************************************************************
1268  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269  over all printers, upgrading ones as necessary
1270  **********************************************************************/
1271
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1273                             void *private_data,
1274                             uint32_t msg_type,
1275                             struct server_id server_id,
1276                             DATA_BLOB *data)
1277 {
1278         fstring drivername;
1279         int snum;
1280         int n_services = lp_numservices();
1281         size_t len;
1282
1283         len = MIN(data->length,sizeof(drivername)-1);
1284         strncpy(drivername, (const char *)data->data, len);
1285
1286         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287
1288         /* Iterate the printer list */
1289
1290         for (snum=0; snum<n_services; snum++)
1291         {
1292                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293                 {
1294                         WERROR result;
1295                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1296
1297                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298                         if (!W_ERROR_IS_OK(result))
1299                                 continue;
1300
1301                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302                         {
1303                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304
1305                                 /* all we care about currently is the change_id */
1306
1307                                 result = mod_a_printer(printer, 2);
1308                                 if (!W_ERROR_IS_OK(result)) {
1309                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310                                                 win_errstr(result)));
1311                                 }
1312                         }
1313
1314                         free_a_printer(&printer, 2);
1315                 }
1316         }
1317
1318         /* all done */
1319 }
1320
1321 /********************************************************************
1322  Update the cache for all printq's with a registered client
1323  connection
1324  ********************************************************************/
1325
1326 void update_monitored_printq_cache( void )
1327 {
1328         Printer_entry *printer = printers_list;
1329         int snum;
1330
1331         /* loop through all printers and update the cache where
1332            client_connected == true */
1333         while ( printer )
1334         {
1335                 if ( (printer->printer_type == SPLHND_PRINTER)
1336                         && printer->notify.client_connected )
1337                 {
1338                         snum = print_queue_snum(printer->sharename);
1339                         print_queue_status( snum, NULL, NULL );
1340                 }
1341
1342                 printer = printer->next;
1343         }
1344
1345         return;
1346 }
1347 /********************************************************************
1348  Send a message to ourself about new driver being installed
1349  so we can upgrade the information for each printer bound to this
1350  driver
1351  ********************************************************************/
1352
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 {
1355         int len = strlen(drivername);
1356
1357         if (!len)
1358                 return false;
1359
1360         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361                 drivername));
1362
1363         messaging_send_buf(smbd_messaging_context(), procid_self(),
1364                            MSG_PRINTERDATA_INIT_RESET,
1365                            (uint8_t *)drivername, len+1);
1366
1367         return true;
1368 }
1369
1370 /**********************************************************************
1371  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372  over all printers, resetting printer data as neessary
1373  **********************************************************************/
1374
1375 void reset_all_printerdata(struct messaging_context *msg,
1376                            void *private_data,
1377                            uint32_t msg_type,
1378                            struct server_id server_id,
1379                            DATA_BLOB *data)
1380 {
1381         fstring drivername;
1382         int snum;
1383         int n_services = lp_numservices();
1384         size_t len;
1385
1386         len = MIN( data->length, sizeof(drivername)-1 );
1387         strncpy( drivername, (const char *)data->data, len );
1388
1389         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390
1391         /* Iterate the printer list */
1392
1393         for ( snum=0; snum<n_services; snum++ )
1394         {
1395                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396                 {
1397                         WERROR result;
1398                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1399
1400                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401                         if ( !W_ERROR_IS_OK(result) )
1402                                 continue;
1403
1404                         /*
1405                          * if the printer is bound to the driver,
1406                          * then reset to the new driver initdata
1407                          */
1408
1409                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410                         {
1411                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412
1413                                 if ( !set_driver_init(printer, 2) ) {
1414                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415                                                 printer->info_2->printername, printer->info_2->drivername));
1416                                 }
1417
1418                                 result = mod_a_printer( printer, 2 );
1419                                 if ( !W_ERROR_IS_OK(result) ) {
1420                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1421                                                 get_dos_error_msg(result)));
1422                                 }
1423                         }
1424
1425                         free_a_printer( &printer, 2 );
1426                 }
1427         }
1428
1429         /* all done */
1430
1431         return;
1432 }
1433
1434 /****************************************************************
1435  _spoolss_OpenPrinter
1436 ****************************************************************/
1437
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439                             struct spoolss_OpenPrinter *r)
1440 {
1441         struct spoolss_OpenPrinterEx e;
1442         WERROR werr;
1443
1444         ZERO_STRUCT(e.in.userlevel);
1445
1446         e.in.printername        = r->in.printername;
1447         e.in.datatype           = r->in.datatype;
1448         e.in.devmode_ctr        = r->in.devmode_ctr;
1449         e.in.access_mask        = r->in.access_mask;
1450         e.in.level              = 0;
1451
1452         e.out.handle            = r->out.handle;
1453
1454         werr = _spoolss_OpenPrinterEx(p, &e);
1455
1456         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457                 /* OpenPrinterEx returns this for a bad
1458                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1459                  * instead.
1460                  */
1461                 werr = WERR_INVALID_PRINTER_NAME;
1462         }
1463
1464         return werr;
1465 }
1466
1467 /********************************************************************
1468  ********************************************************************/
1469
1470 bool convert_devicemode(const char *printername,
1471                         const struct spoolss_DeviceMode *devmode,
1472                         NT_DEVICEMODE **pp_nt_devmode)
1473 {
1474         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475
1476         /*
1477          * Ensure nt_devmode is a valid pointer
1478          * as we will be overwriting it.
1479          */
1480
1481         if (nt_devmode == NULL) {
1482                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484                         return false;
1485         }
1486
1487         fstrcpy(nt_devmode->devicename, devmode->devicename);
1488         fstrcpy(nt_devmode->formname, devmode->formname);
1489
1490         nt_devmode->devicename[31] = '\0';
1491         nt_devmode->formname[31] = '\0';
1492
1493         nt_devmode->specversion         = devmode->specversion;
1494         nt_devmode->driverversion       = devmode->driverversion;
1495         nt_devmode->size                = devmode->size;
1496         nt_devmode->fields              = devmode->fields;
1497         nt_devmode->orientation         = devmode->orientation;
1498         nt_devmode->papersize           = devmode->papersize;
1499         nt_devmode->paperlength         = devmode->paperlength;
1500         nt_devmode->paperwidth          = devmode->paperwidth;
1501         nt_devmode->scale               = devmode->scale;
1502         nt_devmode->copies              = devmode->copies;
1503         nt_devmode->defaultsource       = devmode->defaultsource;
1504         nt_devmode->printquality        = devmode->printquality;
1505         nt_devmode->color               = devmode->color;
1506         nt_devmode->duplex              = devmode->duplex;
1507         nt_devmode->yresolution         = devmode->yresolution;
1508         nt_devmode->ttoption            = devmode->ttoption;
1509         nt_devmode->collate             = devmode->collate;
1510
1511         nt_devmode->logpixels           = devmode->logpixels;
1512         nt_devmode->bitsperpel          = devmode->bitsperpel;
1513         nt_devmode->pelswidth           = devmode->pelswidth;
1514         nt_devmode->pelsheight          = devmode->pelsheight;
1515         nt_devmode->displayflags        = devmode->displayflags;
1516         nt_devmode->displayfrequency    = devmode->displayfrequency;
1517         nt_devmode->icmmethod           = devmode->icmmethod;
1518         nt_devmode->icmintent           = devmode->icmintent;
1519         nt_devmode->mediatype           = devmode->mediatype;
1520         nt_devmode->dithertype          = devmode->dithertype;
1521         nt_devmode->reserved1           = devmode->reserved1;
1522         nt_devmode->reserved2           = devmode->reserved2;
1523         nt_devmode->panningwidth        = devmode->panningwidth;
1524         nt_devmode->panningheight       = devmode->panningheight;
1525
1526         /*
1527          * Only change private and driverextra if the incoming devmode
1528          * has a new one. JRA.
1529          */
1530
1531         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532                 SAFE_FREE(nt_devmode->nt_dev_private);
1533                 nt_devmode->driverextra = devmode->__driverextra_length;
1534                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1535                         return false;
1536                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1537         }
1538
1539         *pp_nt_devmode = nt_devmode;
1540
1541         return true;
1542 }
1543
1544 /****************************************************************
1545  _spoolss_OpenPrinterEx
1546 ****************************************************************/
1547
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549                               struct spoolss_OpenPrinterEx *r)
1550 {
1551         int snum;
1552         Printer_entry *Printer=NULL;
1553
1554         if (!r->in.printername) {
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         /* some sanity check because you can open a printer or a print server */
1559         /* aka: \\server\printer or \\server */
1560
1561         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1562
1563         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564                 ZERO_STRUCTP(r->out.handle);
1565                 return WERR_INVALID_PARAM;
1566         }
1567
1568         Printer = find_printer_index_by_hnd(p, r->out.handle);
1569         if ( !Printer ) {
1570                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1571                         "handle we created for printer %s\n", r->in.printername));
1572                 close_printer_handle(p, r->out.handle);
1573                 ZERO_STRUCTP(r->out.handle);
1574                 return WERR_INVALID_PARAM;
1575         }
1576
1577         /*
1578          * First case: the user is opening the print server:
1579          *
1580          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1582          *
1583          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585          * or if the user is listed in the smb.conf printer admin parameter.
1586          *
1587          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588          * client view printer folder, but does not show the MSAPW.
1589          *
1590          * Note: this test needs code to check access rights here too. Jeremy
1591          * could you look at this?
1592          *
1593          * Second case: the user is opening a printer:
1594          * NT doesn't let us connect to a printer if the connecting user
1595          * doesn't have print permission.
1596          *
1597          * Third case: user is opening a Port Monitor
1598          * access checks same as opening a handle to the print server.
1599          */
1600
1601         switch (Printer->printer_type )
1602         {
1603         case SPLHND_SERVER:
1604         case SPLHND_PORTMON_TCP:
1605         case SPLHND_PORTMON_LOCAL:
1606                 /* Printserver handles use global struct... */
1607
1608                 snum = -1;
1609
1610                 /* Map standard access rights to object specific access rights */
1611
1612                 se_map_standard(&r->in.access_mask,
1613                                 &printserver_std_mapping);
1614
1615                 /* Deny any object specific bits that don't apply to print
1616                    servers (i.e printer and job specific bits) */
1617
1618                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1619
1620                 if (r->in.access_mask &
1621                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623                         close_printer_handle(p, r->out.handle);
1624                         ZERO_STRUCTP(r->out.handle);
1625                         return WERR_ACCESS_DENIED;
1626                 }
1627
1628                 /* Allow admin access */
1629
1630                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1631                 {
1632                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1633
1634                         if (!lp_ms_add_printer_wizard()) {
1635                                 close_printer_handle(p, r->out.handle);
1636                                 ZERO_STRUCTP(r->out.handle);
1637                                 return WERR_ACCESS_DENIED;
1638                         }
1639
1640                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641                            and not a printer admin, then fail */
1642
1643                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644                             !user_has_privileges(p->server_info->ptok,
1645                                                  &se_printop ) &&
1646                             !token_contains_name_in_list(
1647                                     uidtoname(p->server_info->utok.uid),
1648                                     NULL, NULL,
1649                                     p->server_info->ptok,
1650                                     lp_printer_admin(snum))) {
1651                                 close_printer_handle(p, r->out.handle);
1652                                 ZERO_STRUCTP(r->out.handle);
1653                                 return WERR_ACCESS_DENIED;
1654                         }
1655
1656                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657                 }
1658                 else
1659                 {
1660                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661                 }
1662
1663                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1665
1666                 /* We fall through to return WERR_OK */
1667                 break;
1668
1669         case SPLHND_PRINTER:
1670                 /* NT doesn't let us connect to a printer if the connecting user
1671                    doesn't have print permission.  */
1672
1673                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674                         close_printer_handle(p, r->out.handle);
1675                         ZERO_STRUCTP(r->out.handle);
1676                         return WERR_BADFID;
1677                 }
1678
1679                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681                 }
1682
1683                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1684
1685                 /* map an empty access mask to the minimum access mask */
1686                 if (r->in.access_mask == 0x0)
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688
1689                 /*
1690                  * If we are not serving the printer driver for this printer,
1691                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1692                  * will keep NT clients happy  --jerry
1693                  */
1694
1695                 if (lp_use_client_driver(snum)
1696                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1697                 {
1698                         r->in.access_mask = PRINTER_ACCESS_USE;
1699                 }
1700
1701                 /* check smb.conf parameters and the the sec_desc */
1702
1703                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708
1709                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710                                    p->server_info->ptok, snum) ||
1711                     !print_access_check(p->server_info, snum,
1712                                         r->in.access_mask)) {
1713                         DEBUG(3, ("access DENIED for printer open\n"));
1714                         close_printer_handle(p, r->out.handle);
1715                         ZERO_STRUCTP(r->out.handle);
1716                         return WERR_ACCESS_DENIED;
1717                 }
1718
1719                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721                         close_printer_handle(p, r->out.handle);
1722                         ZERO_STRUCTP(r->out.handle);
1723                         return WERR_ACCESS_DENIED;
1724                 }
1725
1726                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1728                 else
1729                         r->in.access_mask = PRINTER_ACCESS_USE;
1730
1731                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1733
1734                 break;
1735
1736         default:
1737                 /* sanity check to prevent programmer error */
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_BADFID;
1740         }
1741
1742         Printer->access_granted = r->in.access_mask;
1743
1744         /*
1745          * If the client sent a devmode in the OpenPrinter() call, then
1746          * save it here in case we get a job submission on this handle
1747          */
1748
1749          if ((Printer->printer_type != SPLHND_SERVER) &&
1750              r->in.devmode_ctr.devmode) {
1751                 convert_devicemode(Printer->sharename,
1752                                    r->in.devmode_ctr.devmode,
1753                                    &Printer->nt_devmode);
1754          }
1755
1756 #if 0   /* JERRY -- I'm doubtful this is really effective */
1757         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758            optimization in Windows 2000 clients  --jerry */
1759
1760         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761                 && (RA_WIN2K == get_remote_arch()) )
1762         {
1763                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764                 sys_usleep( 500000 );
1765         }
1766 #endif
1767
1768         return WERR_OK;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775                                               NT_PRINTER_INFO_LEVEL_2 *d)
1776 {
1777         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1778
1779         if (!r || !d) {
1780                 return false;
1781         }
1782
1783         d->attributes           = r->attributes;
1784         d->priority             = r->priority;
1785         d->default_priority     = r->defaultpriority;
1786         d->starttime            = r->starttime;
1787         d->untiltime            = r->untiltime;
1788         d->status               = r->status;
1789         d->cjobs                = r->cjobs;
1790
1791         fstrcpy(d->servername,  r->servername);
1792         fstrcpy(d->printername, r->printername);
1793         fstrcpy(d->sharename,   r->sharename);
1794         fstrcpy(d->portname,    r->portname);
1795         fstrcpy(d->drivername,  r->drivername);
1796         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797         fstrcpy(d->location,    r->location);
1798         fstrcpy(d->sepfile,     r->sepfile);
1799         fstrcpy(d->printprocessor, r->printprocessor);
1800         fstrcpy(d->datatype,    r->datatype);
1801         fstrcpy(d->parameters,  r->parameters);
1802
1803         return true;
1804 }
1805
1806 /****************************************************************************
1807 ****************************************************************************/
1808
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810                                  NT_PRINTER_INFO_LEVEL *printer)
1811 {
1812         bool ret;
1813
1814         switch (info_ctr->level) {
1815         case 2:
1816                 /* allocate memory if needed.  Messy because
1817                    convert_printer_info is used to update an existing
1818                    printer or build a new one */
1819
1820                 if (!printer->info_2) {
1821                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822                         if (!printer->info_2) {
1823                                 DEBUG(0,("convert_printer_info: "
1824                                         "talloc() failed!\n"));
1825                                 return false;
1826                         }
1827                 }
1828
1829                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1830                                                         printer->info_2);
1831                 printer->info_2->setuptime = time(NULL);
1832                 return ret;
1833         }
1834
1835         return false;
1836 }
1837
1838 /****************************************************************
1839  _spoolss_ClosePrinter
1840 ****************************************************************/
1841
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843                              struct spoolss_ClosePrinter *r)
1844 {
1845         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1846
1847         if (Printer && Printer->document_started) {
1848                 struct spoolss_EndDocPrinter e;
1849
1850                 e.in.handle = r->in.handle;
1851
1852                 _spoolss_EndDocPrinter(p, &e);
1853         }
1854
1855         if (!close_printer_handle(p, r->in.handle))
1856                 return WERR_BADFID;
1857
1858         /* clear the returned printer handle.  Observed behavior
1859            from Win2k server.  Don't think this really matters.
1860            Previous code just copied the value of the closed
1861            handle.    --jerry */
1862
1863         ZERO_STRUCTP(r->out.handle);
1864
1865         return WERR_OK;
1866 }
1867
1868 /****************************************************************
1869  _spoolss_DeletePrinter
1870 ****************************************************************/
1871
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873                               struct spoolss_DeletePrinter *r)
1874 {
1875         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1876         WERROR result;
1877
1878         if (Printer && Printer->document_started) {
1879                 struct spoolss_EndDocPrinter e;
1880
1881                 e.in.handle = r->in.handle;
1882
1883                 _spoolss_EndDocPrinter(p, &e);
1884         }
1885
1886         result = delete_printer_handle(p, r->in.handle);
1887
1888         update_c_setprinter(false);
1889
1890         return result;
1891 }
1892
1893 /*******************************************************************
1894  * static function to lookup the version id corresponding to an
1895  * long architecture string
1896  ******************************************************************/
1897
1898 static const struct print_architecture_table_node archi_table[]= {
1899
1900         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1901         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1902         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1903         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1904         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1905         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1906         {"Windows x64",          SPL_ARCH_X64,          3 },
1907         {NULL,                   "",            -1 }
1908 };
1909
1910 static int get_version_id(const char *arch)
1911 {
1912         int i;
1913
1914         for (i=0; archi_table[i].long_archi != NULL; i++)
1915         {
1916                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917                         return (archi_table[i].version);
1918         }
1919
1920         return -1;
1921 }
1922
1923 /****************************************************************
1924  _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1926
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928                                     struct spoolss_DeletePrinterDriver *r)
1929 {
1930
1931         union spoolss_DriverInfo *info = NULL;
1932         union spoolss_DriverInfo *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, 3, 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, 3,
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->info3)) {
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, 3,
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->info3, 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->info3, 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         union spoolss_DriverInfo        *info = NULL;
2030         union spoolss_DriverInfo        *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, 3, 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, 3, 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->info3) ) {
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->info3) & (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, 3,
2115                                                        r->in.driver,
2116                                                        r->in.architecture, 3)))
2117                 {
2118
2119                         if ( delete_files && printer_driver_files_in_use(info, &info_win2k->info3) & (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->info3, 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->info3, 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         return WERR_INVALID_PARAM;
2309 }
2310
2311 /****************************************************************
2312  _spoolss_GetPrinterData
2313 ****************************************************************/
2314
2315 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2316                                struct spoolss_GetPrinterData *r)
2317 {
2318         WERROR result;
2319         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2320         NT_PRINTER_INFO_LEVEL *printer = NULL;
2321         int snum = 0;
2322
2323         /*
2324          * Reminder: when it's a string, the length is in BYTES
2325          * even if UNICODE is negociated.
2326          *
2327          * JFM, 4/19/1999
2328          */
2329
2330         /* in case of problem, return some default values */
2331
2332         *r->out.needed  = 0;
2333         *r->out.type    = 0;
2334
2335         DEBUG(4,("_spoolss_GetPrinterData\n"));
2336
2337         if (!Printer) {
2338                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2339                         OUR_HANDLE(r->in.handle)));
2340                 result = WERR_BADFID;
2341                 goto done;
2342         }
2343
2344         if (Printer->printer_type == SPLHND_SERVER) {
2345                 result = getprinterdata_printer_server(p->mem_ctx,
2346                                                        r->in.value_name,
2347                                                        r->out.type,
2348                                                        r->out.data);
2349         } else {
2350                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2351                         result = WERR_BADFID;
2352                         goto done;
2353                 }
2354
2355                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2356                 if (!W_ERROR_IS_OK(result)) {
2357                         goto done;
2358                 }
2359
2360                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2361
2362                 if (strequal(r->in.value_name, "ChangeId")) {
2363                         *r->out.type = REG_DWORD;
2364                         r->out.data->value = printer->info_2->changeid;
2365                         result = WERR_OK;
2366                 } else {
2367                         struct regval_blob *v;
2368                         DATA_BLOB blob;
2369
2370                         v = get_printer_data(printer->info_2,
2371                                              SPOOL_PRINTERDATA_KEY,
2372                                              r->in.value_name);
2373                         if (!v) {
2374                                 result = WERR_BADFILE;
2375                                 goto done;
2376                         }
2377
2378                         *r->out.type = v->type;
2379
2380                         blob = data_blob_const(v->data_p, v->size);
2381
2382                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2383                                                           r->out.data,
2384                                                           *r->out.type);
2385                 }
2386         }
2387
2388  done:
2389         /* cleanup & exit */
2390
2391         if (printer) {
2392                 free_a_printer(&printer, 2);
2393         }
2394
2395         if (!W_ERROR_IS_OK(result)) {
2396                 return result;
2397         }
2398
2399         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2400         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2401         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2402
2403         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2404 }
2405
2406 /*********************************************************
2407  Connect to the client machine.
2408 **********************************************************/
2409
2410 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2411                         struct sockaddr_storage *client_ss, const char *remote_machine)
2412 {
2413         NTSTATUS ret;
2414         struct cli_state *the_cli;
2415         struct sockaddr_storage rm_addr;
2416
2417         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2418                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2419                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2420                         return false;
2421                 }
2422
2423                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2424                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2425                         return false;
2426                 }
2427         } else {
2428                 char addr[INET6_ADDRSTRLEN];
2429                 rm_addr = *client_ss;
2430                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2431                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2432                         addr));
2433         }
2434
2435         /* setup the connection */
2436
2437         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2438                 &rm_addr, 0, "IPC$", "IPC",
2439                 "", /* username */
2440                 "", /* domain */
2441                 "", /* password */
2442                 0, lp_client_signing(), NULL );
2443
2444         if ( !NT_STATUS_IS_OK( ret ) ) {
2445                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2446                         remote_machine ));
2447                 return false;
2448         }
2449
2450         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2451                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2452                 cli_shutdown(the_cli);
2453                 return false;
2454         }
2455
2456         /*
2457          * Ok - we have an anonymous connection to the IPC$ share.
2458          * Now start the NT Domain stuff :-).
2459          */
2460
2461         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2462         if (!NT_STATUS_IS_OK(ret)) {
2463                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2464                         remote_machine, nt_errstr(ret)));
2465                 cli_shutdown(the_cli);
2466                 return false;
2467         }
2468
2469         return true;
2470 }
2471
2472 /***************************************************************************
2473  Connect to the client.
2474 ****************************************************************************/
2475
2476 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2477                                         uint32_t localprinter, uint32_t type,
2478                                         struct policy_handle *handle,
2479                                         struct sockaddr_storage *client_ss)
2480 {
2481         WERROR result;
2482         NTSTATUS status;
2483
2484         /*
2485          * If it's the first connection, contact the client
2486          * and connect to the IPC$ share anonymously
2487          */
2488         if (smb_connections==0) {
2489                 fstring unix_printer;
2490
2491                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2492
2493                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2494                         return false;
2495
2496                 messaging_register(smbd_messaging_context(), NULL,
2497                                    MSG_PRINTER_NOTIFY2,
2498                                    receive_notify2_message_list);
2499                 /* Tell the connections db we're now interested in printer
2500                  * notify messages. */
2501                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2502         }
2503
2504         /*
2505          * Tell the specific printing tdb we want messages for this printer
2506          * by registering our PID.
2507          */
2508
2509         if (!print_notify_register_pid(snum))
2510                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2511
2512         smb_connections++;
2513
2514         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2515                                                  printer,
2516                                                  localprinter,
2517                                                  type,
2518                                                  0,
2519                                                  NULL,
2520                                                  handle,
2521                                                  &result);
2522         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2523                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2524                         win_errstr(result)));
2525
2526         return (W_ERROR_IS_OK(result));
2527 }
2528
2529 /****************************************************************
2530  ****************************************************************/
2531
2532 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2533                                                              const struct spoolss_NotifyOption *r)
2534 {
2535         struct spoolss_NotifyOption *option;
2536         uint32_t i,k;
2537
2538         if (!r) {
2539                 return NULL;
2540         }
2541
2542         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2543         if (!option) {
2544                 return NULL;
2545         }
2546
2547         *option = *r;
2548
2549         if (!option->count) {
2550                 return option;
2551         }
2552
2553         option->types = talloc_zero_array(option,
2554                 struct spoolss_NotifyOptionType, option->count);
2555         if (!option->types) {
2556                 talloc_free(option);
2557                 return NULL;
2558         }
2559
2560         for (i=0; i < option->count; i++) {
2561                 option->types[i] = r->types[i];
2562
2563                 if (option->types[i].count) {
2564                         option->types[i].fields = talloc_zero_array(option,
2565                                 union spoolss_Field, option->types[i].count);
2566                         if (!option->types[i].fields) {
2567                                 talloc_free(option);
2568                                 return NULL;
2569                         }
2570                         for (k=0; k<option->types[i].count; k++) {
2571                                 option->types[i].fields[k] =
2572                                         r->types[i].fields[k];
2573                         }
2574                 }
2575         }
2576
2577         return option;
2578 }
2579
2580 /****************************************************************
2581  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2582  *
2583  * before replying OK: status=0 a rpc call is made to the workstation
2584  * asking ReplyOpenPrinter
2585  *
2586  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2587  * called from api_spoolss_rffpcnex
2588 ****************************************************************/
2589
2590 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2591                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2592 {
2593         int snum = -1;
2594         struct spoolss_NotifyOption *option = r->in.notify_options;
2595         struct sockaddr_storage client_ss;
2596
2597         /* store the notify value in the printer struct */
2598
2599         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2600
2601         if (!Printer) {
2602                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2603                         "Invalid handle (%s:%u:%u).\n",
2604                         OUR_HANDLE(r->in.handle)));
2605                 return WERR_BADFID;
2606         }
2607
2608         Printer->notify.flags           = r->in.flags;
2609         Printer->notify.options         = r->in.options;
2610         Printer->notify.printerlocal    = r->in.printer_local;
2611
2612         TALLOC_FREE(Printer->notify.option);
2613         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2614
2615         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2616
2617         /* Connect to the client machine and send a ReplyOpenPrinter */
2618
2619         if ( Printer->printer_type == SPLHND_SERVER)
2620                 snum = -1;
2621         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2622                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2623                 return WERR_BADFID;
2624
2625         if (!interpret_string_addr(&client_ss, p->client_address,
2626                                    AI_NUMERICHOST)) {
2627                 return WERR_SERVER_UNAVAILABLE;
2628         }
2629
2630         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2631                                         Printer->notify.printerlocal, 1,
2632                                         &Printer->notify.client_hnd, &client_ss))
2633                 return WERR_SERVER_UNAVAILABLE;
2634
2635         Printer->notify.client_connected = true;
2636
2637         return WERR_OK;
2638 }
2639
2640 /*******************************************************************
2641  * fill a notify_info_data with the servername
2642  ********************************************************************/
2643
2644 void spoolss_notify_server_name(int snum,
2645                                        struct spoolss_Notify *data,
2646                                        print_queue_struct *queue,
2647                                        NT_PRINTER_INFO_LEVEL *printer,
2648                                        TALLOC_CTX *mem_ctx)
2649 {
2650         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2651 }
2652
2653 /*******************************************************************
2654  * fill a notify_info_data with the printername (not including the servername).
2655  ********************************************************************/
2656
2657 void spoolss_notify_printer_name(int snum,
2658                                         struct spoolss_Notify *data,
2659                                         print_queue_struct *queue,
2660                                         NT_PRINTER_INFO_LEVEL *printer,
2661                                         TALLOC_CTX *mem_ctx)
2662 {
2663         /* the notify name should not contain the \\server\ part */
2664         char *p = strrchr(printer->info_2->printername, '\\');
2665
2666         if (!p) {
2667                 p = printer->info_2->printername;
2668         } else {
2669                 p++;
2670         }
2671
2672         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2673 }
2674
2675 /*******************************************************************
2676  * fill a notify_info_data with the servicename
2677  ********************************************************************/
2678
2679 void spoolss_notify_share_name(int snum,
2680                                       struct spoolss_Notify *data,
2681                                       print_queue_struct *queue,
2682                                       NT_PRINTER_INFO_LEVEL *printer,
2683                                       TALLOC_CTX *mem_ctx)
2684 {
2685         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2686 }
2687
2688 /*******************************************************************
2689  * fill a notify_info_data with the port name
2690  ********************************************************************/
2691
2692 void spoolss_notify_port_name(int snum,
2693                                      struct spoolss_Notify *data,
2694                                      print_queue_struct *queue,
2695                                      NT_PRINTER_INFO_LEVEL *printer,
2696                                      TALLOC_CTX *mem_ctx)
2697 {
2698         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2699 }
2700
2701 /*******************************************************************
2702  * fill a notify_info_data with the printername
2703  * but it doesn't exist, have to see what to do
2704  ********************************************************************/
2705
2706 void spoolss_notify_driver_name(int snum,
2707                                        struct spoolss_Notify *data,
2708                                        print_queue_struct *queue,
2709                                        NT_PRINTER_INFO_LEVEL *printer,
2710                                        TALLOC_CTX *mem_ctx)
2711 {
2712         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2713 }
2714
2715 /*******************************************************************
2716  * fill a notify_info_data with the comment
2717  ********************************************************************/
2718
2719 void spoolss_notify_comment(int snum,
2720                                    struct spoolss_Notify *data,
2721                                    print_queue_struct *queue,
2722                                    NT_PRINTER_INFO_LEVEL *printer,
2723                                    TALLOC_CTX *mem_ctx)
2724 {
2725         char *p;
2726
2727         if (*printer->info_2->comment == '\0') {
2728                 p = lp_comment(snum);
2729         } else {
2730                 p = printer->info_2->comment;
2731         }
2732
2733         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2734 }
2735
2736 /*******************************************************************
2737  * fill a notify_info_data with the comment
2738  * location = "Room 1, floor 2, building 3"
2739  ********************************************************************/
2740
2741 void spoolss_notify_location(int snum,
2742                                     struct spoolss_Notify *data,
2743                                     print_queue_struct *queue,
2744                                     NT_PRINTER_INFO_LEVEL *printer,
2745                                     TALLOC_CTX *mem_ctx)
2746 {
2747         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2748 }
2749
2750 /*******************************************************************
2751  * fill a notify_info_data with the device mode
2752  * jfm:xxxx don't to it for know but that's a real problem !!!
2753  ********************************************************************/
2754
2755 static void spoolss_notify_devmode(int snum,
2756                                    struct spoolss_Notify *data,
2757                                    print_queue_struct *queue,
2758                                    NT_PRINTER_INFO_LEVEL *printer,
2759                                    TALLOC_CTX *mem_ctx)
2760 {
2761         /* for a dummy implementation we have to zero the fields */
2762         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2763 }
2764
2765 /*******************************************************************
2766  * fill a notify_info_data with the separator file name
2767  ********************************************************************/
2768
2769 void spoolss_notify_sepfile(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_STRING(data, printer->info_2->sepfile);
2776 }
2777
2778 /*******************************************************************
2779  * fill a notify_info_data with the print processor
2780  * jfm:xxxx return always winprint to indicate we don't do anything to it
2781  ********************************************************************/
2782
2783 void spoolss_notify_print_processor(int snum,
2784                                            struct spoolss_Notify *data,
2785                                            print_queue_struct *queue,
2786                                            NT_PRINTER_INFO_LEVEL *printer,
2787                                            TALLOC_CTX *mem_ctx)
2788 {
2789         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2790 }
2791
2792 /*******************************************************************
2793  * fill a notify_info_data with the print processor options
2794  * jfm:xxxx send an empty string
2795  ********************************************************************/
2796
2797 void spoolss_notify_parameters(int snum,
2798                                       struct spoolss_Notify *data,
2799                                       print_queue_struct *queue,
2800                                       NT_PRINTER_INFO_LEVEL *printer,
2801                                       TALLOC_CTX *mem_ctx)
2802 {
2803         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2804 }
2805
2806 /*******************************************************************
2807  * fill a notify_info_data with the data type
2808  * jfm:xxxx always send RAW as data type
2809  ********************************************************************/
2810
2811 void spoolss_notify_datatype(int snum,
2812                                     struct spoolss_Notify *data,
2813                                     print_queue_struct *queue,
2814                                     NT_PRINTER_INFO_LEVEL *printer,
2815                                     TALLOC_CTX *mem_ctx)
2816 {
2817         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2818 }
2819
2820 /*******************************************************************
2821  * fill a notify_info_data with the security descriptor
2822  * jfm:xxxx send an null pointer to say no security desc
2823  * have to implement security before !
2824  ********************************************************************/
2825
2826 static void spoolss_notify_security_desc(int snum,
2827                                          struct spoolss_Notify *data,
2828                                          print_queue_struct *queue,
2829                                          NT_PRINTER_INFO_LEVEL *printer,
2830                                          TALLOC_CTX *mem_ctx)
2831 {
2832         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2833                                           printer->info_2->secdesc_buf->sd_size,
2834                                           printer->info_2->secdesc_buf->sd);
2835 }
2836
2837 /*******************************************************************
2838  * fill a notify_info_data with the attributes
2839  * jfm:xxxx a samba printer is always shared
2840  ********************************************************************/
2841
2842 void spoolss_notify_attributes(int snum,
2843                                       struct spoolss_Notify *data,
2844                                       print_queue_struct *queue,
2845                                       NT_PRINTER_INFO_LEVEL *printer,
2846                                       TALLOC_CTX *mem_ctx)
2847 {
2848         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2849 }
2850
2851 /*******************************************************************
2852  * fill a notify_info_data with the priority
2853  ********************************************************************/
2854
2855 static void spoolss_notify_priority(int snum,
2856                                     struct spoolss_Notify *data,
2857                                     print_queue_struct *queue,
2858                                     NT_PRINTER_INFO_LEVEL *printer,
2859                                     TALLOC_CTX *mem_ctx)
2860 {
2861         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2862 }
2863
2864 /*******************************************************************
2865  * fill a notify_info_data with the default priority
2866  ********************************************************************/
2867
2868 static void spoolss_notify_default_priority(int snum,
2869                                             struct spoolss_Notify *data,
2870                                             print_queue_struct *queue,
2871                                             NT_PRINTER_INFO_LEVEL *printer,
2872                                             TALLOC_CTX *mem_ctx)
2873 {
2874         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2875 }
2876
2877 /*******************************************************************
2878  * fill a notify_info_data with the start time
2879  ********************************************************************/
2880
2881 static void spoolss_notify_start_time(int snum,
2882                                       struct spoolss_Notify *data,
2883                                       print_queue_struct *queue,
2884                                       NT_PRINTER_INFO_LEVEL *printer,
2885                                       TALLOC_CTX *mem_ctx)
2886 {
2887         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2888 }
2889
2890 /*******************************************************************
2891  * fill a notify_info_data with the until time
2892  ********************************************************************/
2893
2894 static void spoolss_notify_until_time(int snum,
2895                                       struct spoolss_Notify *data,
2896                                       print_queue_struct *queue,
2897                                       NT_PRINTER_INFO_LEVEL *printer,
2898                                       TALLOC_CTX *mem_ctx)
2899 {
2900         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2901 }
2902
2903 /*******************************************************************
2904  * fill a notify_info_data with the status
2905  ********************************************************************/
2906
2907 static void spoolss_notify_status(int snum,
2908                                   struct spoolss_Notify *data,
2909                                   print_queue_struct *queue,
2910                                   NT_PRINTER_INFO_LEVEL *printer,
2911                                   TALLOC_CTX *mem_ctx)
2912 {
2913         print_status_struct status;
2914
2915         print_queue_length(snum, &status);
2916         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2917 }
2918
2919 /*******************************************************************
2920  * fill a notify_info_data with the number of jobs queued
2921  ********************************************************************/
2922
2923 void spoolss_notify_cjobs(int snum,
2924                                  struct spoolss_Notify *data,
2925                                  print_queue_struct *queue,
2926                                  NT_PRINTER_INFO_LEVEL *printer,
2927                                  TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the average ppm
2934  ********************************************************************/
2935
2936 static void spoolss_notify_average_ppm(int snum,
2937                                        struct spoolss_Notify *data,
2938                                        print_queue_struct *queue,
2939                                        NT_PRINTER_INFO_LEVEL *printer,
2940                                        TALLOC_CTX *mem_ctx)
2941 {
2942         /* always respond 8 pages per minutes */
2943         /* a little hard ! */
2944         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2945 }
2946
2947 /*******************************************************************
2948  * fill a notify_info_data with username
2949  ********************************************************************/
2950
2951 static void spoolss_notify_username(int snum,
2952                                     struct spoolss_Notify *data,
2953                                     print_queue_struct *queue,
2954                                     NT_PRINTER_INFO_LEVEL *printer,
2955                                     TALLOC_CTX *mem_ctx)
2956 {
2957         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2958 }
2959
2960 /*******************************************************************
2961  * fill a notify_info_data with job status
2962  ********************************************************************/
2963
2964 static void spoolss_notify_job_status(int snum,
2965                                       struct spoolss_Notify *data,
2966                                       print_queue_struct *queue,
2967                                       NT_PRINTER_INFO_LEVEL *printer,
2968                                       TALLOC_CTX *mem_ctx)
2969 {
2970         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with job name
2975  ********************************************************************/
2976
2977 static void spoolss_notify_job_name(int snum,
2978                                     struct spoolss_Notify *data,
2979                                     print_queue_struct *queue,
2980                                     NT_PRINTER_INFO_LEVEL *printer,
2981                                     TALLOC_CTX *mem_ctx)
2982 {
2983         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2984 }
2985
2986 /*******************************************************************
2987  * fill a notify_info_data with job status
2988  ********************************************************************/
2989
2990 static void spoolss_notify_job_status_string(int snum,
2991                                              struct spoolss_Notify *data,
2992                                              print_queue_struct *queue,
2993                                              NT_PRINTER_INFO_LEVEL *printer,
2994                                              TALLOC_CTX *mem_ctx)
2995 {
2996         /*
2997          * Now we're returning job status codes we just return a "" here. JRA.
2998          */
2999
3000         const char *p = "";
3001
3002 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3003         p = "unknown";
3004
3005         switch (queue->status) {
3006         case LPQ_QUEUED:
3007                 p = "Queued";
3008                 break;
3009         case LPQ_PAUSED:
3010                 p = "";    /* NT provides the paused string */
3011                 break;
3012         case LPQ_SPOOLING:
3013                 p = "Spooling";
3014                 break;
3015         case LPQ_PRINTING:
3016                 p = "Printing";
3017                 break;
3018         }
3019 #endif /* NO LONGER NEEDED. */
3020
3021         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3022 }
3023
3024 /*******************************************************************
3025  * fill a notify_info_data with job time
3026  ********************************************************************/
3027
3028 static void spoolss_notify_job_time(int snum,
3029                                     struct spoolss_Notify *data,
3030                                     print_queue_struct *queue,
3031                                     NT_PRINTER_INFO_LEVEL *printer,
3032                                     TALLOC_CTX *mem_ctx)
3033 {
3034         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3035 }
3036
3037 /*******************************************************************
3038  * fill a notify_info_data with job size
3039  ********************************************************************/
3040
3041 static void spoolss_notify_job_size(int snum,
3042                                     struct spoolss_Notify *data,
3043                                     print_queue_struct *queue,
3044                                     NT_PRINTER_INFO_LEVEL *printer,
3045                                     TALLOC_CTX *mem_ctx)
3046 {
3047         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with page info
3052  ********************************************************************/
3053 static void spoolss_notify_total_pages(int snum,
3054                                 struct spoolss_Notify *data,
3055                                 print_queue_struct *queue,
3056                                 NT_PRINTER_INFO_LEVEL *printer,
3057                                 TALLOC_CTX *mem_ctx)
3058 {
3059         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with pages printed info.
3064  ********************************************************************/
3065 static void spoolss_notify_pages_printed(int snum,
3066                                 struct spoolss_Notify *data,
3067                                 print_queue_struct *queue,
3068                                 NT_PRINTER_INFO_LEVEL *printer,
3069                                 TALLOC_CTX *mem_ctx)
3070 {
3071         /* Add code when back-end tracks this */
3072         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3073 }
3074
3075 /*******************************************************************
3076  Fill a notify_info_data with job position.
3077  ********************************************************************/
3078
3079 static void spoolss_notify_job_position(int snum,
3080                                         struct spoolss_Notify *data,
3081                                         print_queue_struct *queue,
3082                                         NT_PRINTER_INFO_LEVEL *printer,
3083                                         TALLOC_CTX *mem_ctx)
3084 {
3085         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3086 }
3087
3088 /*******************************************************************
3089  Fill a notify_info_data with submitted time.
3090  ********************************************************************/
3091
3092 static void spoolss_notify_submitted_time(int snum,
3093                                           struct spoolss_Notify *data,
3094                                           print_queue_struct *queue,
3095                                           NT_PRINTER_INFO_LEVEL *printer,
3096                                           TALLOC_CTX *mem_ctx)
3097 {
3098         data->data.string.string = NULL;
3099         data->data.string.size = 0;
3100
3101         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3102                                &data->data.string.string,
3103                                &data->data.string.size);
3104
3105 }
3106
3107 struct s_notify_info_data_table
3108 {
3109         enum spoolss_NotifyType type;
3110         uint16_t field;
3111         const char *name;
3112         enum spoolss_NotifyTable variable_type;
3113         void (*fn) (int snum, struct spoolss_Notify *data,
3114                     print_queue_struct *queue,
3115                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3116 };
3117
3118 /* A table describing the various print notification constants and
3119    whether the notification data is a pointer to a variable sized
3120    buffer, a one value uint32_t or a two value uint32_t. */
3121
3122 static const struct s_notify_info_data_table notify_info_data_table[] =
3123 {
3124 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3125 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3126 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3127 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3128 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3129 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3130 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3131 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3132 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3133 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3134 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3135 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3136 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3137 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3138 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3139 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3140 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3141 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3142 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3143 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3144 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3145 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3146 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3147 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3148 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3149 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3150 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3151 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3152 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3153 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3154 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3155 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3156 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3157 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3158 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3159 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3160 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3161 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3162 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3163 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3164 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3165 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3166 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3167 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3168 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3169 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3170 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3171 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3172 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3173 };
3174
3175 /*******************************************************************
3176  Return the variable_type of info_data structure.
3177 ********************************************************************/
3178
3179 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3180                                                   uint16_t field)
3181 {
3182         int i=0;
3183
3184         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3185                 if ( (notify_info_data_table[i].type == type) &&
3186                      (notify_info_data_table[i].field == field) ) {
3187                         return notify_info_data_table[i].variable_type;
3188                 }
3189         }
3190
3191         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3192
3193         return 0;
3194 }
3195
3196 /****************************************************************************
3197 ****************************************************************************/
3198
3199 static bool search_notify(enum spoolss_NotifyType type,
3200                           uint16_t field,
3201                           int *value)
3202 {
3203         int i;
3204
3205         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3206                 if (notify_info_data_table[i].type == type &&
3207                     notify_info_data_table[i].field == field &&
3208                     notify_info_data_table[i].fn != NULL) {
3209                         *value = i;
3210                         return true;
3211                 }
3212         }
3213
3214         return false;
3215 }
3216
3217 /****************************************************************************
3218 ****************************************************************************/
3219
3220 void construct_info_data(struct spoolss_Notify *info_data,
3221                          enum spoolss_NotifyType type,
3222                          uint16_t field,
3223                          int id)
3224 {
3225         info_data->type                 = type;
3226         info_data->field.field          = field;
3227         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3228         info_data->job_id               = id;
3229 }
3230
3231 /*******************************************************************
3232  *
3233  * fill a notify_info struct with info asked
3234  *
3235  ********************************************************************/
3236
3237 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3238                                           struct spoolss_NotifyInfo *info,
3239                                           int snum,
3240                                           const struct spoolss_NotifyOptionType *option_type,
3241                                           uint32_t id,
3242                                           TALLOC_CTX *mem_ctx)
3243 {
3244         int field_num,j;
3245         enum spoolss_NotifyType type;
3246         uint16_t field;
3247
3248         struct spoolss_Notify *current_data;
3249         NT_PRINTER_INFO_LEVEL *printer = NULL;
3250         print_queue_struct *queue=NULL;
3251
3252         type = option_type->type;
3253
3254         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3255                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3256                 option_type->count, lp_servicename(snum)));
3257
3258         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3259                 return false;
3260
3261         for(field_num=0; field_num < option_type->count; field_num++) {
3262                 field = option_type->fields[field_num].field;
3263
3264                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3265
3266                 if (!search_notify(type, field, &j) )
3267                         continue;
3268
3269                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3270                                                       struct spoolss_Notify,
3271                                                       info->count + 1);
3272                 if (info->notifies == NULL) {
3273                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3274                         free_a_printer(&printer, 2);
3275                         return false;
3276                 }
3277
3278                 current_data = &info->notifies[info->count];
3279
3280                 construct_info_data(current_data, type, field, id);
3281
3282                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3283                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3284
3285                 notify_info_data_table[j].fn(snum, current_data, queue,
3286                                              printer, mem_ctx);
3287
3288                 info->count++;
3289         }
3290
3291         free_a_printer(&printer, 2);
3292         return true;
3293 }
3294
3295 /*******************************************************************
3296  *
3297  * fill a notify_info struct with info asked
3298  *
3299  ********************************************************************/
3300
3301 static bool construct_notify_jobs_info(print_queue_struct *queue,
3302                                        struct spoolss_NotifyInfo *info,
3303                                        NT_PRINTER_INFO_LEVEL *printer,
3304                                        int snum,
3305                                        const struct spoolss_NotifyOptionType *option_type,
3306                                        uint32_t id,
3307                                        TALLOC_CTX *mem_ctx)
3308 {
3309         int field_num,j;
3310         enum spoolss_NotifyType type;
3311         uint16_t field;
3312         struct spoolss_Notify *current_data;
3313
3314         DEBUG(4,("construct_notify_jobs_info\n"));
3315
3316         type = option_type->type;
3317
3318         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3319                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3320                 option_type->count));
3321
3322         for(field_num=0; field_num<option_type->count; field_num++) {
3323                 field = option_type->fields[field_num].field;
3324
3325                 if (!search_notify(type, field, &j) )
3326                         continue;
3327
3328                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3329                                                       struct spoolss_Notify,
3330                                                       info->count + 1);
3331                 if (info->notifies == NULL) {
3332                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3333                         return false;
3334                 }
3335
3336                 current_data=&(info->notifies[info->count]);
3337
3338                 construct_info_data(current_data, type, field, id);
3339                 notify_info_data_table[j].fn(snum, current_data, queue,
3340                                              printer, mem_ctx);
3341                 info->count++;
3342         }
3343
3344         return true;
3345 }
3346
3347 /*
3348  * JFM: The enumeration is not that simple, it's even non obvious.
3349  *
3350  * let's take an example: I want to monitor the PRINTER SERVER for
3351  * the printer's name and the number of jobs currently queued.
3352  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3353  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3354  *
3355  * I have 3 printers on the back of my server.
3356  *
3357  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3358  * structures.
3359  *   Number     Data                    Id
3360  *      1       printer 1 name          1
3361  *      2       printer 1 cjob          1
3362  *      3       printer 2 name          2
3363  *      4       printer 2 cjob          2
3364  *      5       printer 3 name          3
3365  *      6       printer 3 name          3
3366  *
3367  * that's the print server case, the printer case is even worse.
3368  */
3369
3370 /*******************************************************************
3371  *
3372  * enumerate all printers on the printserver
3373  * fill a notify_info struct with info asked
3374  *
3375  ********************************************************************/
3376
3377 static WERROR printserver_notify_info(pipes_struct *p,
3378                                       struct policy_handle *hnd,
3379                                       struct spoolss_NotifyInfo *info,
3380                                       TALLOC_CTX *mem_ctx)
3381 {
3382         int snum;
3383         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3384         int n_services=lp_numservices();
3385         int i;
3386         struct spoolss_NotifyOption *option;
3387         struct spoolss_NotifyOptionType option_type;
3388
3389         DEBUG(4,("printserver_notify_info\n"));
3390
3391         if (!Printer)
3392                 return WERR_BADFID;
3393
3394         option = Printer->notify.option;
3395
3396         info->version   = 2;
3397         info->notifies  = NULL;
3398         info->count     = 0;
3399
3400         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3401            sending a ffpcn() request first */
3402
3403         if ( !option )
3404                 return WERR_BADFID;
3405
3406         for (i=0; i<option->count; i++) {
3407                 option_type = option->types[i];
3408
3409                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3410                         continue;
3411
3412                 for (snum=0; snum<n_services; snum++)
3413                 {
3414                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3415                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3416                 }
3417         }
3418
3419 #if 0
3420         /*
3421          * Debugging information, don't delete.
3422          */
3423
3424         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3425         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3426         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3427
3428         for (i=0; i<info->count; i++) {
3429                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3430                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3431                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3432         }
3433 #endif
3434
3435         return WERR_OK;
3436 }
3437
3438 /*******************************************************************
3439  *
3440  * fill a notify_info struct with info asked
3441  *
3442  ********************************************************************/
3443
3444 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3445                                   struct spoolss_NotifyInfo *info,
3446                                   TALLOC_CTX *mem_ctx)
3447 {
3448         int snum;
3449         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3450         int i;
3451         uint32_t id;
3452         struct spoolss_NotifyOption *option;
3453         struct spoolss_NotifyOptionType option_type;
3454         int count,j;
3455         print_queue_struct *queue=NULL;
3456         print_status_struct status;
3457
3458         DEBUG(4,("printer_notify_info\n"));
3459
3460         if (!Printer)
3461                 return WERR_BADFID;
3462
3463         option = Printer->notify.option;
3464         id = 0x0;
3465
3466         info->version   = 2;
3467         info->notifies  = NULL;
3468         info->count     = 0;
3469
3470         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3471            sending a ffpcn() request first */
3472
3473         if ( !option )
3474                 return WERR_BADFID;
3475
3476         get_printer_snum(p, hnd, &snum, NULL);
3477
3478         for (i=0; i<option->count; i++) {
3479                 option_type = option->types[i];
3480
3481                 switch (option_type.type) {
3482                 case PRINTER_NOTIFY_TYPE:
3483                         if(construct_notify_printer_info(Printer, info, snum,
3484                                                          &option_type, id,
3485                                                          mem_ctx))
3486                                 id--;
3487                         break;
3488
3489                 case JOB_NOTIFY_TYPE: {
3490                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3491
3492                         count = print_queue_status(snum, &queue, &status);
3493
3494                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3495                                 goto done;
3496
3497                         for (j=0; j<count; j++) {
3498                                 construct_notify_jobs_info(&queue[j], info,
3499                                                            printer, snum,
3500                                                            &option_type,
3501                                                            queue[j].job,
3502                                                            mem_ctx);
3503                         }
3504
3505                         free_a_printer(&printer, 2);
3506
3507                 done:
3508                         SAFE_FREE(queue);
3509                         break;
3510                 }
3511                 }
3512         }
3513
3514         /*
3515          * Debugging information, don't delete.
3516          */
3517         /*
3518         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3519         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3520         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3521
3522         for (i=0; i<info->count; i++) {
3523                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3524                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3525                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3526         }
3527         */
3528         return WERR_OK;
3529 }
3530
3531 /****************************************************************
3532  _spoolss_RouterRefreshPrinterChangeNotify
3533 ****************************************************************/
3534
3535 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3536                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3537 {
3538         struct spoolss_NotifyInfo *info;
3539
3540         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3541         WERROR result = WERR_BADFID;
3542
3543         /* we always have a spoolss_NotifyInfo struct */
3544         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3545         if (!info) {
3546                 result = WERR_NOMEM;
3547                 goto done;
3548         }
3549
3550         *r->out.info = info;
3551
3552         if (!Printer) {
3553                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3554                         "Invalid handle (%s:%u:%u).\n",
3555                         OUR_HANDLE(r->in.handle)));
3556                 goto done;
3557         }
3558
3559         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3560
3561         /*
3562          *      We are now using the change value, and
3563          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3564          *      I don't have a global notification system, I'm sending back all the
3565          *      informations even when _NOTHING_ has changed.
3566          */
3567
3568         /* We need to keep track of the change value to send back in
3569            RRPCN replies otherwise our updates are ignored. */
3570
3571         Printer->notify.fnpcn = true;
3572
3573         if (Printer->notify.client_connected) {
3574                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3575                         "Saving change value in request [%x]\n",
3576                         r->in.change_low));
3577                 Printer->notify.change = r->in.change_low;
3578         }
3579
3580         /* just ignore the spoolss_NotifyOption */
3581
3582         switch (Printer->printer_type) {
3583                 case SPLHND_SERVER:
3584                         result = printserver_notify_info(p, r->in.handle,
3585                                                          info, p->mem_ctx);
3586                         break;
3587
3588                 case SPLHND_PRINTER:
3589                         result = printer_notify_info(p, r->in.handle,
3590                                                      info, p->mem_ctx);
3591                         break;
3592         }
3593
3594         Printer->notify.fnpcn = false;
3595
3596 done:
3597         return result;
3598 }
3599
3600 /********************************************************************
3601  * construct_printer_info_0
3602  * fill a printer_info_0 struct
3603  ********************************************************************/
3604
3605 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3606                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3607                                       struct spoolss_PrinterInfo0 *r,
3608                                       int snum)
3609 {
3610         int count;
3611         counter_printer_0 *session_counter;
3612         time_t setuptime;
3613         print_status_struct status;
3614
3615         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3616         W_ERROR_HAVE_NO_MEMORY(r->printername);
3617
3618         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3619         W_ERROR_HAVE_NO_MEMORY(r->servername);
3620
3621         count = print_queue_length(snum, &status);
3622
3623         /* check if we already have a counter for this printer */
3624         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3625                 if (session_counter->snum == snum)
3626                         break;
3627         }
3628
3629         /* it's the first time, add it to the list */
3630         if (session_counter == NULL) {
3631                 session_counter = SMB_MALLOC_P(counter_printer_0);
3632                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3633                 ZERO_STRUCTP(session_counter);
3634                 session_counter->snum           = snum;
3635                 session_counter->counter        = 0;
3636                 DLIST_ADD(counter_list, session_counter);
3637         }
3638
3639         /* increment it */
3640         session_counter->counter++;
3641
3642         r->cjobs                        = count;
3643         r->total_jobs                   = 0;
3644         r->total_bytes                  = 0;
3645
3646         setuptime = (time_t)ntprinter->info_2->setuptime;
3647
3648         init_systemtime(&r->time, gmtime(&setuptime));
3649
3650         /* JFM:
3651          * the global_counter should be stored in a TDB as it's common to all the clients
3652          * and should be zeroed on samba startup
3653          */
3654         r->global_counter               = session_counter->counter;
3655         r->total_pages                  = 0;
3656         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3657         r->version                      = 0x0005;       /* NT 5 */
3658         r->free_build                   = 0x0893;       /* build 2195 */
3659         r->spooling                     = 0;
3660         r->max_spooling                 = 0;
3661         r->session_counter              = session_counter->counter;
3662         r->num_error_out_of_paper       = 0x0;
3663         r->num_error_not_ready          = 0x0;          /* number of print failure */
3664         r->job_error                    = 0x0;
3665         r->number_of_processors         = 0x1;
3666         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3667         r->high_part_total_bytes        = 0x0;
3668         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3669         r->last_error                   = WERR_OK;
3670         r->status                       = nt_printq_status(status.status);
3671         r->enumerate_network_printers   = 0x0;
3672         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3673         r->processor_architecture       = 0x0;
3674         r->processor_level              = 0x6;          /* 6  ???*/
3675         r->ref_ic                       = 0;
3676         r->reserved2                    = 0;
3677         r->reserved3                    = 0;
3678
3679         return WERR_OK;
3680 }
3681
3682 /****************************************************************************
3683  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3684  should be valid upon entry
3685 ****************************************************************************/
3686
3687 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3688                                     struct spoolss_DeviceMode *r,
3689                                     const NT_DEVICEMODE *ntdevmode)
3690 {
3691         if (!r || !ntdevmode) {
3692                 return WERR_INVALID_PARAM;
3693         }
3694
3695         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3696         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3697
3698         r->specversion          = ntdevmode->specversion;
3699         r->driverversion        = ntdevmode->driverversion;
3700         r->size                 = ntdevmode->size;
3701         r->__driverextra_length = ntdevmode->driverextra;
3702         r->fields               = ntdevmode->fields;
3703
3704         r->orientation          = ntdevmode->orientation;
3705         r->papersize            = ntdevmode->papersize;
3706         r->paperlength          = ntdevmode->paperlength;
3707         r->paperwidth           = ntdevmode->paperwidth;
3708         r->scale                = ntdevmode->scale;
3709         r->copies               = ntdevmode->copies;
3710         r->defaultsource        = ntdevmode->defaultsource;
3711         r->printquality         = ntdevmode->printquality;
3712         r->color                = ntdevmode->color;
3713         r->duplex               = ntdevmode->duplex;
3714         r->yresolution          = ntdevmode->yresolution;
3715         r->ttoption             = ntdevmode->ttoption;
3716         r->collate              = ntdevmode->collate;
3717
3718         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3719         W_ERROR_HAVE_NO_MEMORY(r->formname);
3720
3721         /* all 0 below are values that have not been set in the old parsing/copy
3722          * function, maybe they should... - gd */
3723
3724         r->logpixels            = 0;
3725         r->bitsperpel           = 0;
3726         r->pelswidth            = 0;
3727         r->pelsheight           = 0;
3728         r->displayflags         = 0;
3729         r->displayfrequency     = 0;
3730         r->icmmethod            = ntdevmode->icmmethod;
3731         r->icmintent            = ntdevmode->icmintent;
3732         r->mediatype            = ntdevmode->mediatype;
3733         r->dithertype           = ntdevmode->dithertype;
3734         r->reserved1            = 0;
3735         r->reserved2            = 0;
3736         r->panningwidth         = 0;
3737         r->panningheight        = 0;
3738
3739         if (ntdevmode->nt_dev_private != NULL) {
3740                 r->driverextra_data = data_blob_talloc(mem_ctx,
3741                         ntdevmode->nt_dev_private,
3742                         ntdevmode->driverextra);
3743                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3744         }
3745
3746         return WERR_OK;
3747 }
3748
3749
3750 /****************************************************************************
3751  Create a spoolss_DeviceMode struct. Returns talloced memory.
3752 ****************************************************************************/
3753
3754 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3755                                               const char *servicename)
3756 {
3757         WERROR result;
3758         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3759         struct spoolss_DeviceMode *devmode = NULL;
3760
3761         DEBUG(7,("construct_dev_mode\n"));
3762
3763         DEBUGADD(8,("getting printer characteristics\n"));
3764
3765         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3766                 return NULL;
3767
3768         if (!printer->info_2->devmode) {
3769                 DEBUG(5, ("BONG! There was no device mode!\n"));
3770                 goto done;
3771         }
3772
3773         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3774         if (!devmode) {
3775                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3776                 goto done;
3777         }
3778
3779         DEBUGADD(8,("loading DEVICEMODE\n"));
3780
3781         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3782         if (!W_ERROR_IS_OK(result)) {
3783                 TALLOC_FREE(devmode);
3784         }
3785
3786 done:
3787         free_a_printer(&printer,2);
3788
3789         return devmode;
3790 }
3791
3792 /********************************************************************
3793  * construct_printer_info1
3794  * fill a spoolss_PrinterInfo1 struct
3795 ********************************************************************/
3796
3797 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3798                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3799                                       uint32_t flags,
3800                                       struct spoolss_PrinterInfo1 *r,
3801                                       int snum)
3802 {
3803         r->flags                = flags;
3804
3805         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3806                                                   ntprinter->info_2->printername,
3807                                                   ntprinter->info_2->drivername,
3808                                                   ntprinter->info_2->location);
3809         W_ERROR_HAVE_NO_MEMORY(r->description);
3810
3811         if (*ntprinter->info_2->comment == '\0') {
3812                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3813         } else {
3814                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3815         }
3816         W_ERROR_HAVE_NO_MEMORY(r->comment);
3817
3818         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3819         W_ERROR_HAVE_NO_MEMORY(r->name);
3820
3821         return WERR_OK;
3822 }
3823
3824 /********************************************************************
3825  * construct_printer_info2
3826  * fill a spoolss_PrinterInfo2 struct
3827 ********************************************************************/
3828
3829 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3830                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3831                                       struct spoolss_PrinterInfo2 *r,
3832                                       int snum)
3833 {
3834         int count;
3835
3836         print_status_struct status;
3837
3838         count = print_queue_length(snum, &status);
3839
3840         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3841         W_ERROR_HAVE_NO_MEMORY(r->servername);
3842         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3843         W_ERROR_HAVE_NO_MEMORY(r->printername);
3844         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3845         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3846         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3847         W_ERROR_HAVE_NO_MEMORY(r->portname);
3848         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3849         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3850
3851         if (*ntprinter->info_2->comment == '\0') {
3852                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3853         } else {
3854                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3855         }
3856         W_ERROR_HAVE_NO_MEMORY(r->comment);
3857
3858         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3859         W_ERROR_HAVE_NO_MEMORY(r->location);
3860         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3861         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3862         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3863         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3864         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3865         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3866         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3867         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3868
3869         r->attributes           = ntprinter->info_2->attributes;
3870
3871         r->priority             = ntprinter->info_2->priority;
3872         r->defaultpriority      = ntprinter->info_2->default_priority;
3873         r->starttime            = ntprinter->info_2->starttime;
3874         r->untiltime            = ntprinter->info_2->untiltime;
3875         r->status               = nt_printq_status(status.status);
3876         r->cjobs                = count;
3877         r->averageppm           = ntprinter->info_2->averageppm;
3878
3879         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3880         if (!r->devmode) {
3881                 DEBUG(8,("Returning NULL Devicemode!\n"));
3882         }
3883
3884         r->secdesc              = NULL;
3885
3886         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3887                 /* don't use talloc_steal() here unless you do a deep steal of all
3888                    the SEC_DESC members */
3889
3890                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3891         }
3892
3893         return WERR_OK;
3894 }
3895
3896 /********************************************************************
3897  * construct_printer_info3
3898  * fill a spoolss_PrinterInfo3 struct
3899  ********************************************************************/
3900
3901 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3902                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3903                                       struct spoolss_PrinterInfo3 *r,
3904                                       int snum)
3905 {
3906         /* These are the components of the SD we are returning. */
3907
3908         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3909                 /* don't use talloc_steal() here unless you do a deep steal of all
3910                    the SEC_DESC members */
3911
3912                 r->secdesc = dup_sec_desc(mem_ctx,
3913                                           ntprinter->info_2->secdesc_buf->sd);
3914                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3915         }
3916
3917         return WERR_OK;
3918 }
3919
3920 /********************************************************************
3921  * construct_printer_info4
3922  * fill a spoolss_PrinterInfo4 struct
3923  ********************************************************************/
3924
3925 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3926                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3927                                       struct spoolss_PrinterInfo4 *r,
3928                                       int snum)
3929 {
3930         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3931         W_ERROR_HAVE_NO_MEMORY(r->printername);
3932         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3933         W_ERROR_HAVE_NO_MEMORY(r->servername);
3934
3935         r->attributes   = ntprinter->info_2->attributes;
3936
3937         return WERR_OK;
3938 }
3939
3940 /********************************************************************
3941  * construct_printer_info5
3942  * fill a spoolss_PrinterInfo5 struct
3943  ********************************************************************/
3944
3945 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3946                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3947                                       struct spoolss_PrinterInfo5 *r,
3948                                       int snum)
3949 {
3950         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3951         W_ERROR_HAVE_NO_MEMORY(r->printername);
3952         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3953         W_ERROR_HAVE_NO_MEMORY(r->portname);
3954
3955         r->attributes   = ntprinter->info_2->attributes;
3956
3957         /* these two are not used by NT+ according to MSDN */
3958
3959         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3960         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3961
3962         return WERR_OK;
3963 }
3964
3965 /********************************************************************
3966  * construct_printer_info_6
3967  * fill a spoolss_PrinterInfo6 struct
3968  ********************************************************************/
3969
3970 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3971                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3972                                       struct spoolss_PrinterInfo6 *r,
3973                                       int snum)
3974 {
3975         int count;
3976         print_status_struct status;
3977
3978         count = print_queue_length(snum, &status);
3979
3980         r->status = nt_printq_status(status.status);
3981
3982         return WERR_OK;
3983 }
3984
3985 /********************************************************************
3986  * construct_printer_info7
3987  * fill a spoolss_PrinterInfo7 struct
3988  ********************************************************************/
3989
3990 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3991                                       Printer_entry *print_hnd,
3992                                       struct spoolss_PrinterInfo7 *r,
3993                                       int snum)
3994 {
3995         struct GUID guid;
3996
3997         if (is_printer_published(print_hnd, snum, &guid)) {
3998                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3999                 r->action = DSPRINT_PUBLISH;
4000         } else {
4001                 r->guid = talloc_strdup(mem_ctx, "");
4002                 r->action = DSPRINT_UNPUBLISH;
4003         }
4004         W_ERROR_HAVE_NO_MEMORY(r->guid);
4005
4006         return WERR_OK;
4007 }
4008
4009 /********************************************************************
4010  * construct_printer_info8
4011  * fill a spoolss_PrinterInfo8 struct
4012  ********************************************************************/
4013
4014 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4015                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4016                                       struct spoolss_DeviceModeInfo *r,
4017                                       int snum)
4018 {
4019         struct spoolss_DeviceMode *devmode;
4020         WERROR result;
4021
4022         if (!ntprinter->info_2->devmode) {
4023                 r->devmode = NULL;
4024                 return WERR_OK;
4025         }
4026
4027         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4028         W_ERROR_HAVE_NO_MEMORY(devmode);
4029
4030         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4031         if (!W_ERROR_IS_OK(result)) {
4032                 TALLOC_FREE(devmode);
4033                 return result;
4034         }
4035
4036         r->devmode      = devmode;
4037
4038         return WERR_OK;
4039 }
4040
4041
4042 /********************************************************************
4043 ********************************************************************/
4044
4045 static bool snum_is_shared_printer(int snum)
4046 {
4047         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4048 }
4049
4050 /********************************************************************
4051  Spoolss_enumprinters.
4052 ********************************************************************/
4053
4054 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4055                                            uint32_t level,
4056                                            uint32_t flags,
4057                                            union spoolss_PrinterInfo **info_p,
4058                                            uint32_t *count_p)
4059 {
4060         int snum;
4061         int n_services = lp_numservices();
4062         union spoolss_PrinterInfo *info = NULL;
4063         uint32_t count = 0;
4064         WERROR result = WERR_OK;
4065
4066         *count_p = 0;
4067         *info_p = NULL;
4068
4069         for (snum = 0; snum < n_services; snum++) {
4070
4071                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4072
4073                 if (!snum_is_shared_printer(snum)) {
4074                         continue;
4075                 }
4076
4077                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4078                         lp_servicename(snum), snum));
4079
4080                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4081                                             union spoolss_PrinterInfo,
4082                                             count + 1);
4083                 if (!info) {
4084                         result = WERR_NOMEM;
4085                         goto out;
4086                 }
4087
4088                 result = get_a_printer(NULL, &ntprinter, 2,
4089                                        lp_const_servicename(snum));
4090                 if (!W_ERROR_IS_OK(result)) {
4091                         goto out;
4092                 }
4093
4094                 switch (level) {
4095                 case 0:
4096                         result = construct_printer_info0(info, ntprinter,
4097                                                          &info[count].info0, snum);
4098                         break;
4099                 case 1:
4100                         result = construct_printer_info1(info, ntprinter, flags,
4101                                                          &info[count].info1, snum);
4102                         break;
4103                 case 2:
4104                         result = construct_printer_info2(info, ntprinter,
4105                                                          &info[count].info2, snum);
4106                         break;
4107                 case 4:
4108                         result = construct_printer_info4(info, ntprinter,
4109                                                          &info[count].info4, snum);
4110                         break;
4111                 case 5:
4112                         result = construct_printer_info5(info, ntprinter,
4113                                                          &info[count].info5, snum);
4114                         break;
4115
4116                 default:
4117                         result = WERR_UNKNOWN_LEVEL;
4118                         free_a_printer(&ntprinter, 2);
4119                         goto out;
4120                 }
4121
4122                 free_a_printer(&ntprinter, 2);
4123                 if (!W_ERROR_IS_OK(result)) {
4124                         goto out;
4125                 }
4126
4127                 count++;
4128         }
4129
4130         *count_p = count;
4131         *info_p = info;
4132
4133  out:
4134         if (!W_ERROR_IS_OK(result)) {
4135                 TALLOC_FREE(info);
4136                 return result;
4137         }
4138
4139         *info_p = info;
4140
4141         return WERR_OK;
4142 }
4143
4144 /********************************************************************
4145  * handle enumeration of printers at level 0
4146  ********************************************************************/
4147
4148 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4149                                   uint32_t flags,
4150                                   const char *servername,
4151                                   union spoolss_PrinterInfo **info,
4152                                   uint32_t *count)
4153 {
4154         DEBUG(4,("enum_all_printers_info_0\n"));
4155
4156         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4157 }
4158
4159
4160 /********************************************************************
4161 ********************************************************************/
4162
4163 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4164                                        uint32_t flags,
4165                                        union spoolss_PrinterInfo **info,
4166                                        uint32_t *count)
4167 {
4168         DEBUG(4,("enum_all_printers_info_1\n"));
4169
4170         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4171 }
4172
4173 /********************************************************************
4174  enum_all_printers_info_1_local.
4175 *********************************************************************/
4176
4177 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4178                                              union spoolss_PrinterInfo **info,
4179                                              uint32_t *count)
4180 {
4181         DEBUG(4,("enum_all_printers_info_1_local\n"));
4182
4183         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4184 }
4185
4186 /********************************************************************
4187  enum_all_printers_info_1_name.
4188 *********************************************************************/
4189
4190 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4191                                             const char *name,
4192                                             union spoolss_PrinterInfo **info,
4193                                             uint32_t *count)
4194 {
4195         const char *s = name;
4196
4197         DEBUG(4,("enum_all_printers_info_1_name\n"));
4198
4199         if ((name[0] == '\\') && (name[1] == '\\')) {
4200                 s = name + 2;
4201         }
4202
4203         if (!is_myname_or_ipaddr(s)) {
4204                 return WERR_INVALID_NAME;
4205         }
4206
4207         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4208 }
4209
4210 /********************************************************************
4211  enum_all_printers_info_1_network.
4212 *********************************************************************/
4213
4214 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4215                                                const char *name,
4216                                                union spoolss_PrinterInfo **info,
4217                                                uint32_t *count)
4218 {
4219         const char *s = name;
4220
4221         DEBUG(4,("enum_all_printers_info_1_network\n"));
4222
4223         /* If we respond to a enum_printers level 1 on our name with flags
4224            set to PRINTER_ENUM_REMOTE with a list of printers then these
4225            printers incorrectly appear in the APW browse list.
4226            Specifically the printers for the server appear at the workgroup
4227            level where all the other servers in the domain are
4228            listed. Windows responds to this call with a
4229            WERR_CAN_NOT_COMPLETE so we should do the same. */
4230
4231         if (name[0] == '\\' && name[1] == '\\') {
4232                  s = name + 2;
4233         }
4234
4235         if (is_myname_or_ipaddr(s)) {
4236                  return WERR_CAN_NOT_COMPLETE;
4237         }
4238
4239         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4240 }
4241
4242 /********************************************************************
4243  * api_spoolss_enumprinters
4244  *
4245  * called from api_spoolss_enumprinters (see this to understand)
4246  ********************************************************************/
4247
4248 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4249                                        union spoolss_PrinterInfo **info,
4250                                        uint32_t *count)
4251 {
4252         DEBUG(4,("enum_all_printers_info_2\n"));
4253
4254         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4255 }
4256
4257 /********************************************************************
4258  * handle enumeration of printers at level 1
4259  ********************************************************************/
4260
4261 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4262                                   uint32_t flags,
4263                                   const char *name,
4264                                   union spoolss_PrinterInfo **info,
4265                                   uint32_t *count)
4266 {
4267         /* Not all the flags are equals */
4268
4269         if (flags & PRINTER_ENUM_LOCAL) {
4270                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4271         }
4272
4273         if (flags & PRINTER_ENUM_NAME) {
4274                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4275         }
4276
4277         if (flags & PRINTER_ENUM_NETWORK) {
4278                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4279         }
4280
4281         return WERR_OK; /* NT4sp5 does that */
4282 }
4283
4284 /********************************************************************
4285  * handle enumeration of printers at level 2
4286  ********************************************************************/
4287
4288 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4289                                   uint32_t flags,
4290                                   const char *servername,
4291                                   union spoolss_PrinterInfo **info,
4292                                   uint32_t *count)
4293 {
4294         if (flags & PRINTER_ENUM_LOCAL) {
4295                 return enum_all_printers_info_2(mem_ctx, info, count);
4296         }
4297
4298         if (flags & PRINTER_ENUM_NAME) {
4299                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4300                         return WERR_INVALID_NAME;
4301                 }
4302
4303                 return enum_all_printers_info_2(mem_ctx, info, count);
4304         }
4305
4306         if (flags & PRINTER_ENUM_REMOTE) {
4307                 return WERR_UNKNOWN_LEVEL;
4308         }
4309
4310         return WERR_OK;
4311 }
4312
4313 /********************************************************************
4314  * handle enumeration of printers at level 4
4315  ********************************************************************/
4316
4317 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4318                                   uint32_t flags,
4319                                   const char *servername,
4320                                   union spoolss_PrinterInfo **info,
4321                                   uint32_t *count)
4322 {
4323         DEBUG(4,("enum_all_printers_info_4\n"));
4324
4325         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4326 }
4327
4328
4329 /********************************************************************
4330  * handle enumeration of printers at level 5
4331  ********************************************************************/
4332
4333 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4334                                   uint32_t flags,
4335                                   const char *servername,
4336                                   union spoolss_PrinterInfo **info,
4337                                   uint32_t *count)
4338 {
4339         DEBUG(4,("enum_all_printers_info_5\n"));
4340
4341         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4342 }
4343
4344 /****************************************************************
4345  _spoolss_EnumPrinters
4346 ****************************************************************/
4347
4348 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4349                              struct spoolss_EnumPrinters *r)
4350 {
4351         const char *name;
4352         WERROR result;
4353
4354         /* that's an [in out] buffer */
4355
4356         if (!r->in.buffer && (r->in.offered != 0)) {
4357                 return WERR_INVALID_PARAM;
4358         }
4359
4360         DEBUG(4,("_spoolss_EnumPrinters\n"));
4361
4362         *r->out.needed = 0;
4363         *r->out.count = 0;
4364         *r->out.info = NULL;
4365
4366         /*
4367          * Level 1:
4368          *          flags==PRINTER_ENUM_NAME
4369          *           if name=="" then enumerates all printers
4370          *           if name!="" then enumerate the printer
4371          *          flags==PRINTER_ENUM_REMOTE
4372          *          name is NULL, enumerate printers
4373          * Level 2: name!="" enumerates printers, name can't be NULL
4374          * Level 3: doesn't exist
4375          * Level 4: does a local registry lookup
4376          * Level 5: same as Level 2
4377          */
4378
4379         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4380         W_ERROR_HAVE_NO_MEMORY(name);
4381
4382         switch (r->in.level) {
4383         case 0:
4384                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4385                                              r->out.info, r->out.count);
4386                 break;
4387         case 1:
4388                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4389                                              r->out.info, r->out.count);
4390                 break;
4391         case 2:
4392                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4393                                              r->out.info, r->out.count);
4394                 break;
4395         case 4:
4396                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4397                                              r->out.info, r->out.count);
4398                 break;
4399         case 5:
4400                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4401                                              r->out.info, r->out.count);
4402                 break;
4403         default:
4404                 return WERR_UNKNOWN_LEVEL;
4405         }
4406
4407         if (!W_ERROR_IS_OK(result)) {
4408                 return result;
4409         }
4410
4411         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4412                                                      spoolss_EnumPrinters, NULL,
4413                                                      *r->out.info, r->in.level,
4414                                                      *r->out.count);
4415         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4416         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4417
4418         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4419 }
4420
4421 /****************************************************************
4422  _spoolss_GetPrinter
4423 ****************************************************************/
4424
4425 WERROR _spoolss_GetPrinter(pipes_struct *p,
4426                            struct spoolss_GetPrinter *r)
4427 {
4428         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4429         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4430         WERROR result = WERR_OK;
4431
4432         int snum;
4433
4434         /* that's an [in out] buffer */
4435
4436         if (!r->in.buffer && (r->in.offered != 0)) {
4437                 return WERR_INVALID_PARAM;
4438         }
4439
4440         *r->out.needed = 0;
4441
4442         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4443                 return WERR_BADFID;
4444         }
4445
4446         result = get_a_printer(Printer, &ntprinter, 2,
4447                                lp_const_servicename(snum));
4448         if (!W_ERROR_IS_OK(result)) {
4449                 return result;
4450         }
4451
4452         switch (r->in.level) {
4453         case 0:
4454                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4455                                                  &r->out.info->info0, snum);
4456                 break;
4457         case 1:
4458                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4459                                                  PRINTER_ENUM_ICON8,
4460                                                  &r->out.info->info1, snum);
4461                 break;
4462         case 2:
4463                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4464                                                  &r->out.info->info2, snum);
4465                 break;
4466         case 3:
4467                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4468                                                  &r->out.info->info3, snum);
4469                 break;
4470         case 4:
4471                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4472                                                  &r->out.info->info4, snum);
4473                 break;
4474         case 5:
4475                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4476                                                  &r->out.info->info5, snum);
4477                 break;
4478         case 6:
4479                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4480                                                  &r->out.info->info6, snum);
4481                 break;
4482         case 7:
4483                 result = construct_printer_info7(p->mem_ctx, Printer,
4484                                                  &r->out.info->info7, snum);
4485                 break;
4486         case 8:
4487                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4488                                                  &r->out.info->info8, snum);
4489                 break;
4490         default:
4491                 result = WERR_UNKNOWN_LEVEL;
4492                 break;
4493         }
4494
4495         free_a_printer(&ntprinter, 2);
4496
4497         if (!W_ERROR_IS_OK(result)) {
4498                 TALLOC_FREE(r->out.info);
4499                 return result;
4500         }
4501
4502         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4503                                                r->out.info, r->in.level);
4504         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4505
4506         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4507 }
4508
4509 /********************************************************************
4510  ********************************************************************/
4511
4512 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4513                                                   const char **string_array,
4514                                                   const char *cservername)
4515 {
4516         int i, num_strings = 0;
4517         const char **array = NULL;
4518
4519         if (!string_array) {
4520                 return NULL;
4521         }
4522
4523         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4524
4525                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4526                                                   cservername, string_array[i]);
4527                 if (!str) {
4528                         TALLOC_FREE(array);
4529                         return NULL;
4530                 }
4531
4532
4533                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4534                         TALLOC_FREE(array);
4535                         return NULL;
4536                 }
4537         }
4538
4539         if (i > 0) {
4540                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4541                              &array, &num_strings);
4542         }
4543
4544         return array;
4545 }
4546
4547 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4548         do { \
4549                 if (in && strlen(in)) { \
4550                         out = talloc_strdup(mem_ctx, in); \
4551                         W_ERROR_HAVE_NO_MEMORY(out); \
4552                 } \
4553         } while (0);
4554
4555 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4556         do { \
4557                 if (in && strlen(in)) { \
4558                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4559                 } else { \
4560                         out = talloc_strdup(mem_ctx, ""); \
4561                 } \
4562                 W_ERROR_HAVE_NO_MEMORY(out); \
4563         } while (0);
4564
4565 /********************************************************************
4566  * fill a spoolss_DriverInfo1 struct
4567  ********************************************************************/
4568
4569 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4570                                         struct spoolss_DriverInfo1 *r,
4571                                         const struct spoolss_DriverInfo3 *driver,
4572                                         const char *servername,
4573                                         const char *architecture)
4574 {
4575         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4576         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4577
4578         return WERR_OK;
4579 }
4580
4581 /********************************************************************
4582  * fill a spoolss_DriverInfo2 struct
4583  ********************************************************************/
4584
4585 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4586                                         struct spoolss_DriverInfo2 *r,
4587                                         const struct spoolss_DriverInfo3 *driver,
4588                                         const char *servername)
4589
4590 {
4591         const char *cservername = canon_servername(servername);
4592
4593         r->version              = driver->version;
4594
4595         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4596         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4597         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4598         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4599
4600         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4601                                driver->driver_path,
4602                                r->driver_path);
4603
4604         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4605                                driver->data_file,
4606                                r->data_file);
4607
4608         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4609                                driver->config_file,
4610                                r->config_file);
4611
4612         return WERR_OK;
4613 }
4614
4615 /********************************************************************
4616  * fill a spoolss_DriverInfo3 struct
4617  ********************************************************************/
4618
4619 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4620                                         struct spoolss_DriverInfo3 *r,
4621                                         const struct spoolss_DriverInfo3 *driver,
4622                                         const char *servername)
4623 {
4624         const char *cservername = canon_servername(servername);
4625
4626         r->version              = driver->version;
4627
4628         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4629         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4630         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4631         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4632
4633         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4634                                driver->driver_path,
4635                                r->driver_path);
4636
4637         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4638                                driver->data_file,
4639                                r->data_file);
4640
4641         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4642                                driver->config_file,
4643                                r->config_file);
4644
4645         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4646                                driver->help_file,
4647                                r->help_file);
4648
4649         FILL_DRIVER_STRING(mem_ctx,
4650                            driver->monitor_name,
4651                            r->monitor_name);
4652
4653         FILL_DRIVER_STRING(mem_ctx,
4654                            driver->default_datatype,
4655                            r->default_datatype);
4656
4657         r->dependent_files = string_array_from_driver_info(mem_ctx,
4658                                                            driver->dependent_files,
4659                                                            cservername);
4660         return WERR_OK;
4661 }
4662
4663 /********************************************************************
4664  * fill a spoolss_DriverInfo4 struct
4665  ********************************************************************/
4666
4667 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4668                                         struct spoolss_DriverInfo4 *r,
4669                                         const struct spoolss_DriverInfo3 *driver,
4670                                         const char *servername)
4671 {
4672         const char *cservername = canon_servername(servername);
4673
4674         r->version              = driver->version;
4675
4676         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4677         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4678         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4679         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4680
4681         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4682                                driver->driver_path,
4683                                r->driver_path);
4684
4685         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4686                                driver->data_file,
4687                                r->data_file);
4688
4689         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4690                                driver->config_file,
4691                                r->config_file);
4692
4693         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4694                                driver->help_file,
4695                                r->help_file);
4696
4697         r->dependent_files = string_array_from_driver_info(mem_ctx,
4698                                                            driver->dependent_files,
4699                                                            cservername);
4700
4701         FILL_DRIVER_STRING(mem_ctx,
4702                            driver->monitor_name,
4703                            r->monitor_name);
4704
4705         FILL_DRIVER_STRING(mem_ctx,
4706                            driver->default_datatype,
4707                            r->default_datatype);
4708
4709         r->previous_names = string_array_from_driver_info(mem_ctx,
4710                                                           NULL,
4711                                                           cservername);
4712
4713         return WERR_OK;
4714 }
4715
4716 /********************************************************************
4717  * fill a spoolss_DriverInfo5 struct
4718  ********************************************************************/
4719
4720 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4721                                         struct spoolss_DriverInfo5 *r,
4722                                         const struct spoolss_DriverInfo3 *driver,
4723                                         const char *servername)
4724 {
4725         const char *cservername = canon_servername(servername);
4726
4727         r->version              = driver->version;
4728
4729         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4730         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4731         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4732         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4733
4734         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4735                                driver->driver_path,
4736                                r->driver_path);
4737
4738         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4739                                driver->data_file,
4740                                r->data_file);
4741
4742         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4743                                driver->config_file,
4744                                r->config_file);
4745
4746         r->driver_attributes    = 0;
4747         r->config_version       = 0;
4748         r->driver_version       = 0;
4749
4750         return WERR_OK;
4751 }
4752 /********************************************************************
4753  * fill a spoolss_DriverInfo6 struct
4754  ********************************************************************/
4755
4756 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4757                                         struct spoolss_DriverInfo6 *r,
4758                                         const struct spoolss_DriverInfo3 *driver,
4759                                         const char *servername)
4760 {
4761         const char *cservername = canon_servername(servername);
4762
4763         r->version              = driver->version;
4764
4765         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4766         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4767         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4768         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4769
4770         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4771                                driver->driver_path,
4772                                r->driver_path);
4773
4774         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4775                                driver->data_file,
4776                                r->data_file);
4777
4778         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4779                                driver->config_file,
4780                                r->config_file);
4781
4782         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4783                                driver->help_file,
4784                                r->help_file);
4785
4786         FILL_DRIVER_STRING(mem_ctx,
4787                            driver->monitor_name,
4788                            r->monitor_name);
4789
4790         FILL_DRIVER_STRING(mem_ctx,
4791                            driver->default_datatype,
4792                            r->default_datatype);
4793
4794         r->dependent_files = string_array_from_driver_info(mem_ctx,
4795                                                            driver->dependent_files,
4796                                                            cservername);
4797         r->previous_names = string_array_from_driver_info(mem_ctx,
4798                                                           NULL,
4799                                                           cservername);
4800
4801         r->driver_date          = 0;
4802         r->driver_version       = 0;
4803
4804         FILL_DRIVER_STRING(mem_ctx, "",
4805                            r->manufacturer_name);
4806         FILL_DRIVER_STRING(mem_ctx, "",
4807                            r->manufacturer_url);
4808         FILL_DRIVER_STRING(mem_ctx, "",
4809                            r->hardware_id);
4810         FILL_DRIVER_STRING(mem_ctx, "",
4811                            r->provider);
4812
4813         return WERR_OK;
4814 }
4815
4816 /********************************************************************
4817  ********************************************************************/
4818
4819 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4820                                           struct spoolss_DriverFileInfo *r,
4821                                           const char *cservername,
4822                                           const char *file_name,
4823                                           enum spoolss_DriverFileType file_type,
4824                                           uint32_t file_version)
4825 {
4826         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4827                                           cservername, file_name);
4828         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4829         r->file_type    = file_type;
4830         r->file_version = file_version;
4831
4832         return WERR_OK;
4833 }
4834
4835 /********************************************************************
4836  ********************************************************************/
4837
4838 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4839                                                  const struct spoolss_DriverInfo3 *driver,
4840                                                  const char *cservername,
4841                                                  struct spoolss_DriverFileInfo **info_p,
4842                                                  uint32_t *count_p)
4843 {
4844         struct spoolss_DriverFileInfo *info = NULL;
4845         uint32_t count = 0;
4846         WERROR result;
4847         uint32_t i;
4848
4849         *info_p = NULL;
4850         *count_p = 0;
4851
4852         if (strlen(driver->driver_path)) {
4853                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4854                                             struct spoolss_DriverFileInfo,
4855                                             count + 1);
4856                 W_ERROR_HAVE_NO_MEMORY(info);
4857                 result = fill_spoolss_DriverFileInfo(info,
4858                                                      &info[count],
4859                                                      cservername,
4860                                                      driver->driver_path,
4861                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4862                                                      0);
4863                 W_ERROR_NOT_OK_RETURN(result);
4864                 count++;
4865         }
4866
4867         if (strlen(driver->config_file)) {
4868                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4869                                             struct spoolss_DriverFileInfo,
4870                                             count + 1);
4871                 W_ERROR_HAVE_NO_MEMORY(info);
4872                 result = fill_spoolss_DriverFileInfo(info,
4873                                                      &info[count],
4874                                                      cservername,
4875                                                      driver->config_file,
4876                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4877                                                      0);
4878                 W_ERROR_NOT_OK_RETURN(result);
4879                 count++;
4880         }
4881
4882         if (strlen(driver->data_file)) {
4883                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4884                                             struct spoolss_DriverFileInfo,
4885                                             count + 1);
4886                 W_ERROR_HAVE_NO_MEMORY(info);
4887                 result = fill_spoolss_DriverFileInfo(info,
4888                                                      &info[count],
4889                                                      cservername,
4890                                                      driver->data_file,
4891                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4892                                                      0);
4893                 W_ERROR_NOT_OK_RETURN(result);
4894                 count++;
4895         }
4896
4897         if (strlen(driver->help_file)) {
4898                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4899                                             struct spoolss_DriverFileInfo,
4900                                             count + 1);
4901                 W_ERROR_HAVE_NO_MEMORY(info);
4902                 result = fill_spoolss_DriverFileInfo(info,
4903                                                      &info[count],
4904                                                      cservername,
4905                                                      driver->help_file,
4906                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4907                                                      0);
4908                 W_ERROR_NOT_OK_RETURN(result);
4909                 count++;
4910         }
4911
4912         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4913                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4914                                             struct spoolss_DriverFileInfo,
4915                                             count + 1);
4916                 W_ERROR_HAVE_NO_MEMORY(info);
4917                 result = fill_spoolss_DriverFileInfo(info,
4918                                                      &info[count],
4919                                                      cservername,
4920                                                      driver->dependent_files[i],
4921                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4922                                                      0);
4923                 W_ERROR_NOT_OK_RETURN(result);
4924                 count++;
4925         }
4926
4927         *info_p = info;
4928         *count_p = count;
4929
4930         return WERR_OK;
4931 }
4932
4933 /********************************************************************
4934  * fill a spoolss_DriverInfo101 sttruct
4935  ********************************************************************/
4936
4937 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4938                                           struct spoolss_DriverInfo101 *r,
4939                                           const struct spoolss_DriverInfo3 *driver,
4940                                           const char *servername)
4941 {
4942         const char *cservername = canon_servername(servername);
4943         WERROR result;
4944
4945         r->version              = driver->version;
4946
4947         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4948         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4949         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4950         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4951
4952         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4953                                                     cservername,
4954                                                     &r->file_info,
4955                                                     &r->file_count);
4956         if (!W_ERROR_IS_OK(result)) {
4957                 return result;
4958         }
4959
4960         FILL_DRIVER_STRING(mem_ctx,
4961                            driver->monitor_name,
4962                            r->monitor_name);
4963
4964         FILL_DRIVER_STRING(mem_ctx,
4965                            driver->default_datatype,
4966                            r->default_datatype);
4967
4968         r->previous_names = string_array_from_driver_info(mem_ctx,
4969                                                           NULL,
4970                                                           cservername);
4971         r->driver_date          = 0;
4972         r->driver_version       = 0;
4973
4974         FILL_DRIVER_STRING(mem_ctx, "",
4975                            r->manufacturer_name);
4976         FILL_DRIVER_STRING(mem_ctx, "",
4977                            r->manufacturer_url);
4978         FILL_DRIVER_STRING(mem_ctx, "",
4979                            r->hardware_id);
4980         FILL_DRIVER_STRING(mem_ctx, "",
4981                            r->provider);
4982
4983         return WERR_OK;
4984 }
4985
4986 /********************************************************************
4987  * construct_printer_driver_info_1
4988  ********************************************************************/
4989
4990 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4991                                               struct spoolss_DriverInfo1 *r,
4992                                               int snum,
4993                                               const char *servername,
4994                                               const char *architecture,
4995                                               uint32_t version)
4996 {
4997         NT_PRINTER_INFO_LEVEL *printer = NULL;
4998         union spoolss_DriverInfo *driver;
4999         WERROR result;
5000
5001         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5002                 return WERR_INVALID_PRINTER_NAME;
5003
5004         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
5005                 free_a_printer(&printer, 2);
5006                 return WERR_UNKNOWN_PRINTER_DRIVER;
5007         }
5008
5009         result = fill_printer_driver_info1(mem_ctx, r, &driver->info3, servername, architecture);
5010
5011         free_a_printer_driver(driver);
5012         free_a_printer(&printer,2);
5013
5014         return result;
5015 }
5016
5017 /********************************************************************
5018  * construct_printer_driver_info_2
5019  * fill a printer_info_2 struct
5020  ********************************************************************/
5021
5022 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5023                                               struct spoolss_DriverInfo2 *r,
5024                                               int snum,
5025                                               const char *servername,
5026                                               const char *architecture,
5027                                               uint32_t version)
5028 {
5029         NT_PRINTER_INFO_LEVEL *printer = NULL;
5030         union spoolss_DriverInfo *driver;
5031         WERROR result;
5032
5033         ZERO_STRUCT(printer);
5034
5035         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5036                 return WERR_INVALID_PRINTER_NAME;
5037
5038         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
5039                 free_a_printer(&printer, 2);
5040                 return WERR_UNKNOWN_PRINTER_DRIVER;
5041         }
5042
5043         result = fill_printer_driver_info2(mem_ctx, r, &driver->info3, servername);
5044
5045         free_a_printer_driver(driver);
5046         free_a_printer(&printer,2);
5047
5048         return result;
5049 }
5050
5051 /********************************************************************
5052  * construct_printer_info_3
5053  * fill a printer_info_3 struct
5054  ********************************************************************/
5055
5056 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5057                                               struct spoolss_DriverInfo3 *r,
5058                                               int snum,
5059                                               const char *servername,
5060                                               const char *architecture,
5061                                               uint32_t version)
5062 {
5063         NT_PRINTER_INFO_LEVEL *printer = NULL;
5064         union spoolss_DriverInfo *driver;
5065         WERROR status;
5066         ZERO_STRUCT(driver);
5067
5068         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5069         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5070         if (!W_ERROR_IS_OK(status))
5071                 return WERR_INVALID_PRINTER_NAME;
5072
5073         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5074         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5075
5076 #if 0   /* JERRY */
5077
5078         /*
5079          * I put this code in during testing.  Helpful when commenting out the
5080          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5081          * as win2k always queries the driver using an infor level of 6.
5082          * I've left it in (but ifdef'd out) because I'll probably
5083          * use it in experimentation again in the future.   --jerry 22/01/2002
5084          */
5085
5086         if (!W_ERROR_IS_OK(status)) {
5087                 /*
5088                  * Is this a W2k client ?
5089                  */
5090                 if (version == 3) {
5091                         /* Yes - try again with a WinNT driver. */
5092                         version = 2;
5093                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5094                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5095                 }
5096 #endif
5097
5098                 if (!W_ERROR_IS_OK(status)) {
5099                         free_a_printer(&printer,2);
5100                         return WERR_UNKNOWN_PRINTER_DRIVER;
5101                 }
5102
5103 #if 0   /* JERRY */
5104         }
5105 #endif
5106
5107
5108         status = fill_printer_driver_info3(mem_ctx, r, &driver->info3, servername);
5109
5110         free_a_printer_driver(driver);
5111         free_a_printer(&printer,2);
5112
5113         return status;
5114 }
5115
5116 /********************************************************************
5117  * construct_printer_info_6
5118  * fill a printer_info_6 struct
5119  ********************************************************************/
5120
5121 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5122                                               struct spoolss_DriverInfo6 *r,
5123                                               int snum,
5124                                               const char *servername,
5125                                               const char *architecture,
5126                                               uint32_t version)
5127 {
5128         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5129         union spoolss_DriverInfo *driver;
5130         WERROR                          status;
5131
5132         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5133
5134         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5135
5136         if (!W_ERROR_IS_OK(status))
5137                 return WERR_INVALID_PRINTER_NAME;
5138
5139         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5140
5141         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5142
5143         if (!W_ERROR_IS_OK(status))
5144         {
5145                 /*
5146                  * Is this a W2k client ?
5147                  */
5148
5149                 if (version < 3) {
5150                         free_a_printer(&printer,2);
5151                         return WERR_UNKNOWN_PRINTER_DRIVER;
5152                 }
5153
5154                 /* Yes - try again with a WinNT driver. */
5155                 version = 2;
5156                 status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5157                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5158                 if (!W_ERROR_IS_OK(status)) {
5159                         free_a_printer(&printer,2);
5160                         return WERR_UNKNOWN_PRINTER_DRIVER;
5161                 }
5162         }
5163
5164         status = fill_printer_driver_info6(mem_ctx, r, &driver->info3, servername);
5165
5166         free_a_printer(&printer,2);
5167         free_a_printer_driver(driver);
5168
5169         return status;
5170 }
5171
5172 /********************************************************************
5173  * construct_printer_info_101
5174  * fill a printer_info_101 struct
5175  ********************************************************************/
5176
5177 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5178                                                 struct spoolss_DriverInfo101 *r,
5179                                                 int snum,
5180                                                 const char *servername,
5181                                                 const char *architecture,
5182                                                 uint32_t version)
5183 {
5184         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5185         union spoolss_DriverInfo *driver;
5186         WERROR                          result;
5187
5188         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5189
5190         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5191                 win_errstr(result)));
5192
5193         if (!W_ERROR_IS_OK(result)) {
5194                 return WERR_INVALID_PRINTER_NAME;
5195         }
5196
5197         result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5198                                       architecture, version);
5199
5200         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5201                 win_errstr(result)));
5202
5203         if (!W_ERROR_IS_OK(result)) {
5204                 /*
5205                  * Is this a W2k client ?
5206                  */
5207
5208                 if (version < 3) {
5209                         free_a_printer(&printer, 2);
5210                         return WERR_UNKNOWN_PRINTER_DRIVER;
5211                 }
5212
5213                 /* Yes - try again with a WinNT driver. */
5214                 version = 2;
5215                 result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5216                                               architecture, version);
5217                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5218                         win_errstr(result)));
5219                 if (!W_ERROR_IS_OK(result)) {
5220                         free_a_printer(&printer, 2);
5221                         return WERR_UNKNOWN_PRINTER_DRIVER;
5222                 }
5223         }
5224
5225         result = fill_printer_driver_info101(mem_ctx, r, &driver->info3, servername);
5226
5227         free_a_printer(&printer, 2);
5228         free_a_printer_driver(driver);
5229
5230         return result;
5231 }
5232
5233 /****************************************************************
5234  _spoolss_GetPrinterDriver2
5235 ****************************************************************/
5236
5237 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5238                                   struct spoolss_GetPrinterDriver2 *r)
5239 {
5240         Printer_entry *printer;
5241         WERROR result;
5242
5243         const char *servername;
5244         int snum;
5245
5246         /* that's an [in out] buffer */
5247
5248         if (!r->in.buffer && (r->in.offered != 0)) {
5249                 return WERR_INVALID_PARAM;
5250         }
5251
5252         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5253
5254         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5255                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5256                 return WERR_INVALID_PRINTER_NAME;
5257         }
5258
5259         *r->out.needed = 0;
5260         *r->out.server_major_version = 0;
5261         *r->out.server_minor_version = 0;
5262
5263         servername = get_server_name(printer);
5264
5265         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5266                 return WERR_BADFID;
5267         }
5268
5269         switch (r->in.level) {
5270         case 1:
5271                 result = construct_printer_driver_info_1(p->mem_ctx,
5272                                                          &r->out.info->info1,
5273                                                          snum,
5274                                                          servername,
5275                                                          r->in.architecture,
5276                                                          r->in.client_major_version);
5277                 break;
5278         case 2:
5279                 result = construct_printer_driver_info_2(p->mem_ctx,
5280                                                          &r->out.info->info2,
5281                                                          snum,
5282                                                          servername,
5283                                                          r->in.architecture,
5284                                                          r->in.client_major_version);
5285                 break;
5286         case 3:
5287                 result = construct_printer_driver_info_3(p->mem_ctx,
5288                                                          &r->out.info->info3,
5289                                                          snum,
5290                                                          servername,
5291                                                          r->in.architecture,
5292                                                          r->in.client_major_version);
5293                 break;
5294         case 6:
5295                 result = construct_printer_driver_info_6(p->mem_ctx,
5296                                                          &r->out.info->info6,
5297                                                          snum,
5298                                                          servername,
5299                                                          r->in.architecture,
5300                                                          r->in.client_major_version);
5301                 break;
5302         case 101:
5303                 result = construct_printer_driver_info_101(p->mem_ctx,
5304                                                            &r->out.info->info101,
5305                                                            snum,
5306                                                            servername,
5307                                                            r->in.architecture,
5308                                                            r->in.client_major_version);
5309                 break;
5310         default:
5311                 result = WERR_UNKNOWN_LEVEL;
5312                 break;
5313         }
5314
5315         if (!W_ERROR_IS_OK(result)) {
5316                 TALLOC_FREE(r->out.info);
5317                 return result;
5318         }
5319
5320         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5321                                                r->out.info, r->in.level);
5322         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5323
5324         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5325 }
5326
5327
5328 /****************************************************************
5329  _spoolss_StartPagePrinter
5330 ****************************************************************/
5331
5332 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5333                                  struct spoolss_StartPagePrinter *r)
5334 {
5335         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5336
5337         if (!Printer) {
5338                 DEBUG(3,("_spoolss_StartPagePrinter: "
5339                         "Error in startpageprinter printer handle\n"));
5340                 return WERR_BADFID;
5341         }
5342
5343         Printer->page_started = true;
5344         return WERR_OK;
5345 }
5346
5347 /****************************************************************
5348  _spoolss_EndPagePrinter
5349 ****************************************************************/
5350
5351 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5352                                struct spoolss_EndPagePrinter *r)
5353 {
5354         int snum;
5355
5356         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5357
5358         if (!Printer) {
5359                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5360                         OUR_HANDLE(r->in.handle)));
5361                 return WERR_BADFID;
5362         }
5363
5364         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5365                 return WERR_BADFID;
5366
5367         Printer->page_started = false;
5368         print_job_endpage(snum, Printer->jobid);
5369
5370         return WERR_OK;
5371 }
5372
5373 /****************************************************************
5374  _spoolss_StartDocPrinter
5375 ****************************************************************/
5376
5377 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5378                                 struct spoolss_StartDocPrinter *r)
5379 {
5380         struct spoolss_DocumentInfo1 *info_1;
5381         int snum;
5382         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5383
5384         if (!Printer) {
5385                 DEBUG(2,("_spoolss_StartDocPrinter: "
5386                         "Invalid handle (%s:%u:%u)\n",
5387                         OUR_HANDLE(r->in.handle)));
5388                 return WERR_BADFID;
5389         }
5390
5391         if (r->in.level != 1) {
5392                 return WERR_UNKNOWN_LEVEL;
5393         }
5394
5395         info_1 = r->in.info.info1;
5396
5397         /*
5398          * a nice thing with NT is it doesn't listen to what you tell it.
5399          * when asked to send _only_ RAW datas, it tries to send datas
5400          * in EMF format.
5401          *
5402          * So I add checks like in NT Server ...
5403          */
5404
5405         if (info_1->datatype) {
5406                 if (strcmp(info_1->datatype, "RAW") != 0) {
5407                         *r->out.job_id = 0;
5408                         return WERR_INVALID_DATATYPE;
5409                 }
5410         }
5411
5412         /* get the share number of the printer */
5413         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5414                 return WERR_BADFID;
5415         }
5416
5417         Printer->jobid = print_job_start(p->server_info, snum,
5418                                          info_1->document_name,
5419                                          Printer->nt_devmode);
5420
5421         /* An error occured in print_job_start() so return an appropriate
5422            NT error code. */
5423
5424         if (Printer->jobid == -1) {
5425                 return map_werror_from_unix(errno);
5426         }
5427
5428         Printer->document_started = true;
5429         *r->out.job_id = Printer->jobid;
5430
5431         return WERR_OK;
5432 }
5433
5434 /****************************************************************
5435  _spoolss_EndDocPrinter
5436 ****************************************************************/
5437
5438 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5439                               struct spoolss_EndDocPrinter *r)
5440 {
5441         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5442         int snum;
5443
5444         if (!Printer) {
5445                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5446                         OUR_HANDLE(r->in.handle)));
5447                 return WERR_BADFID;
5448         }
5449
5450         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5451                 return WERR_BADFID;
5452         }
5453
5454         Printer->document_started = false;
5455         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5456         /* error codes unhandled so far ... */
5457
5458         return WERR_OK;
5459 }
5460
5461 /****************************************************************
5462  _spoolss_WritePrinter
5463 ****************************************************************/
5464
5465 WERROR _spoolss_WritePrinter(pipes_struct *p,
5466                              struct spoolss_WritePrinter *r)
5467 {
5468         uint32_t buffer_written;
5469         int snum;
5470         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5471
5472         if (!Printer) {
5473                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5474                         OUR_HANDLE(r->in.handle)));
5475                 *r->out.num_written = r->in._data_size;
5476                 return WERR_BADFID;
5477         }
5478
5479         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5480                 return WERR_BADFID;
5481
5482         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5483                                                    (const char *)r->in.data.data,
5484                                                    (SMB_OFF_T)-1,
5485                                                    (size_t)r->in._data_size);
5486         if (buffer_written == (uint32_t)-1) {
5487                 *r->out.num_written = 0;
5488                 if (errno == ENOSPC)
5489                         return WERR_NO_SPOOL_SPACE;
5490                 else
5491                         return WERR_ACCESS_DENIED;
5492         }
5493
5494         *r->out.num_written = r->in._data_size;
5495
5496         return WERR_OK;
5497 }
5498
5499 /********************************************************************
5500  * api_spoolss_getprinter
5501  * called from the spoolss dispatcher
5502  *
5503  ********************************************************************/
5504
5505 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5506                               pipes_struct *p)
5507 {
5508         int snum;
5509         WERROR errcode = WERR_BADFUNC;
5510         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5511
5512         if (!Printer) {
5513                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5514                         OUR_HANDLE(handle)));
5515                 return WERR_BADFID;
5516         }
5517
5518         if (!get_printer_snum(p, handle, &snum, NULL))
5519                 return WERR_BADFID;
5520
5521         switch (command) {
5522         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5523                 errcode = print_queue_pause(p->server_info, snum);
5524                 break;
5525         case SPOOLSS_PRINTER_CONTROL_RESUME:
5526         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5527                 errcode = print_queue_resume(p->server_info, snum);
5528                 break;
5529         case SPOOLSS_PRINTER_CONTROL_PURGE:
5530                 errcode = print_queue_purge(p->server_info, snum);
5531                 break;
5532         default:
5533                 return WERR_UNKNOWN_LEVEL;
5534         }
5535
5536         return errcode;
5537 }
5538
5539
5540 /****************************************************************
5541  _spoolss_AbortPrinter
5542  * From MSDN: "Deletes printer's spool file if printer is configured
5543  * for spooling"
5544 ****************************************************************/
5545
5546 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5547                              struct spoolss_AbortPrinter *r)
5548 {
5549         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5550         int             snum;
5551         WERROR          errcode = WERR_OK;
5552
5553         if (!Printer) {
5554                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5555                         OUR_HANDLE(r->in.handle)));
5556                 return WERR_BADFID;
5557         }
5558
5559         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5560                 return WERR_BADFID;
5561
5562         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5563
5564         return errcode;
5565 }
5566
5567 /********************************************************************
5568  * called by spoolss_api_setprinter
5569  * when updating a printer description
5570  ********************************************************************/
5571
5572 static WERROR update_printer_sec(struct policy_handle *handle,
5573                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5574 {
5575         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5576         WERROR result;
5577         int snum;
5578
5579         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5580
5581         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5582                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5583                          OUR_HANDLE(handle)));
5584
5585                 result = WERR_BADFID;
5586                 goto done;
5587         }
5588
5589         if (!secdesc_ctr) {
5590                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5591                 result = WERR_INVALID_PARAM;
5592                 goto done;
5593         }
5594
5595         /* Check the user has permissions to change the security
5596            descriptor.  By experimentation with two NT machines, the user
5597            requires Full Access to the printer to change security
5598            information. */
5599
5600         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5601                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5602                 result = WERR_ACCESS_DENIED;
5603                 goto done;
5604         }
5605
5606         /* NT seems to like setting the security descriptor even though
5607            nothing may have actually changed. */
5608
5609         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5610                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5611                 result = WERR_BADFID;
5612                 goto done;
5613         }
5614
5615         if (DEBUGLEVEL >= 10) {
5616                 SEC_ACL *the_acl;
5617                 int i;
5618
5619                 the_acl = old_secdesc_ctr->sd->dacl;
5620                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5621                            PRINTERNAME(snum), the_acl->num_aces));
5622
5623                 for (i = 0; i < the_acl->num_aces; i++) {
5624                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5625                                            &the_acl->aces[i].trustee),
5626                                   the_acl->aces[i].access_mask));
5627                 }
5628
5629                 the_acl = secdesc_ctr->sd->dacl;
5630
5631                 if (the_acl) {
5632                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5633                                    PRINTERNAME(snum), the_acl->num_aces));
5634
5635                         for (i = 0; i < the_acl->num_aces; i++) {
5636                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5637                                                    &the_acl->aces[i].trustee),
5638                                            the_acl->aces[i].access_mask));
5639                         }
5640                 } else {
5641                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5642                 }
5643         }
5644
5645         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5646         if (!new_secdesc_ctr) {
5647                 result = WERR_NOMEM;
5648                 goto done;
5649         }
5650
5651         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5652                 result = WERR_OK;
5653                 goto done;
5654         }
5655
5656         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5657
5658  done:
5659
5660         return result;
5661 }
5662
5663 /********************************************************************
5664  Canonicalize printer info from a client
5665
5666  ATTN: It does not matter what we set the servername to hear
5667  since we do the necessary work in get_a_printer() to set it to
5668  the correct value based on what the client sent in the
5669  _spoolss_open_printer_ex().
5670  ********************************************************************/
5671
5672 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5673 {
5674         fstring printername;
5675         const char *p;
5676
5677         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5678                 "portname=%s drivername=%s comment=%s location=%s\n",
5679                 info->servername, info->printername, info->sharename,
5680                 info->portname, info->drivername, info->comment, info->location));
5681
5682         /* we force some elements to "correct" values */
5683         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5684         fstrcpy(info->sharename, lp_servicename(snum));
5685
5686         /* check to see if we allow printername != sharename */
5687
5688         if ( lp_force_printername(snum) ) {
5689                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5690                         global_myname(), info->sharename );
5691         } else {
5692
5693                 /* make sure printername is in \\server\printername format */
5694
5695                 fstrcpy( printername, info->printername );
5696                 p = printername;
5697                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5698                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5699                                 p++;
5700                 }
5701
5702                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5703                          global_myname(), p );
5704         }
5705
5706         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5707         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5708
5709
5710
5711         return true;
5712 }
5713
5714 /****************************************************************************
5715 ****************************************************************************/
5716
5717 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5718 {
5719         char *cmd = lp_addport_cmd();
5720         char *command = NULL;
5721         int ret;
5722         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5723         bool is_print_op = false;
5724
5725         if ( !*cmd ) {
5726                 return WERR_ACCESS_DENIED;
5727         }
5728
5729         command = talloc_asprintf(ctx,
5730                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5731         if (!command) {
5732                 return WERR_NOMEM;
5733         }
5734
5735         if ( token )
5736                 is_print_op = user_has_privileges( token, &se_printop );
5737
5738         DEBUG(10,("Running [%s]\n", command));
5739
5740         /********* BEGIN SePrintOperatorPrivilege **********/
5741
5742         if ( is_print_op )
5743                 become_root();
5744
5745         ret = smbrun(command, NULL);
5746
5747         if ( is_print_op )
5748                 unbecome_root();
5749
5750         /********* END SePrintOperatorPrivilege **********/
5751
5752         DEBUGADD(10,("returned [%d]\n", ret));
5753
5754         TALLOC_FREE(command);
5755
5756         if ( ret != 0 ) {
5757                 return WERR_ACCESS_DENIED;
5758         }
5759
5760         return WERR_OK;
5761 }
5762
5763 /****************************************************************************
5764 ****************************************************************************/
5765
5766 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5767 {
5768         char *cmd = lp_addprinter_cmd();
5769         char **qlines;
5770         char *command = NULL;
5771         int numlines;
5772         int ret;
5773         int fd;
5774         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5775         bool is_print_op = false;
5776         char *remote_machine = talloc_strdup(ctx, "%m");
5777
5778         if (!remote_machine) {
5779                 return false;
5780         }
5781         remote_machine = talloc_sub_basic(ctx,
5782                                 current_user_info.smb_name,
5783                                 current_user_info.domain,
5784                                 remote_machine);
5785         if (!remote_machine) {
5786                 return false;
5787         }
5788
5789         command = talloc_asprintf(ctx,
5790                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5791                         cmd, printer->info_2->printername, printer->info_2->sharename,
5792                         printer->info_2->portname, printer->info_2->drivername,
5793                         printer->info_2->location, printer->info_2->comment, remote_machine);
5794         if (!command) {
5795                 return false;
5796         }
5797
5798         if ( token )
5799                 is_print_op = user_has_privileges( token, &se_printop );
5800
5801         DEBUG(10,("Running [%s]\n", command));
5802
5803         /********* BEGIN SePrintOperatorPrivilege **********/
5804
5805         if ( is_print_op )
5806                 become_root();
5807
5808         if ( (ret = smbrun(command, &fd)) == 0 ) {
5809                 /* Tell everyone we updated smb.conf. */
5810                 message_send_all(smbd_messaging_context(),
5811                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5812         }
5813
5814         if ( is_print_op )
5815                 unbecome_root();
5816
5817         /********* END SePrintOperatorPrivilege **********/
5818
5819         DEBUGADD(10,("returned [%d]\n", ret));
5820
5821         TALLOC_FREE(command);
5822         TALLOC_FREE(remote_machine);
5823
5824         if ( ret != 0 ) {
5825                 if (fd != -1)
5826                         close(fd);
5827                 return false;
5828         }
5829
5830         /* reload our services immediately */
5831         become_root();
5832         reload_services(false);
5833         unbecome_root();
5834
5835         numlines = 0;
5836         /* Get lines and convert them back to dos-codepage */
5837         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5838         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5839         close(fd);
5840
5841         /* Set the portname to what the script says the portname should be. */
5842         /* but don't require anything to be return from the script exit a good error code */
5843
5844         if (numlines) {
5845                 /* Set the portname to what the script says the portname should be. */
5846                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5847                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5848         }
5849
5850         TALLOC_FREE(qlines);
5851         return true;
5852 }
5853
5854
5855 /********************************************************************
5856  * Called by spoolss_api_setprinter
5857  * when updating a printer description.
5858  ********************************************************************/
5859
5860 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5861                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5862                              struct spoolss_DeviceMode *devmode)
5863 {
5864         int snum;
5865         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5866         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5867         WERROR result;
5868         DATA_BLOB buffer;
5869         fstring asc_buffer;
5870
5871         DEBUG(8,("update_printer\n"));
5872
5873         result = WERR_OK;
5874
5875         if (!Printer) {
5876                 result = WERR_BADFID;
5877                 goto done;
5878         }
5879
5880         if (!get_printer_snum(p, handle, &snum, NULL)) {
5881                 result = WERR_BADFID;
5882                 goto done;
5883         }
5884
5885         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5886             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5887                 result = WERR_BADFID;
5888                 goto done;
5889         }
5890
5891         DEBUGADD(8,("Converting info_2 struct\n"));
5892
5893         /*
5894          * convert_printer_info converts the incoming
5895          * info from the client and overwrites the info
5896          * just read from the tdb in the pointer 'printer'.
5897          */
5898
5899         if (!convert_printer_info(info_ctr, printer)) {
5900                 result =  WERR_NOMEM;
5901                 goto done;
5902         }
5903
5904         if (devmode) {
5905                 /* we have a valid devmode
5906                    convert it and link it*/
5907
5908                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5909                 if (!convert_devicemode(printer->info_2->printername, devmode,
5910                                         &printer->info_2->devmode)) {
5911                         result =  WERR_NOMEM;
5912                         goto done;
5913                 }
5914         }
5915
5916         /* Do sanity check on the requested changes for Samba */
5917
5918         if (!check_printer_ok(printer->info_2, snum)) {
5919                 result = WERR_INVALID_PARAM;
5920                 goto done;
5921         }
5922
5923         /* FIXME!!! If the driver has changed we really should verify that
5924            it is installed before doing much else   --jerry */
5925
5926         /* Check calling user has permission to update printer description */
5927
5928         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5929                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5930                 result = WERR_ACCESS_DENIED;
5931                 goto done;
5932         }
5933
5934         /* Call addprinter hook */
5935         /* Check changes to see if this is really needed */
5936
5937         if ( *lp_addprinter_cmd()
5938                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5939                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5940                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5941                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5942         {
5943                 /* add_printer_hook() will call reload_services() */
5944
5945                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5946                                        printer) ) {
5947                         result = WERR_ACCESS_DENIED;
5948                         goto done;
5949                 }
5950         }
5951
5952         /*
5953          * When a *new* driver is bound to a printer, the drivername is used to
5954          * lookup previously saved driver initialization info, which is then
5955          * bound to the printer, simulating what happens in the Windows arch.
5956          */
5957         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5958         {
5959                 if (!set_driver_init(printer, 2))
5960                 {
5961                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5962                                 printer->info_2->drivername));
5963                 }
5964
5965                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5966                         printer->info_2->drivername));
5967
5968                 notify_printer_driver(snum, printer->info_2->drivername);
5969         }
5970
5971         /*
5972          * flag which changes actually occured.  This is a small subset of
5973          * all the possible changes.  We also have to update things in the
5974          * DsSpooler key.
5975          */
5976
5977         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5978                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5979                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5980                         REG_SZ, buffer.data, buffer.length);
5981
5982                 notify_printer_comment(snum, printer->info_2->comment);
5983         }
5984
5985         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5986                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5987                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5988                         REG_SZ, buffer.data, buffer.length);
5989
5990                 notify_printer_sharename(snum, printer->info_2->sharename);
5991         }
5992
5993         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5994                 char *pname;
5995
5996                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5997                         pname++;
5998                 else
5999                         pname = printer->info_2->printername;
6000
6001
6002                 push_reg_sz(talloc_tos(), &buffer, pname);
6003                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6004                         REG_SZ, buffer.data, buffer.length);
6005
6006                 notify_printer_printername( snum, pname );
6007         }
6008
6009         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6010                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
6011                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6012                         REG_SZ, buffer.data, buffer.length);
6013
6014                 notify_printer_port(snum, printer->info_2->portname);
6015         }
6016
6017         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6018                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
6019                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6020                         REG_SZ, buffer.data, buffer.length);
6021
6022                 notify_printer_location(snum, printer->info_2->location);
6023         }
6024
6025         /* here we need to update some more DsSpooler keys */
6026         /* uNCName, serverName, shortServerName */
6027
6028         push_reg_sz(talloc_tos(), &buffer, global_myname());
6029         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6030                 REG_SZ, buffer.data, buffer.length);
6031         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6032                 REG_SZ, buffer.data, buffer.length);
6033
6034         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6035                  global_myname(), printer->info_2->sharename );
6036         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
6037         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6038                 REG_SZ, buffer.data, buffer.length);
6039
6040         /* Update printer info */
6041         result = mod_a_printer(printer, 2);
6042
6043 done:
6044         free_a_printer(&printer, 2);
6045         free_a_printer(&old_printer, 2);
6046
6047
6048         return result;
6049 }
6050
6051 /****************************************************************************
6052 ****************************************************************************/
6053 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6054                                            struct policy_handle *handle,
6055                                            struct spoolss_SetPrinterInfo7 *info7)
6056 {
6057 #ifdef HAVE_ADS
6058         int snum;
6059         Printer_entry *Printer;
6060
6061         if ( lp_security() != SEC_ADS ) {
6062                 return WERR_UNKNOWN_LEVEL;
6063         }
6064
6065         Printer = find_printer_index_by_hnd(p, handle);
6066
6067         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6068
6069         if (!Printer)
6070                 return WERR_BADFID;
6071
6072         if (!get_printer_snum(p, handle, &snum, NULL))
6073                 return WERR_BADFID;
6074
6075         nt_printer_publish(Printer, snum, info7->action);
6076
6077         return WERR_OK;
6078 #else
6079         return WERR_UNKNOWN_LEVEL;
6080 #endif
6081 }
6082
6083 /****************************************************************
6084  _spoolss_SetPrinter
6085 ****************************************************************/
6086
6087 WERROR _spoolss_SetPrinter(pipes_struct *p,
6088                            struct spoolss_SetPrinter *r)
6089 {
6090         WERROR result;
6091
6092         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6093
6094         if (!Printer) {
6095                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6096                         OUR_HANDLE(r->in.handle)));
6097                 return WERR_BADFID;
6098         }
6099
6100         /* check the level */
6101         switch (r->in.info_ctr->level) {
6102                 case 0:
6103                         return control_printer(r->in.handle, r->in.command, p);
6104                 case 2:
6105                         result = update_printer(p, r->in.handle,
6106                                                 r->in.info_ctr,
6107                                                 r->in.devmode_ctr->devmode);
6108                         if (!W_ERROR_IS_OK(result))
6109                                 return result;
6110                         if (r->in.secdesc_ctr->sd)
6111                                 result = update_printer_sec(r->in.handle, p,
6112                                                             r->in.secdesc_ctr);
6113                         return result;
6114                 case 3:
6115                         return update_printer_sec(r->in.handle, p,
6116                                                   r->in.secdesc_ctr);
6117                 case 7:
6118                         return publish_or_unpublish_printer(p, r->in.handle,
6119                                                             r->in.info_ctr->info.info7);
6120                 default:
6121                         return WERR_UNKNOWN_LEVEL;
6122         }
6123 }
6124
6125 /****************************************************************
6126  _spoolss_FindClosePrinterNotify
6127 ****************************************************************/
6128
6129 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6130                                        struct spoolss_FindClosePrinterNotify *r)
6131 {
6132         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6133
6134         if (!Printer) {
6135                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6136                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6137                 return WERR_BADFID;
6138         }
6139
6140         if (Printer->notify.client_connected == true) {
6141                 int snum = -1;
6142
6143                 if ( Printer->printer_type == SPLHND_SERVER)
6144                         snum = -1;
6145                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6146                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6147                         return WERR_BADFID;
6148
6149                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6150         }
6151
6152         Printer->notify.flags=0;
6153         Printer->notify.options=0;
6154         Printer->notify.localmachine[0]='\0';
6155         Printer->notify.printerlocal=0;
6156         TALLOC_FREE(Printer->notify.option);
6157         Printer->notify.client_connected = false;
6158
6159         return WERR_OK;
6160 }
6161
6162 /****************************************************************
6163  _spoolss_AddJob
6164 ****************************************************************/
6165
6166 WERROR _spoolss_AddJob(pipes_struct *p,
6167                        struct spoolss_AddJob *r)
6168 {
6169         if (!r->in.buffer && (r->in.offered != 0)) {
6170                 return WERR_INVALID_PARAM;
6171         }
6172
6173         /* this is what a NT server returns for AddJob. AddJob must fail on
6174          * non-local printers */
6175
6176         if (r->in.level != 1) {
6177                 return WERR_UNKNOWN_LEVEL;
6178         }
6179
6180         return WERR_INVALID_PARAM;
6181 }
6182
6183 /****************************************************************************
6184 fill_job_info1
6185 ****************************************************************************/
6186
6187 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6188                              struct spoolss_JobInfo1 *r,
6189                              const print_queue_struct *queue,
6190                              int position, int snum,
6191                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6192 {
6193         struct tm *t;
6194
6195         t = gmtime(&queue->time);
6196
6197         r->job_id               = queue->job;
6198
6199         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6200         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6201         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6202         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6203         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6204         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6205         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6206         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6207         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6208         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6209         r->text_status          = talloc_strdup(mem_ctx, "");
6210         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6211
6212         r->status               = nt_printj_status(queue->status);
6213         r->priority             = queue->priority;
6214         r->position             = position;
6215         r->total_pages          = queue->page_count;
6216         r->pages_printed        = 0; /* ??? */
6217
6218         init_systemtime(&r->submitted, t);
6219
6220         return WERR_OK;
6221 }
6222
6223 /****************************************************************************
6224 fill_job_info2
6225 ****************************************************************************/
6226
6227 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6228                              struct spoolss_JobInfo2 *r,
6229                              const print_queue_struct *queue,
6230                              int position, int snum,
6231                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6232                              struct spoolss_DeviceMode *devmode)
6233 {
6234         struct tm *t;
6235
6236         t = gmtime(&queue->time);
6237
6238         r->job_id               = queue->job;
6239
6240         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6241         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6242         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6243         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6244         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6245         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6246         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6247         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6248         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6249         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6250         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6251         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6252         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6253         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6254         r->parameters           = talloc_strdup(mem_ctx, "");
6255         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6256         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6257         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6258
6259         r->devmode              = devmode;
6260
6261         r->text_status          = talloc_strdup(mem_ctx, "");
6262         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6263
6264         r->secdesc              = NULL;
6265
6266         r->status               = nt_printj_status(queue->status);
6267         r->priority             = queue->priority;
6268         r->position             = position;
6269         r->start_time           = 0;
6270         r->until_time           = 0;
6271         r->total_pages          = queue->page_count;
6272         r->size                 = queue->size;
6273         init_systemtime(&r->submitted, t);
6274         r->time                 = 0;
6275         r->pages_printed        = 0; /* ??? */
6276
6277         return WERR_OK;
6278 }
6279
6280 /****************************************************************************
6281  Enumjobs at level 1.
6282 ****************************************************************************/
6283
6284 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6285                               const print_queue_struct *queue,
6286                               uint32_t num_queues, int snum,
6287                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6288                               union spoolss_JobInfo **info_p,
6289                               uint32_t *count)
6290 {
6291         union spoolss_JobInfo *info;
6292         int i;
6293         WERROR result = WERR_OK;
6294
6295         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6296         W_ERROR_HAVE_NO_MEMORY(info);
6297
6298         *count = num_queues;
6299
6300         for (i=0; i<*count; i++) {
6301                 result = fill_job_info1(info,
6302                                         &info[i].info1,
6303                                         &queue[i],
6304                                         i,
6305                                         snum,
6306                                         ntprinter);
6307                 if (!W_ERROR_IS_OK(result)) {
6308                         goto out;
6309                 }
6310         }
6311
6312  out:
6313         if (!W_ERROR_IS_OK(result)) {
6314                 TALLOC_FREE(info);
6315                 *count = 0;
6316                 return result;
6317         }
6318
6319         *info_p = info;
6320
6321         return WERR_OK;
6322 }
6323
6324 /****************************************************************************
6325  Enumjobs at level 2.
6326 ****************************************************************************/
6327
6328 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6329                               const print_queue_struct *queue,
6330                               uint32_t num_queues, int snum,
6331                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6332                               union spoolss_JobInfo **info_p,
6333                               uint32_t *count)
6334 {
6335         union spoolss_JobInfo *info;
6336         int i;
6337         WERROR result = WERR_OK;
6338
6339         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6340         W_ERROR_HAVE_NO_MEMORY(info);
6341
6342         *count = num_queues;
6343
6344         for (i=0; i<*count; i++) {
6345
6346                 struct spoolss_DeviceMode *devmode;
6347
6348                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6349                 if (!devmode) {
6350                         result = WERR_NOMEM;
6351                         goto out;
6352                 }
6353
6354                 result = fill_job_info2(info,
6355                                         &info[i].info2,
6356                                         &queue[i],
6357                                         i,
6358                                         snum,
6359                                         ntprinter,
6360                                         devmode);
6361                 if (!W_ERROR_IS_OK(result)) {
6362                         goto out;
6363                 }
6364         }
6365
6366  out:
6367         if (!W_ERROR_IS_OK(result)) {
6368                 TALLOC_FREE(info);
6369                 *count = 0;
6370                 return result;
6371         }
6372
6373         *info_p = info;
6374
6375         return WERR_OK;
6376 }
6377
6378 /****************************************************************
6379  _spoolss_EnumJobs
6380 ****************************************************************/
6381
6382 WERROR _spoolss_EnumJobs(pipes_struct *p,
6383                          struct spoolss_EnumJobs *r)
6384 {
6385         WERROR result;
6386         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6387         int snum;
6388         print_status_struct prt_status;
6389         print_queue_struct *queue = NULL;
6390         uint32_t count;
6391
6392         /* that's an [in out] buffer */
6393
6394         if (!r->in.buffer && (r->in.offered != 0)) {
6395                 return WERR_INVALID_PARAM;
6396         }
6397
6398         DEBUG(4,("_spoolss_EnumJobs\n"));
6399
6400         *r->out.needed = 0;
6401         *r->out.count = 0;
6402         *r->out.info = NULL;
6403
6404         /* lookup the printer snum and tdb entry */
6405
6406         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6407                 return WERR_BADFID;
6408         }
6409
6410         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6411         if (!W_ERROR_IS_OK(result)) {
6412                 return result;
6413         }
6414
6415         count = print_queue_status(snum, &queue, &prt_status);
6416         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6417                 count, prt_status.status, prt_status.message));
6418
6419         if (count == 0) {
6420                 SAFE_FREE(queue);
6421                 free_a_printer(&ntprinter, 2);
6422                 return WERR_OK;
6423         }
6424
6425         switch (r->in.level) {
6426         case 1:
6427                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6428                                          ntprinter, r->out.info, r->out.count);
6429                 break;
6430         case 2:
6431                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6432                                          ntprinter, r->out.info, r->out.count);
6433                 break;
6434         default:
6435                 result = WERR_UNKNOWN_LEVEL;
6436                 break;
6437         }
6438
6439         SAFE_FREE(queue);
6440         free_a_printer(&ntprinter, 2);
6441
6442         if (!W_ERROR_IS_OK(result)) {
6443                 return result;
6444         }
6445
6446         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6447                                                      spoolss_EnumJobs, NULL,
6448                                                      *r->out.info, r->in.level,
6449                                                      *r->out.count);
6450         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6451         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6452
6453         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6454 }
6455
6456 /****************************************************************
6457  _spoolss_ScheduleJob
6458 ****************************************************************/
6459
6460 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6461                             struct spoolss_ScheduleJob *r)
6462 {
6463         return WERR_OK;
6464 }
6465
6466 /****************************************************************
6467  _spoolss_SetJob
6468 ****************************************************************/
6469
6470 WERROR _spoolss_SetJob(pipes_struct *p,
6471                        struct spoolss_SetJob *r)
6472 {
6473         int snum;
6474         WERROR errcode = WERR_BADFUNC;
6475
6476         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6477                 return WERR_BADFID;
6478         }
6479
6480         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6481                 return WERR_INVALID_PRINTER_NAME;
6482         }
6483
6484         switch (r->in.command) {
6485         case SPOOLSS_JOB_CONTROL_CANCEL:
6486         case SPOOLSS_JOB_CONTROL_DELETE:
6487                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6488                         errcode = WERR_OK;
6489                 }
6490                 break;
6491         case SPOOLSS_JOB_CONTROL_PAUSE:
6492                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6493                         errcode = WERR_OK;
6494                 }
6495                 break;
6496         case SPOOLSS_JOB_CONTROL_RESTART:
6497         case SPOOLSS_JOB_CONTROL_RESUME:
6498                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6499                         errcode = WERR_OK;
6500                 }
6501                 break;
6502         default:
6503                 return WERR_UNKNOWN_LEVEL;
6504         }
6505
6506         return errcode;
6507 }
6508
6509 /****************************************************************************
6510  Enumerates all printer drivers by level and architecture.
6511 ****************************************************************************/
6512
6513 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6514                                                        const char *servername,
6515                                                        const char *architecture,
6516                                                        uint32_t level,
6517                                                        union spoolss_DriverInfo **info_p,
6518                                                        uint32_t *count_p)
6519 {
6520         int i;
6521         int ndrivers;
6522         uint32_t version;
6523         fstring *list = NULL;
6524         union spoolss_DriverInfo *driver;
6525         union spoolss_DriverInfo *info = NULL;
6526         uint32_t count = 0;
6527         WERROR result = WERR_OK;
6528
6529         *count_p = 0;
6530         *info_p = NULL;
6531
6532         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6533                 list = NULL;
6534                 ndrivers = get_ntdrivers(&list, architecture, version);
6535                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6536                         ndrivers, architecture, version));
6537
6538                 if (ndrivers == -1) {
6539                         result = WERR_NOMEM;
6540                         goto out;
6541                 }
6542
6543                 if (ndrivers != 0) {
6544                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6545                                                     union spoolss_DriverInfo,
6546                                                     count + ndrivers);
6547                         if (!info) {
6548                                 DEBUG(0,("enumprinterdrivers_level1: "
6549                                         "failed to enlarge driver info buffer!\n"));
6550                                 result = WERR_NOMEM;
6551                                 goto out;
6552                         }
6553                 }
6554
6555                 for (i=0; i<ndrivers; i++) {
6556                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6557                         ZERO_STRUCT(driver);
6558                         result = get_a_printer_driver(mem_ctx, &driver, 3, list[i],
6559                                                       architecture, version);
6560                         if (!W_ERROR_IS_OK(result)) {
6561                                 goto out;
6562                         }
6563
6564                         switch (level) {
6565                         case 1:
6566                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6567                                                                    &driver->info3, servername,
6568                                                                    architecture);
6569                                 break;
6570                         case 2:
6571                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6572                                                                    &driver->info3, servername);
6573                                 break;
6574                         case 3:
6575                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6576                                                                    &driver->info3, servername);
6577                                 break;
6578                         case 4:
6579                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6580                                                                    &driver->info3, servername);
6581                                 break;
6582                         case 5:
6583                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6584                                                                    &driver->info3, servername);
6585                                 break;
6586                         case 6:
6587                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6588                                                                    &driver->info3, servername);
6589                                 break;
6590                         default:
6591                                 result = WERR_UNKNOWN_LEVEL;
6592                                 break;
6593                         }
6594
6595                         free_a_printer_driver(driver);
6596
6597                         if (!W_ERROR_IS_OK(result)) {
6598                                 goto out;
6599                         }
6600                 }
6601
6602                 count += ndrivers;
6603                 SAFE_FREE(list);
6604         }
6605
6606  out:
6607         SAFE_FREE(list);
6608
6609         if (!W_ERROR_IS_OK(result)) {
6610                 TALLOC_FREE(info);
6611                 return result;
6612         }
6613
6614         *info_p = info;
6615         *count_p = count;
6616
6617         return WERR_OK;
6618 }
6619
6620 /****************************************************************************
6621  Enumerates all printer drivers by level.
6622 ****************************************************************************/
6623
6624 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6625                                        const char *servername,
6626                                        const char *architecture,
6627                                        uint32_t level,
6628                                        union spoolss_DriverInfo **info_p,
6629                                        uint32_t *count_p)
6630 {
6631         uint32_t a,i;
6632         WERROR result = WERR_OK;
6633
6634         if (strequal(architecture, "all")) {
6635
6636                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6637
6638                         union spoolss_DriverInfo *info = NULL;
6639                         uint32_t count = 0;
6640
6641                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6642                                                                           servername,
6643                                                                           archi_table[a].long_archi,
6644                                                                           level,
6645                                                                           &info,
6646                                                                           &count);
6647                         if (!W_ERROR_IS_OK(result)) {
6648                                 continue;
6649                         }
6650
6651                         for (i=0; i < count; i++) {
6652                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6653                                              info[i], info_p, count_p);
6654                         }
6655                 }
6656
6657                 return result;
6658         }
6659
6660         return enumprinterdrivers_level_by_architecture(mem_ctx,
6661                                                         servername,
6662                                                         architecture,
6663                                                         level,
6664                                                         info_p,
6665                                                         count_p);
6666 }
6667
6668 /****************************************************************************
6669  Enumerates all printer drivers at level 1.
6670 ****************************************************************************/
6671
6672 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6673                                         const char *servername,
6674                                         const char *architecture,
6675                                         union spoolss_DriverInfo **info_p,
6676                                         uint32_t *count)
6677 {
6678         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6679                                         info_p, count);
6680 }
6681
6682 /****************************************************************************
6683  Enumerates all printer drivers at level 2.
6684 ****************************************************************************/
6685
6686 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6687                                         const char *servername,
6688                                         const char *architecture,
6689                                         union spoolss_DriverInfo **info_p,
6690                                         uint32_t *count)
6691 {
6692         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6693                                         info_p, count);
6694 }
6695
6696 /****************************************************************************
6697  Enumerates all printer drivers at level 3.
6698 ****************************************************************************/
6699
6700 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6701                                         const char *servername,
6702                                         const char *architecture,
6703                                         union spoolss_DriverInfo **info_p,
6704                                         uint32_t *count)
6705 {
6706         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6707                                         info_p, count);
6708 }
6709
6710 /****************************************************************************
6711  Enumerates all printer drivers at level 4.
6712 ****************************************************************************/
6713
6714 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6715                                         const char *servername,
6716                                         const char *architecture,
6717                                         union spoolss_DriverInfo **info_p,
6718                                         uint32_t *count)
6719 {
6720         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6721                                         info_p, count);
6722 }
6723
6724 /****************************************************************************
6725  Enumerates all printer drivers at level 5.
6726 ****************************************************************************/
6727
6728 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6729                                         const char *servername,
6730                                         const char *architecture,
6731                                         union spoolss_DriverInfo **info_p,
6732                                         uint32_t *count)
6733 {
6734         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6735                                         info_p, count);
6736 }
6737
6738 /****************************************************************************
6739  Enumerates all printer drivers at level 6.
6740 ****************************************************************************/
6741
6742 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6743                                         const char *servername,
6744                                         const char *architecture,
6745                                         union spoolss_DriverInfo **info_p,
6746                                         uint32_t *count)
6747 {
6748         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6749                                         info_p, count);
6750 }
6751
6752
6753 /****************************************************************
6754  _spoolss_EnumPrinterDrivers
6755 ****************************************************************/
6756
6757 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6758                                    struct spoolss_EnumPrinterDrivers *r)
6759 {
6760         const char *cservername;
6761         WERROR result;
6762
6763         /* that's an [in out] buffer */
6764
6765         if (!r->in.buffer && (r->in.offered != 0)) {
6766                 return WERR_INVALID_PARAM;
6767         }
6768
6769         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6770
6771         *r->out.needed = 0;
6772         *r->out.count = 0;
6773         *r->out.info = NULL;
6774
6775         cservername = canon_servername(r->in.server);
6776
6777         if (!is_myname_or_ipaddr(cservername)) {
6778                 return WERR_UNKNOWN_PRINTER_DRIVER;
6779         }
6780
6781         switch (r->in.level) {
6782         case 1:
6783                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6784                                                    r->in.environment,
6785                                                    r->out.info, r->out.count);
6786                 break;
6787         case 2:
6788                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6789                                                    r->in.environment,
6790                                                    r->out.info, r->out.count);
6791                 break;
6792         case 3:
6793                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6794                                                    r->in.environment,
6795                                                    r->out.info, r->out.count);
6796                 break;
6797         case 4:
6798                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6799                                                    r->in.environment,
6800                                                    r->out.info, r->out.count);
6801                 break;
6802         case 5:
6803                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6804                                                    r->in.environment,
6805                                                    r->out.info, r->out.count);
6806                 break;
6807         case 6:
6808                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6809                                                    r->in.environment,
6810                                                    r->out.info, r->out.count);
6811                 break;
6812         default:
6813                 return WERR_UNKNOWN_LEVEL;
6814         }
6815
6816         if (!W_ERROR_IS_OK(result)) {
6817                 return result;
6818         }
6819
6820         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6821                                                      spoolss_EnumPrinterDrivers, NULL,
6822                                                      *r->out.info, r->in.level,
6823                                                      *r->out.count);
6824         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6825         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6826
6827         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6828 }
6829
6830 /****************************************************************************
6831 ****************************************************************************/
6832
6833 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6834                                struct spoolss_FormInfo1 *r,
6835                                const nt_forms_struct *form)
6836 {
6837         r->form_name    = talloc_strdup(mem_ctx, form->name);
6838         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6839
6840         r->flags        = form->flag;
6841         r->size.width   = form->width;
6842         r->size.height  = form->length;
6843         r->area.left    = form->left;
6844         r->area.top     = form->top;
6845         r->area.right   = form->right;
6846         r->area.bottom  = form->bottom;
6847
6848         return WERR_OK;
6849 }
6850
6851 /****************************************************************
6852  spoolss_enumforms_level1
6853 ****************************************************************/
6854
6855 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6856                                        const nt_forms_struct *builtin_forms,
6857                                        uint32_t num_builtin_forms,
6858                                        const nt_forms_struct *user_forms,
6859                                        uint32_t num_user_forms,
6860                                        union spoolss_FormInfo **info_p,
6861                                        uint32_t *count)
6862 {
6863         union spoolss_FormInfo *info;
6864         WERROR result = WERR_OK;
6865         int i;
6866
6867         *count = num_builtin_forms + num_user_forms;
6868
6869         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6870         W_ERROR_HAVE_NO_MEMORY(info);
6871
6872         /* construct the list of form structures */
6873         for (i=0; i<num_builtin_forms; i++) {
6874                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6875                 result = fill_form_info_1(info, &info[i].info1,
6876                                           &builtin_forms[i]);
6877                 if (!W_ERROR_IS_OK(result)) {
6878                         goto out;
6879                 }
6880         }
6881
6882         for (i=0; i<num_user_forms; i++) {
6883                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6884                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6885                                           &user_forms[i]);
6886                 if (!W_ERROR_IS_OK(result)) {
6887                         goto out;
6888                 }
6889         }
6890
6891  out:
6892         if (!W_ERROR_IS_OK(result)) {
6893                 TALLOC_FREE(info);
6894                 *count = 0;
6895                 return result;
6896         }
6897
6898         *info_p = info;
6899
6900         return WERR_OK;
6901 }
6902
6903 /****************************************************************
6904  _spoolss_EnumForms
6905 ****************************************************************/
6906
6907 WERROR _spoolss_EnumForms(pipes_struct *p,
6908                           struct spoolss_EnumForms *r)
6909 {
6910         WERROR result;
6911         nt_forms_struct *user_forms = NULL;
6912         nt_forms_struct *builtin_forms = NULL;
6913         uint32_t num_user_forms;
6914         uint32_t num_builtin_forms;
6915
6916         *r->out.count = 0;
6917         *r->out.needed = 0;
6918         *r->out.info = NULL;
6919
6920         /* that's an [in out] buffer */
6921
6922         if (!r->in.buffer && (r->in.offered != 0) ) {
6923                 return WERR_INVALID_PARAM;
6924         }
6925
6926         DEBUG(4,("_spoolss_EnumForms\n"));
6927         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6928         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6929
6930         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6931         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6932         num_user_forms = get_ntforms(&user_forms);
6933         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6934
6935         if (num_user_forms + num_builtin_forms == 0) {
6936                 SAFE_FREE(builtin_forms);
6937                 SAFE_FREE(user_forms);
6938                 return WERR_NO_MORE_ITEMS;
6939         }
6940
6941         switch (r->in.level) {
6942         case 1:
6943                 result = spoolss_enumforms_level1(p->mem_ctx,
6944                                                   builtin_forms,
6945                                                   num_builtin_forms,
6946                                                   user_forms,
6947                                                   num_user_forms,
6948                                                   r->out.info,
6949                                                   r->out.count);
6950                 break;
6951         default:
6952                 result = WERR_UNKNOWN_LEVEL;
6953                 break;
6954         }
6955
6956         SAFE_FREE(user_forms);
6957         SAFE_FREE(builtin_forms);
6958
6959         if (!W_ERROR_IS_OK(result)) {
6960                 return result;
6961         }
6962
6963         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6964                                                      spoolss_EnumForms, NULL,
6965                                                      *r->out.info, r->in.level,
6966                                                      *r->out.count);
6967         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6968         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6969
6970         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6971 }
6972
6973 /****************************************************************
6974 ****************************************************************/
6975
6976 static WERROR find_form_byname(const char *name,
6977                                nt_forms_struct *form)
6978 {
6979         nt_forms_struct *list = NULL;
6980         int num_forms = 0, i = 0;
6981
6982         if (get_a_builtin_ntform_by_string(name, form)) {
6983                 return WERR_OK;
6984         }
6985
6986         num_forms = get_ntforms(&list);
6987         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6988
6989         if (num_forms == 0) {
6990                 return WERR_BADFID;
6991         }
6992
6993         /* Check if the requested name is in the list of form structures */
6994         for (i = 0; i < num_forms; i++) {
6995
6996                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6997
6998                 if (strequal(name, list[i].name)) {
6999                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7000                         *form = list[i];
7001                         SAFE_FREE(list);
7002                         return WERR_OK;
7003                 }
7004         }
7005
7006         SAFE_FREE(list);
7007
7008         return WERR_BADFID;
7009 }
7010
7011 /****************************************************************
7012  _spoolss_GetForm
7013 ****************************************************************/
7014
7015 WERROR _spoolss_GetForm(pipes_struct *p,
7016                         struct spoolss_GetForm *r)
7017 {
7018         WERROR result;
7019         nt_forms_struct form;
7020
7021         /* that's an [in out] buffer */
7022
7023         if (!r->in.buffer && (r->in.offered != 0)) {
7024                 return WERR_INVALID_PARAM;
7025         }
7026
7027         DEBUG(4,("_spoolss_GetForm\n"));
7028         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7029         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7030
7031         result = find_form_byname(r->in.form_name, &form);
7032         if (!W_ERROR_IS_OK(result)) {
7033                 TALLOC_FREE(r->out.info);
7034                 return result;
7035         }
7036
7037         switch (r->in.level) {
7038         case 1:
7039                 result = fill_form_info_1(p->mem_ctx,
7040                                           &r->out.info->info1,
7041                                           &form);
7042                 break;
7043
7044         default:
7045                 result = WERR_UNKNOWN_LEVEL;
7046                 break;
7047         }
7048
7049         if (!W_ERROR_IS_OK(result)) {
7050                 TALLOC_FREE(r->out.info);
7051                 return result;
7052         }
7053
7054         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7055                                                r->out.info, r->in.level);
7056         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7057
7058         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7059 }
7060
7061 /****************************************************************************
7062 ****************************************************************************/
7063
7064 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7065                           struct spoolss_PortInfo1 *r,
7066                           const char *name)
7067 {
7068         r->port_name = talloc_strdup(mem_ctx, name);
7069         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7070
7071         return WERR_OK;
7072 }
7073
7074 /****************************************************************************
7075  TODO: This probably needs distinguish between TCP/IP and Local ports
7076  somehow.
7077 ****************************************************************************/
7078
7079 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7080                           struct spoolss_PortInfo2 *r,
7081                           const char *name)
7082 {
7083         r->port_name = talloc_strdup(mem_ctx, name);
7084         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7085
7086         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7087         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7088
7089         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7090         W_ERROR_HAVE_NO_MEMORY(r->description);
7091
7092         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7093         r->reserved = 0;
7094
7095         return WERR_OK;
7096 }
7097
7098
7099 /****************************************************************************
7100  wrapper around the enumer ports command
7101 ****************************************************************************/
7102
7103 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7104 {
7105         char *cmd = lp_enumports_cmd();
7106         char **qlines = NULL;
7107         char *command = NULL;
7108         int numlines;
7109         int ret;
7110         int fd;
7111
7112         *count = 0;
7113         *lines = NULL;
7114
7115         /* if no hook then just fill in the default port */
7116
7117         if ( !*cmd ) {
7118                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7119                         return WERR_NOMEM;
7120                 }
7121                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7122                         TALLOC_FREE(qlines);
7123                         return WERR_NOMEM;
7124                 }
7125                 qlines[1] = NULL;
7126                 numlines = 1;
7127         }
7128         else {
7129                 /* we have a valid enumport command */
7130
7131                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7132                 if (!command) {
7133                         return WERR_NOMEM;
7134                 }
7135
7136                 DEBUG(10,("Running [%s]\n", command));
7137                 ret = smbrun(command, &fd);
7138                 DEBUG(10,("Returned [%d]\n", ret));
7139                 TALLOC_FREE(command);
7140                 if (ret != 0) {
7141                         if (fd != -1) {
7142                                 close(fd);
7143                         }
7144                         return WERR_ACCESS_DENIED;
7145                 }
7146
7147                 numlines = 0;
7148                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7149                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7150                 close(fd);
7151         }
7152
7153         *count = numlines;
7154         *lines = qlines;
7155
7156         return WERR_OK;
7157 }
7158
7159 /****************************************************************************
7160  enumports level 1.
7161 ****************************************************************************/
7162
7163 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7164                                 union spoolss_PortInfo **info_p,
7165                                 uint32_t *count)
7166 {
7167         union spoolss_PortInfo *info = NULL;
7168         int i=0;
7169         WERROR result = WERR_OK;
7170         char **qlines = NULL;
7171         int numlines = 0;
7172
7173         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7174         if (!W_ERROR_IS_OK(result)) {
7175                 goto out;
7176         }
7177
7178         if (numlines) {
7179                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7180                 if (!info) {
7181                         DEBUG(10,("Returning WERR_NOMEM\n"));
7182                         result = WERR_NOMEM;
7183                         goto out;
7184                 }
7185
7186                 for (i=0; i<numlines; i++) {
7187                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7188                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7189                         if (!W_ERROR_IS_OK(result)) {
7190                                 goto out;
7191                         }
7192                 }
7193         }
7194         TALLOC_FREE(qlines);
7195
7196 out:
7197         if (!W_ERROR_IS_OK(result)) {
7198                 TALLOC_FREE(info);
7199                 TALLOC_FREE(qlines);
7200                 *count = 0;
7201                 *info_p = NULL;
7202                 return result;
7203         }
7204
7205         *info_p = info;
7206         *count = numlines;
7207
7208         return WERR_OK;
7209 }
7210
7211 /****************************************************************************
7212  enumports level 2.
7213 ****************************************************************************/
7214
7215 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7216                                 union spoolss_PortInfo **info_p,
7217                                 uint32_t *count)
7218 {
7219         union spoolss_PortInfo *info = NULL;
7220         int i=0;
7221         WERROR result = WERR_OK;
7222         char **qlines = NULL;
7223         int numlines = 0;
7224
7225         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7226         if (!W_ERROR_IS_OK(result)) {
7227                 goto out;
7228         }
7229
7230         if (numlines) {
7231                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7232                 if (!info) {
7233                         DEBUG(10,("Returning WERR_NOMEM\n"));
7234                         result = WERR_NOMEM;
7235                         goto out;
7236                 }
7237
7238                 for (i=0; i<numlines; i++) {
7239                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7240                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7241                         if (!W_ERROR_IS_OK(result)) {
7242                                 goto out;
7243                         }
7244                 }
7245         }
7246         TALLOC_FREE(qlines);
7247
7248 out:
7249         if (!W_ERROR_IS_OK(result)) {
7250                 TALLOC_FREE(info);
7251                 TALLOC_FREE(qlines);
7252                 *count = 0;
7253                 *info_p = NULL;
7254                 return result;
7255         }
7256
7257         *info_p = info;
7258         *count = numlines;
7259
7260         return WERR_OK;
7261 }
7262
7263 /****************************************************************
7264  _spoolss_EnumPorts
7265 ****************************************************************/
7266
7267 WERROR _spoolss_EnumPorts(pipes_struct *p,
7268                           struct spoolss_EnumPorts *r)
7269 {
7270         WERROR result;
7271
7272         /* that's an [in out] buffer */
7273
7274         if (!r->in.buffer && (r->in.offered != 0)) {
7275                 return WERR_INVALID_PARAM;
7276         }
7277
7278         DEBUG(4,("_spoolss_EnumPorts\n"));
7279
7280         *r->out.count = 0;
7281         *r->out.needed = 0;
7282         *r->out.info = NULL;
7283
7284         switch (r->in.level) {
7285         case 1:
7286                 result = enumports_level_1(p->mem_ctx, r->out.info,
7287                                            r->out.count);
7288                 break;
7289         case 2:
7290                 result = enumports_level_2(p->mem_ctx, r->out.info,
7291                                            r->out.count);
7292                 break;
7293         default:
7294                 return WERR_UNKNOWN_LEVEL;
7295         }
7296
7297         if (!W_ERROR_IS_OK(result)) {
7298                 return result;
7299         }
7300
7301         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7302                                                      spoolss_EnumPorts, NULL,
7303                                                      *r->out.info, r->in.level,
7304                                                      *r->out.count);
7305         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7306         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7307
7308         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7309 }
7310
7311 /****************************************************************************
7312 ****************************************************************************/
7313
7314 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7315                                            const char *server,
7316                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7317                                            struct spoolss_DeviceMode *devmode,
7318                                            struct security_descriptor *sec_desc,
7319                                            struct spoolss_UserLevelCtr *user_ctr,
7320                                            struct policy_handle *handle)
7321 {
7322         NT_PRINTER_INFO_LEVEL *printer = NULL;
7323         fstring name;
7324         int     snum;
7325         WERROR err = WERR_OK;
7326
7327         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7328                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7329                 return WERR_NOMEM;
7330         }
7331
7332         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7333         if (!convert_printer_info(info_ctr, printer)) {
7334                 free_a_printer(&printer, 2);
7335                 return WERR_NOMEM;
7336         }
7337
7338         /* check to see if the printer already exists */
7339
7340         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7341                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7342                         printer->info_2->sharename));
7343                 free_a_printer(&printer, 2);
7344                 return WERR_PRINTER_ALREADY_EXISTS;
7345         }
7346
7347         /* FIXME!!!  smbd should check to see if the driver is installed before
7348            trying to add a printer like this  --jerry */
7349
7350         if (*lp_addprinter_cmd() ) {
7351                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7352                                        printer) ) {
7353                         free_a_printer(&printer,2);
7354                         return WERR_ACCESS_DENIED;
7355                 }
7356         } else {
7357                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7358                         "smb.conf parameter \"addprinter command\" is defined. This"
7359                         "parameter must exist for this call to succeed\n",
7360                         printer->info_2->sharename ));
7361         }
7362
7363         /* use our primary netbios name since get_a_printer() will convert
7364            it to what the client expects on a case by case basis */
7365
7366         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7367              printer->info_2->sharename);
7368
7369
7370         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7371                 free_a_printer(&printer,2);
7372                 return WERR_ACCESS_DENIED;
7373         }
7374
7375         /* you must be a printer admin to add a new printer */
7376         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7377                 free_a_printer(&printer,2);
7378                 return WERR_ACCESS_DENIED;
7379         }
7380
7381         /*
7382          * Do sanity check on the requested changes for Samba.
7383          */
7384
7385         if (!check_printer_ok(printer->info_2, snum)) {
7386                 free_a_printer(&printer,2);
7387                 return WERR_INVALID_PARAM;
7388         }
7389
7390         /*
7391          * When a printer is created, the drivername bound to the printer is used
7392          * to lookup previously saved driver initialization info, which is then
7393          * bound to the new printer, simulating what happens in the Windows arch.
7394          */
7395
7396         if (!devmode)
7397         {
7398                 set_driver_init(printer, 2);
7399         }
7400         else
7401         {
7402                 /* A valid devmode was included, convert and link it
7403                 */
7404                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7405
7406                 if (!convert_devicemode(printer->info_2->printername, devmode,
7407                                         &printer->info_2->devmode)) {
7408                         return  WERR_NOMEM;
7409                 }
7410         }
7411
7412         /* write the ASCII on disk */
7413         err = mod_a_printer(printer, 2);
7414         if (!W_ERROR_IS_OK(err)) {
7415                 free_a_printer(&printer,2);
7416                 return err;
7417         }
7418
7419         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7420                 /* Handle open failed - remove addition. */
7421                 del_a_printer(printer->info_2->sharename);
7422                 free_a_printer(&printer,2);
7423                 ZERO_STRUCTP(handle);
7424                 return WERR_ACCESS_DENIED;
7425         }
7426
7427         update_c_setprinter(false);
7428         free_a_printer(&printer,2);
7429
7430         return WERR_OK;
7431 }
7432
7433 /****************************************************************
7434  _spoolss_AddPrinterEx
7435 ****************************************************************/
7436
7437 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7438                              struct spoolss_AddPrinterEx *r)
7439 {
7440         switch (r->in.info_ctr->level) {
7441         case 1:
7442                 /* we don't handle yet */
7443                 /* but I know what to do ... */
7444                 return WERR_UNKNOWN_LEVEL;
7445         case 2:
7446                 return spoolss_addprinterex_level_2(p, r->in.server,
7447                                                     r->in.info_ctr,
7448                                                     r->in.devmode_ctr->devmode,
7449                                                     r->in.secdesc_ctr->sd,
7450                                                     r->in.userlevel_ctr,
7451                                                     r->out.handle);
7452         default:
7453                 return WERR_UNKNOWN_LEVEL;
7454         }
7455 }
7456
7457 /****************************************************************
7458  _spoolss_AddPrinter
7459 ****************************************************************/
7460
7461 WERROR _spoolss_AddPrinter(pipes_struct *p,
7462                            struct spoolss_AddPrinter *r)
7463 {
7464         struct spoolss_AddPrinterEx a;
7465         struct spoolss_UserLevelCtr userlevel_ctr;
7466
7467         ZERO_STRUCT(userlevel_ctr);
7468
7469         userlevel_ctr.level = 1;
7470
7471         a.in.server             = r->in.server;
7472         a.in.info_ctr           = r->in.info_ctr;
7473         a.in.devmode_ctr        = r->in.devmode_ctr;
7474         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7475         a.in.userlevel_ctr      = &userlevel_ctr;
7476         a.out.handle            = r->out.handle;
7477
7478         return _spoolss_AddPrinterEx(p, &a);
7479 }
7480
7481 /****************************************************************
7482  _spoolss_AddPrinterDriver
7483 ****************************************************************/
7484
7485 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7486                                  struct spoolss_AddPrinterDriver *r)
7487 {
7488         WERROR err = WERR_OK;
7489         char *driver_name = NULL;
7490         uint32_t version;
7491         const char *fn;
7492
7493         switch (p->hdr_req.opnum) {
7494                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7495                         fn = "_spoolss_AddPrinterDriver";
7496                         break;
7497                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7498                         fn = "_spoolss_AddPrinterDriverEx";
7499                         break;
7500                 default:
7501                         return WERR_INVALID_PARAM;
7502         }
7503
7504
7505         /* FIXME */
7506         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7507                 /* Clever hack from Martin Zielinski <mz@seh.de>
7508                  * to allow downgrade from level 8 (Vista).
7509                  */
7510                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7511                         r->in.info_ctr->level));
7512                 return WERR_UNKNOWN_LEVEL;
7513         }
7514
7515         DEBUG(5,("Cleaning driver's information\n"));
7516         err = clean_up_driver_struct(p, r->in.info_ctr);
7517         if (!W_ERROR_IS_OK(err))
7518                 goto done;
7519
7520         DEBUG(5,("Moving driver to final destination\n"));
7521         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7522                                                               &err)) ) {
7523                 goto done;
7524         }
7525
7526         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7527                 err = WERR_ACCESS_DENIED;
7528                 goto done;
7529         }
7530
7531         /*
7532          * I think this is where he DrvUpgradePrinter() hook would be
7533          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7534          * server.  Right now, we just need to send ourselves a message
7535          * to update each printer bound to this driver.   --jerry
7536          */
7537
7538         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7539                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7540                         fn, driver_name));
7541         }
7542
7543         /*
7544          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7545          * decide if the driver init data should be deleted. The rules are:
7546          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7547          *  2) delete init data only if there is no 2k/Xp driver
7548          *  3) always delete init data
7549          * The generalized rule is always use init data from the highest order driver.
7550          * It is necessary to follow the driver install by an initialization step to
7551          * finish off this process.
7552         */
7553
7554         switch (version) {
7555                 /*
7556                  * 9x printer driver - never delete init data
7557                 */
7558                 case 0:
7559                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7560                                 fn, driver_name));
7561                         break;
7562
7563                 /*
7564                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7565                  * there is no 2k/Xp driver init data for this driver name.
7566                 */
7567                 case 2:
7568                 {
7569                         union spoolss_DriverInfo *driver1;
7570
7571                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, 3, driver_name, "Windows NT x86", 3))) {
7572                                 /*
7573                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7574                                 */
7575                                 if (!del_driver_init(driver_name))
7576                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7577                                                 fn, driver_name));
7578                         } else {
7579                                 /*
7580                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7581                                 */
7582                                 free_a_printer_driver(driver1);
7583                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7584                                         fn, driver_name));
7585                         }
7586                 }
7587                 break;
7588
7589                 /*
7590                  * 2k or Xp printer driver - always delete init data
7591                 */
7592                 case 3:
7593                         if (!del_driver_init(driver_name))
7594                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7595                                         fn, driver_name));
7596                         break;
7597
7598                 default:
7599                         DEBUG(0,("%s: invalid level=%d\n", fn,
7600                                 r->in.info_ctr->level));
7601                         break;
7602         }
7603
7604
7605 done:
7606         return err;
7607 }
7608
7609 /****************************************************************
7610  _spoolss_AddPrinterDriverEx
7611 ****************************************************************/
7612
7613 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7614                                    struct spoolss_AddPrinterDriverEx *r)
7615 {
7616         struct spoolss_AddPrinterDriver a;
7617
7618         /*
7619          * we only support the semantics of AddPrinterDriver()
7620          * i.e. only copy files that are newer than existing ones
7621          */
7622
7623         if (r->in.flags != APD_COPY_NEW_FILES) {
7624                 return WERR_ACCESS_DENIED;
7625         }
7626
7627         a.in.servername         = r->in.servername;
7628         a.in.info_ctr           = r->in.info_ctr;
7629
7630         return _spoolss_AddPrinterDriver(p, &a);
7631 }
7632
7633 /****************************************************************************
7634 ****************************************************************************/
7635
7636 struct _spoolss_paths {
7637         int type;
7638         const char *share;
7639         const char *dir;
7640 };
7641
7642 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7643
7644 static const struct _spoolss_paths spoolss_paths[]= {
7645         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7646         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7647 };
7648
7649 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7650                                           const char *servername,
7651                                           const char *environment,
7652                                           int component,
7653                                           char **path)
7654 {
7655         const char *pservername = NULL;
7656         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7657         const char *short_archi;
7658
7659         *path = NULL;
7660
7661         /* environment may be empty */
7662         if (environment && strlen(environment)) {
7663                 long_archi = environment;
7664         }
7665
7666         /* servername may be empty */
7667         if (servername && strlen(servername)) {
7668                 pservername = canon_servername(servername);
7669
7670                 if (!is_myname_or_ipaddr(pservername)) {
7671                         return WERR_INVALID_PARAM;
7672                 }
7673         }
7674
7675         if (!(short_archi = get_short_archi(long_archi))) {
7676                 return WERR_INVALID_ENVIRONMENT;
7677         }
7678
7679         switch (component) {
7680         case SPOOLSS_PRTPROCS_PATH:
7681         case SPOOLSS_DRIVER_PATH:
7682                 if (pservername) {
7683                         *path = talloc_asprintf(mem_ctx,
7684                                         "\\\\%s\\%s\\%s",
7685                                         pservername,
7686                                         spoolss_paths[component].share,
7687                                         short_archi);
7688                 } else {
7689                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7690                                         SPOOLSS_DEFAULT_SERVER_PATH,
7691                                         spoolss_paths[component].dir,
7692                                         short_archi);
7693                 }
7694                 break;
7695         default:
7696                 return WERR_INVALID_PARAM;
7697         }
7698
7699         if (!*path) {
7700                 return WERR_NOMEM;
7701         }
7702
7703         return WERR_OK;
7704 }
7705
7706 /****************************************************************************
7707 ****************************************************************************/
7708
7709 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7710                                           const char *servername,
7711                                           const char *environment,
7712                                           struct spoolss_DriverDirectoryInfo1 *r)
7713 {
7714         WERROR werr;
7715         char *path = NULL;
7716
7717         werr = compose_spoolss_server_path(mem_ctx,
7718                                            servername,
7719                                            environment,
7720                                            SPOOLSS_DRIVER_PATH,
7721                                            &path);
7722         if (!W_ERROR_IS_OK(werr)) {
7723                 return werr;
7724         }
7725
7726         DEBUG(4,("printer driver directory: [%s]\n", path));
7727
7728         r->directory_name = path;
7729
7730         return WERR_OK;
7731 }
7732
7733 /****************************************************************
7734  _spoolss_GetPrinterDriverDirectory
7735 ****************************************************************/
7736
7737 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7738                                           struct spoolss_GetPrinterDriverDirectory *r)
7739 {
7740         WERROR werror;
7741
7742         /* that's an [in out] buffer */
7743
7744         if (!r->in.buffer && (r->in.offered != 0)) {
7745                 return WERR_INVALID_PARAM;
7746         }
7747
7748         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7749                 r->in.level));
7750
7751         *r->out.needed = 0;
7752
7753         /* r->in.level is ignored */
7754
7755         werror = getprinterdriverdir_level_1(p->mem_ctx,
7756                                              r->in.server,
7757                                              r->in.environment,
7758                                              &r->out.info->info1);
7759         if (!W_ERROR_IS_OK(werror)) {
7760                 TALLOC_FREE(r->out.info);
7761                 return werror;
7762         }
7763
7764         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7765                                                r->out.info, r->in.level);
7766         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7767
7768         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7769 }
7770
7771 /****************************************************************
7772  _spoolss_EnumPrinterData
7773 ****************************************************************/
7774
7775 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7776                                 struct spoolss_EnumPrinterData *r)
7777 {
7778         NT_PRINTER_INFO_LEVEL *printer = NULL;
7779         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7780         int             snum;
7781         WERROR          result;
7782         struct regval_blob      *val = NULL;
7783         NT_PRINTER_DATA *p_data;
7784         int             i, key_index, num_values;
7785         int             name_length;
7786
7787         *r->out.value_needed    = 0;
7788         *r->out.type            = REG_NONE;
7789         *r->out.data_needed     = 0;
7790
7791         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7792
7793         if (!Printer) {
7794                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7795                         OUR_HANDLE(r->in.handle)));
7796                 return WERR_BADFID;
7797         }
7798
7799         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7800                 return WERR_BADFID;
7801         }
7802
7803         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7804         if (!W_ERROR_IS_OK(result)) {
7805                 return result;
7806         }
7807
7808         p_data = printer->info_2->data;
7809         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7810
7811         result = WERR_OK;
7812
7813         /*
7814          * The NT machine wants to know the biggest size of value and data
7815          *
7816          * cf: MSDN EnumPrinterData remark section
7817          */
7818
7819         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7820
7821                 uint32_t biggest_valuesize = 0;
7822                 uint32_t biggest_datasize = 0;
7823
7824                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7825
7826                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7827
7828                 for ( i=0; i<num_values; i++ )
7829                 {
7830                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7831
7832                         name_length = strlen(val->valuename);
7833                         if ( strlen(val->valuename) > biggest_valuesize )
7834                                 biggest_valuesize = name_length;
7835
7836                         if ( val->size > biggest_datasize )
7837                                 biggest_datasize = val->size;
7838
7839                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7840                                 biggest_datasize));
7841                 }
7842
7843                 /* the value is an UNICODE string but real_value_size is the length
7844                    in bytes including the trailing 0 */
7845
7846                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7847                 *r->out.data_needed  = biggest_datasize;
7848
7849                 DEBUG(6,("final values: [%d], [%d]\n",
7850                         *r->out.value_needed, *r->out.data_needed));
7851
7852                 goto done;
7853         }
7854
7855         /*
7856          * the value len is wrong in NT sp3
7857          * that's the number of bytes not the number of unicode chars
7858          */
7859
7860         if (key_index != -1) {
7861                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7862                                                 r->in.enum_index);
7863         }
7864
7865         if (!val) {
7866
7867                 /* out_value should default to "" or else NT4 has
7868                    problems unmarshalling the response */
7869
7870                 if (r->in.value_offered) {
7871                         *r->out.value_needed = 1;
7872                         r->out.value_name = talloc_strdup(r, "");
7873                         if (!r->out.value_name) {
7874                                 result = WERR_NOMEM;
7875                                 goto done;
7876                         }
7877                 } else {
7878                         r->out.value_name = NULL;
7879                         *r->out.value_needed = 0;
7880                 }
7881
7882                 /* the data is counted in bytes */
7883
7884                 *r->out.data_needed = r->in.data_offered;
7885
7886                 result = WERR_NO_MORE_ITEMS;
7887         } else {
7888                 /*
7889                  * the value is:
7890                  * - counted in bytes in the request
7891                  * - counted in UNICODE chars in the max reply
7892                  * - counted in bytes in the real size
7893                  *
7894                  * take a pause *before* coding not *during* coding
7895                  */
7896
7897                 /* name */
7898                 if (r->in.value_offered) {
7899                         r->out.value_name = talloc_strdup(r, regval_name(val));
7900                         if (!r->out.value_name) {
7901                                 result = WERR_NOMEM;
7902                                 goto done;
7903                         }
7904                         *r->out.value_needed = strlen_m(regval_name(val));
7905                 } else {
7906                         r->out.value_name = NULL;
7907                         *r->out.value_needed = 0;
7908                 }
7909
7910                 /* type */
7911
7912                 *r->out.type = regval_type(val);
7913
7914                 /* data - counted in bytes */
7915
7916                 if (r->out.data && regval_size(val)) {
7917                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
7918                 }
7919
7920                 *r->out.data_needed = regval_size(val);
7921         }
7922
7923 done:
7924         free_a_printer(&printer, 2);
7925         return result;
7926 }
7927
7928 /****************************************************************
7929  _spoolss_SetPrinterData
7930 ****************************************************************/
7931
7932 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7933                                struct spoolss_SetPrinterData *r)
7934 {
7935         NT_PRINTER_INFO_LEVEL *printer = NULL;
7936         int snum=0;
7937         WERROR result = WERR_OK;
7938         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7939         DATA_BLOB blob;
7940
7941         DEBUG(5,("_spoolss_SetPrinterData\n"));
7942
7943         if (!Printer) {
7944                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7945                         OUR_HANDLE(r->in.handle)));
7946                 return WERR_BADFID;
7947         }
7948
7949         if (Printer->printer_type == SPLHND_SERVER) {
7950                 DEBUG(10,("_spoolss_SetPrinterData: "
7951                         "Not implemented for server handles yet\n"));
7952                 return WERR_INVALID_PARAM;
7953         }
7954
7955         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7956                 return WERR_BADFID;
7957         }
7958
7959         /*
7960          * Access check : NT returns "access denied" if you make a
7961          * SetPrinterData call without the necessary privildge.
7962          * we were originally returning OK if nothing changed
7963          * which made Win2k issue **a lot** of SetPrinterData
7964          * when connecting to a printer  --jerry
7965          */
7966
7967         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7968                 DEBUG(3,("_spoolss_SetPrinterData: "
7969                         "change denied by handle access permissions\n"));
7970                 result = WERR_ACCESS_DENIED;
7971                 goto done;
7972         }
7973
7974         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7975         if (!W_ERROR_IS_OK(result)) {
7976                 return result;
7977         }
7978
7979         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
7980                                           r->in.type, &r->in.data);
7981         if (!W_ERROR_IS_OK(result)) {
7982                 goto done;
7983         }
7984
7985         /*
7986          * When client side code sets a magic printer data key, detect it and save
7987          * the current printer data and the magic key's data (its the DEVMODE) for
7988          * future printer/driver initializations.
7989          */
7990         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
7991                 /* Set devmode and printer initialization info */
7992                 result = save_driver_init(printer, 2, blob.data, blob.length);
7993
7994                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
7995
7996                 goto done;
7997         }
7998
7999         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8000                                     r->in.value_name, r->in.type,
8001                                     blob.data, blob.length);
8002         if (W_ERROR_IS_OK(result)) {
8003                 result = mod_a_printer(printer, 2);
8004         }
8005
8006 done:
8007         free_a_printer(&printer, 2);
8008
8009         return result;
8010 }
8011
8012 /****************************************************************
8013  _spoolss_ResetPrinter
8014 ****************************************************************/
8015
8016 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8017                              struct spoolss_ResetPrinter *r)
8018 {
8019         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8020         int             snum;
8021
8022         DEBUG(5,("_spoolss_ResetPrinter\n"));
8023
8024         /*
8025          * All we do is to check to see if the handle and queue is valid.
8026          * This call really doesn't mean anything to us because we only
8027          * support RAW printing.   --jerry
8028          */
8029
8030         if (!Printer) {
8031                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8032                         OUR_HANDLE(r->in.handle)));
8033                 return WERR_BADFID;
8034         }
8035
8036         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8037                 return WERR_BADFID;
8038
8039
8040         /* blindly return success */
8041         return WERR_OK;
8042 }
8043
8044 /****************************************************************
8045  _spoolss_DeletePrinterData
8046 ****************************************************************/
8047
8048 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8049                                   struct spoolss_DeletePrinterData *r)
8050 {
8051         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8052         int             snum=0;
8053         WERROR          status = WERR_OK;
8054         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8055
8056         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8057
8058         if (!Printer) {
8059                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8060                         OUR_HANDLE(r->in.handle)));
8061                 return WERR_BADFID;
8062         }
8063
8064         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8065                 return WERR_BADFID;
8066
8067         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8068                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8069                         "printer properties change denied by handle\n"));
8070                 return WERR_ACCESS_DENIED;
8071         }
8072
8073         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8074         if (!W_ERROR_IS_OK(status))
8075                 return status;
8076
8077         if (!r->in.value_name) {
8078                 free_a_printer(&printer, 2);
8079                 return WERR_NOMEM;
8080         }
8081
8082         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8083                                         r->in.value_name );
8084
8085         if ( W_ERROR_IS_OK(status) )
8086                 mod_a_printer( printer, 2 );
8087
8088         free_a_printer(&printer, 2);
8089
8090         return status;
8091 }
8092
8093 /****************************************************************
8094  _spoolss_AddForm
8095 ****************************************************************/
8096
8097 WERROR _spoolss_AddForm(pipes_struct *p,
8098                         struct spoolss_AddForm *r)
8099 {
8100         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8101         nt_forms_struct tmpForm;
8102         int snum = -1;
8103         WERROR status = WERR_OK;
8104         NT_PRINTER_INFO_LEVEL *printer = NULL;
8105         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8106
8107         int count=0;
8108         nt_forms_struct *list=NULL;
8109         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8110
8111         DEBUG(5,("_spoolss_AddForm\n"));
8112
8113         if (!Printer) {
8114                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8115                         OUR_HANDLE(r->in.handle)));
8116                 return WERR_BADFID;
8117         }
8118
8119
8120         /* forms can be added on printer of on the print server handle */
8121
8122         if ( Printer->printer_type == SPLHND_PRINTER )
8123         {
8124                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8125                         return WERR_BADFID;
8126
8127                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8128                 if (!W_ERROR_IS_OK(status))
8129                         goto done;
8130         }
8131
8132         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8133            and not a printer admin, then fail */
8134
8135         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8136              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8137              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8138                                           NULL, NULL,
8139                                           p->server_info->ptok,
8140                                           lp_printer_admin(snum))) {
8141                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8142                 return WERR_ACCESS_DENIED;
8143         }
8144
8145         /* can't add if builtin */
8146
8147         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8148                 status = WERR_FILE_EXISTS;
8149                 goto done;
8150         }
8151
8152         count = get_ntforms(&list);
8153
8154         if(!add_a_form(&list, form, &count)) {
8155                 status =  WERR_NOMEM;
8156                 goto done;
8157         }
8158
8159         become_root();
8160         write_ntforms(&list, count);
8161         unbecome_root();
8162
8163         /*
8164          * ChangeID must always be set if this is a printer
8165          */
8166
8167         if ( Printer->printer_type == SPLHND_PRINTER )
8168                 status = mod_a_printer(printer, 2);
8169
8170 done:
8171         if ( printer )
8172                 free_a_printer(&printer, 2);
8173         SAFE_FREE(list);
8174
8175         return status;
8176 }
8177
8178 /****************************************************************
8179  _spoolss_DeleteForm
8180 ****************************************************************/
8181
8182 WERROR _spoolss_DeleteForm(pipes_struct *p,
8183                            struct spoolss_DeleteForm *r)
8184 {
8185         const char *form_name = r->in.form_name;
8186         nt_forms_struct tmpForm;
8187         int count=0;
8188         nt_forms_struct *list=NULL;
8189         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8190         int snum = -1;
8191         WERROR status = WERR_OK;
8192         NT_PRINTER_INFO_LEVEL *printer = NULL;
8193         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8194         bool ret = false;
8195
8196         DEBUG(5,("_spoolss_DeleteForm\n"));
8197
8198         if (!Printer) {
8199                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8200                         OUR_HANDLE(r->in.handle)));
8201                 return WERR_BADFID;
8202         }
8203
8204         /* forms can be deleted on printer of on the print server handle */
8205
8206         if ( Printer->printer_type == SPLHND_PRINTER )
8207         {
8208                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8209                         return WERR_BADFID;
8210
8211                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8212                 if (!W_ERROR_IS_OK(status))
8213                         goto done;
8214         }
8215
8216         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8217              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8218              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8219                                           NULL, NULL,
8220                                           p->server_info->ptok,
8221                                           lp_printer_admin(snum))) {
8222                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8223                 return WERR_ACCESS_DENIED;
8224         }
8225
8226
8227         /* can't delete if builtin */
8228
8229         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8230                 status = WERR_INVALID_PARAM;
8231                 goto done;
8232         }
8233
8234         count = get_ntforms(&list);
8235
8236         become_root();
8237         ret = delete_a_form(&list, form_name, &count, &status);
8238         unbecome_root();
8239         if (ret == false) {
8240                 goto done;
8241         }
8242
8243         /*
8244          * ChangeID must always be set if this is a printer
8245          */
8246
8247         if ( Printer->printer_type == SPLHND_PRINTER )
8248                 status = mod_a_printer(printer, 2);
8249
8250 done:
8251         if ( printer )
8252                 free_a_printer(&printer, 2);
8253         SAFE_FREE(list);
8254
8255         return status;
8256 }
8257
8258 /****************************************************************
8259  _spoolss_SetForm
8260 ****************************************************************/
8261
8262 WERROR _spoolss_SetForm(pipes_struct *p,
8263                         struct spoolss_SetForm *r)
8264 {
8265         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8266         nt_forms_struct tmpForm;
8267         int snum = -1;
8268         WERROR status = WERR_OK;
8269         NT_PRINTER_INFO_LEVEL *printer = NULL;
8270         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8271
8272         int count=0;
8273         nt_forms_struct *list=NULL;
8274         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8275
8276         DEBUG(5,("_spoolss_SetForm\n"));
8277
8278         if (!Printer) {
8279                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8280                         OUR_HANDLE(r->in.handle)));
8281                 return WERR_BADFID;
8282         }
8283
8284         /* forms can be modified on printer of on the print server handle */
8285
8286         if ( Printer->printer_type == SPLHND_PRINTER )
8287         {
8288                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8289                         return WERR_BADFID;
8290
8291                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8292                 if (!W_ERROR_IS_OK(status))
8293                         goto done;
8294         }
8295
8296         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8297            and not a printer admin, then fail */
8298
8299         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8300              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8301              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8302                                           NULL, NULL,
8303                                           p->server_info->ptok,
8304                                           lp_printer_admin(snum))) {
8305                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8306                 return WERR_ACCESS_DENIED;
8307         }
8308
8309         /* can't set if builtin */
8310         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8311                 status = WERR_INVALID_PARAM;
8312                 goto done;
8313         }
8314
8315         count = get_ntforms(&list);
8316         update_a_form(&list, form, count);
8317         become_root();
8318         write_ntforms(&list, count);
8319         unbecome_root();
8320
8321         /*
8322          * ChangeID must always be set if this is a printer
8323          */
8324
8325         if ( Printer->printer_type == SPLHND_PRINTER )
8326                 status = mod_a_printer(printer, 2);
8327
8328
8329 done:
8330         if ( printer )
8331                 free_a_printer(&printer, 2);
8332         SAFE_FREE(list);
8333
8334         return status;
8335 }
8336
8337 /****************************************************************************
8338  fill_print_processor1
8339 ****************************************************************************/
8340
8341 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8342                                     struct spoolss_PrintProcessorInfo1 *r,
8343                                     const char *print_processor_name)
8344 {
8345         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8346         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8347
8348         return WERR_OK;
8349 }
8350
8351 /****************************************************************************
8352  enumprintprocessors level 1.
8353 ****************************************************************************/
8354
8355 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8356                                           union spoolss_PrintProcessorInfo **info_p,
8357                                           uint32_t *count)
8358 {
8359         union spoolss_PrintProcessorInfo *info;
8360         WERROR result;
8361
8362         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8363         W_ERROR_HAVE_NO_MEMORY(info);
8364
8365         *count = 1;
8366
8367         result = fill_print_processor1(info, &info[0].info1, "winprint");
8368         if (!W_ERROR_IS_OK(result)) {
8369                 goto out;
8370         }
8371
8372  out:
8373         if (!W_ERROR_IS_OK(result)) {
8374                 TALLOC_FREE(info);
8375                 *count = 0;
8376                 return result;
8377         }
8378
8379         *info_p = info;
8380
8381         return WERR_OK;
8382 }
8383
8384 /****************************************************************
8385  _spoolss_EnumPrintProcessors
8386 ****************************************************************/
8387
8388 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8389                                     struct spoolss_EnumPrintProcessors *r)
8390 {
8391         WERROR result;
8392
8393         /* that's an [in out] buffer */
8394
8395         if (!r->in.buffer && (r->in.offered != 0)) {
8396                 return WERR_INVALID_PARAM;
8397         }
8398
8399         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8400
8401         /*
8402          * Enumerate the print processors ...
8403          *
8404          * Just reply with "winprint", to keep NT happy
8405          * and I can use my nice printer checker.
8406          */
8407
8408         *r->out.count = 0;
8409         *r->out.needed = 0;
8410         *r->out.info = NULL;
8411
8412         switch (r->in.level) {
8413         case 1:
8414                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8415                                                      r->out.count);
8416                 break;
8417         default:
8418                 return WERR_UNKNOWN_LEVEL;
8419         }
8420
8421         if (!W_ERROR_IS_OK(result)) {
8422                 return result;
8423         }
8424
8425         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8426                                                      spoolss_EnumPrintProcessors, NULL,
8427                                                      *r->out.info, r->in.level,
8428                                                      *r->out.count);
8429         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8430         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8431
8432         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8433 }
8434
8435 /****************************************************************************
8436  fill_printprocdatatype1
8437 ****************************************************************************/
8438
8439 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8440                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8441                                       const char *name_array)
8442 {
8443         r->name_array = talloc_strdup(mem_ctx, name_array);
8444         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8445
8446         return WERR_OK;
8447 }
8448
8449 /****************************************************************************
8450  enumprintprocdatatypes level 1.
8451 ****************************************************************************/
8452
8453 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8454                                              union spoolss_PrintProcDataTypesInfo **info_p,
8455                                              uint32_t *count)
8456 {
8457         WERROR result;
8458         union spoolss_PrintProcDataTypesInfo *info;
8459
8460         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8461         W_ERROR_HAVE_NO_MEMORY(info);
8462
8463         *count = 1;
8464
8465         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8466         if (!W_ERROR_IS_OK(result)) {
8467                 goto out;
8468         }
8469
8470  out:
8471         if (!W_ERROR_IS_OK(result)) {
8472                 TALLOC_FREE(info);
8473                 *count = 0;
8474                 return result;
8475         }
8476
8477         *info_p = info;
8478
8479         return WERR_OK;
8480 }
8481
8482 /****************************************************************
8483  _spoolss_EnumPrintProcDataTypes
8484 ****************************************************************/
8485
8486 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8487                                        struct spoolss_EnumPrintProcDataTypes *r)
8488 {
8489         WERROR result;
8490
8491         /* that's an [in out] buffer */
8492
8493         if (!r->in.buffer && (r->in.offered != 0)) {
8494                 return WERR_INVALID_PARAM;
8495         }
8496
8497         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8498
8499         *r->out.count = 0;
8500         *r->out.needed = 0;
8501         *r->out.info = NULL;
8502
8503         switch (r->in.level) {
8504         case 1:
8505                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8506                                                         r->out.count);
8507                 break;
8508         default:
8509                 return WERR_UNKNOWN_LEVEL;
8510         }
8511
8512         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8513                                                      spoolss_EnumPrintProcDataTypes, NULL,
8514                                                      *r->out.info, r->in.level,
8515                                                      *r->out.count);
8516         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8517         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8518
8519         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8520 }
8521
8522 /****************************************************************************
8523  fill_monitor_1
8524 ****************************************************************************/
8525
8526 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8527                              struct spoolss_MonitorInfo1 *r,
8528                              const char *monitor_name)
8529 {
8530         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8531         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8532
8533         return WERR_OK;
8534 }
8535
8536 /****************************************************************************
8537  fill_monitor_2
8538 ****************************************************************************/
8539
8540 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8541                              struct spoolss_MonitorInfo2 *r,
8542                              const char *monitor_name,
8543                              const char *environment,
8544                              const char *dll_name)
8545 {
8546         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8547         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8548         r->environment                  = talloc_strdup(mem_ctx, environment);
8549         W_ERROR_HAVE_NO_MEMORY(r->environment);
8550         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8551         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8552
8553         return WERR_OK;
8554 }
8555
8556 /****************************************************************************
8557  enumprintmonitors level 1.
8558 ****************************************************************************/
8559
8560 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8561                                         union spoolss_MonitorInfo **info_p,
8562                                         uint32_t *count)
8563 {
8564         union spoolss_MonitorInfo *info;
8565         WERROR result = WERR_OK;
8566
8567         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8568         W_ERROR_HAVE_NO_MEMORY(info);
8569
8570         *count = 2;
8571
8572         result = fill_monitor_1(info, &info[0].info1,
8573                                 SPL_LOCAL_PORT);
8574         if (!W_ERROR_IS_OK(result)) {
8575                 goto out;
8576         }
8577
8578         result = fill_monitor_1(info, &info[1].info1,
8579                                 SPL_TCPIP_PORT);
8580         if (!W_ERROR_IS_OK(result)) {
8581                 goto out;
8582         }
8583
8584 out:
8585         if (!W_ERROR_IS_OK(result)) {
8586                 TALLOC_FREE(info);
8587                 *count = 0;
8588                 return result;
8589         }
8590
8591         *info_p = info;
8592
8593         return WERR_OK;
8594 }
8595
8596 /****************************************************************************
8597  enumprintmonitors level 2.
8598 ****************************************************************************/
8599
8600 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8601                                         union spoolss_MonitorInfo **info_p,
8602                                         uint32_t *count)
8603 {
8604         union spoolss_MonitorInfo *info;
8605         WERROR result = WERR_OK;
8606
8607         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8608         W_ERROR_HAVE_NO_MEMORY(info);
8609
8610         *count = 2;
8611
8612         result = fill_monitor_2(info, &info[0].info2,
8613                                 SPL_LOCAL_PORT,
8614                                 "Windows NT X86", /* FIXME */
8615                                 "localmon.dll");
8616         if (!W_ERROR_IS_OK(result)) {
8617                 goto out;
8618         }
8619
8620         result = fill_monitor_2(info, &info[1].info2,
8621                                 SPL_TCPIP_PORT,
8622                                 "Windows NT X86", /* FIXME */
8623                                 "tcpmon.dll");
8624         if (!W_ERROR_IS_OK(result)) {
8625                 goto out;
8626         }
8627
8628 out:
8629         if (!W_ERROR_IS_OK(result)) {
8630                 TALLOC_FREE(info);
8631                 *count = 0;
8632                 return result;
8633         }
8634
8635         *info_p = info;
8636
8637         return WERR_OK;
8638 }
8639
8640 /****************************************************************
8641  _spoolss_EnumMonitors
8642 ****************************************************************/
8643
8644 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8645                              struct spoolss_EnumMonitors *r)
8646 {
8647         WERROR result;
8648
8649         /* that's an [in out] buffer */
8650
8651         if (!r->in.buffer && (r->in.offered != 0)) {
8652                 return WERR_INVALID_PARAM;
8653         }
8654
8655         DEBUG(5,("_spoolss_EnumMonitors\n"));
8656
8657         /*
8658          * Enumerate the print monitors ...
8659          *
8660          * Just reply with "Local Port", to keep NT happy
8661          * and I can use my nice printer checker.
8662          */
8663
8664         *r->out.count = 0;
8665         *r->out.needed = 0;
8666         *r->out.info = NULL;
8667
8668         switch (r->in.level) {
8669         case 1:
8670                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8671                                                    r->out.count);
8672                 break;
8673         case 2:
8674                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8675                                                    r->out.count);
8676                 break;
8677         default:
8678                 return WERR_UNKNOWN_LEVEL;
8679         }
8680
8681         if (!W_ERROR_IS_OK(result)) {
8682                 return result;
8683         }
8684
8685         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8686                                                      spoolss_EnumMonitors, NULL,
8687                                                      *r->out.info, r->in.level,
8688                                                      *r->out.count);
8689         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8690         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8691
8692         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8693 }
8694
8695 /****************************************************************************
8696 ****************************************************************************/
8697
8698 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8699                              const print_queue_struct *queue,
8700                              int count, int snum,
8701                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8702                              uint32_t jobid,
8703                              struct spoolss_JobInfo1 *r)
8704 {
8705         int i = 0;
8706         bool found = false;
8707
8708         for (i=0; i<count && found == false; i++) {
8709                 if (queue[i].job == (int)jobid) {
8710                         found = true;
8711                 }
8712         }
8713
8714         if (found == false) {
8715                 /* NT treats not found as bad param... yet another bad choice */
8716                 return WERR_INVALID_PARAM;
8717         }
8718
8719         return fill_job_info1(mem_ctx,
8720                               r,
8721                               &queue[i-1],
8722                               i,
8723                               snum,
8724                               ntprinter);
8725 }
8726
8727 /****************************************************************************
8728 ****************************************************************************/
8729
8730 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8731                              const print_queue_struct *queue,
8732                              int count, int snum,
8733                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8734                              uint32_t jobid,
8735                              struct spoolss_JobInfo2 *r)
8736 {
8737         int i = 0;
8738         bool found = false;
8739         struct spoolss_DeviceMode *devmode;
8740         NT_DEVICEMODE *nt_devmode;
8741         WERROR result;
8742
8743         for (i=0; i<count && found == false; i++) {
8744                 if (queue[i].job == (int)jobid) {
8745                         found = true;
8746                 }
8747         }
8748
8749         if (found == false) {
8750                 /* NT treats not found as bad param... yet another bad
8751                    choice */
8752                 return WERR_INVALID_PARAM;
8753         }
8754
8755         /*
8756          * if the print job does not have a DEVMODE associated with it,
8757          * just use the one for the printer. A NULL devicemode is not
8758          *  a failure condition
8759          */
8760
8761         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8762         if (nt_devmode) {
8763                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8764                 W_ERROR_HAVE_NO_MEMORY(devmode);
8765                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8766                 if (!W_ERROR_IS_OK(result)) {
8767                         return result;
8768                 }
8769         } else {
8770                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8771                 W_ERROR_HAVE_NO_MEMORY(devmode);
8772         }
8773
8774         return fill_job_info2(mem_ctx,
8775                               r,
8776                               &queue[i-1],
8777                               i,
8778                               snum,
8779                               ntprinter,
8780                               devmode);
8781 }
8782
8783 /****************************************************************
8784  _spoolss_GetJob
8785 ****************************************************************/
8786
8787 WERROR _spoolss_GetJob(pipes_struct *p,
8788                        struct spoolss_GetJob *r)
8789 {
8790         WERROR result = WERR_OK;
8791         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8792         int snum;
8793         int count;
8794         print_queue_struct      *queue = NULL;
8795         print_status_struct prt_status;
8796
8797         /* that's an [in out] buffer */
8798
8799         if (!r->in.buffer && (r->in.offered != 0)) {
8800                 return WERR_INVALID_PARAM;
8801         }
8802
8803         DEBUG(5,("_spoolss_GetJob\n"));
8804
8805         *r->out.needed = 0;
8806
8807         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8808                 return WERR_BADFID;
8809         }
8810
8811         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8812         if (!W_ERROR_IS_OK(result)) {
8813                 return result;
8814         }
8815
8816         count = print_queue_status(snum, &queue, &prt_status);
8817
8818         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8819                      count, prt_status.status, prt_status.message));
8820
8821         switch (r->in.level) {
8822         case 1:
8823                 result = getjob_level_1(p->mem_ctx,
8824                                         queue, count, snum, ntprinter,
8825                                         r->in.job_id, &r->out.info->info1);
8826                 break;
8827         case 2:
8828                 result = getjob_level_2(p->mem_ctx,
8829                                         queue, count, snum, ntprinter,
8830                                         r->in.job_id, &r->out.info->info2);
8831                 break;
8832         default:
8833                 result = WERR_UNKNOWN_LEVEL;
8834                 break;
8835         }
8836
8837         SAFE_FREE(queue);
8838         free_a_printer(&ntprinter, 2);
8839
8840         if (!W_ERROR_IS_OK(result)) {
8841                 TALLOC_FREE(r->out.info);
8842                 return result;
8843         }
8844
8845         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8846                                                r->out.info, r->in.level);
8847         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8848
8849         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8850 }
8851
8852 /****************************************************************
8853  _spoolss_GetPrinterDataEx
8854
8855  From MSDN documentation of GetPrinterDataEx: pass request
8856  to GetPrinterData if key is "PrinterDriverData".
8857 ****************************************************************/
8858
8859 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8860                                  struct spoolss_GetPrinterDataEx *r)
8861 {
8862
8863         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8864         struct regval_blob              *val = NULL;
8865         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8866         int                     snum = 0;
8867         WERROR result = WERR_OK;
8868
8869         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8870
8871         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8872                 r->in.key_name, r->in.value_name));
8873
8874         /* in case of problem, return some default values */
8875
8876         *r->out.needed  = 0;
8877         *r->out.type    = REG_NONE;
8878
8879         if (!Printer) {
8880                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8881                         OUR_HANDLE(r->in.handle)));
8882                 result = WERR_BADFID;
8883                 goto done;
8884         }
8885
8886         /* Is the handle to a printer or to the server? */
8887
8888         if (Printer->printer_type == SPLHND_SERVER) {
8889                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8890                         "Not implemented for server handles yet\n"));
8891                 result = WERR_INVALID_PARAM;
8892                 goto done;
8893         }
8894
8895         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8896                 return WERR_BADFID;
8897         }
8898
8899         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8900         if (!W_ERROR_IS_OK(result)) {
8901                 goto done;
8902         }
8903
8904         /* check to see if the keyname is valid */
8905         if (!strlen(r->in.key_name)) {
8906                 result = WERR_INVALID_PARAM;
8907                 goto done;
8908         }
8909
8910         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8911                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8912                         "Invalid keyname [%s]\n", r->in.key_name ));
8913                 result = WERR_BADFILE;
8914                 goto done;
8915         }
8916
8917         /* When given a new keyname, we should just create it */
8918
8919         val = get_printer_data(printer->info_2,
8920                                r->in.key_name, r->in.value_name);
8921         if (!val) {
8922                 result = WERR_BADFILE;
8923                 goto done;
8924         }
8925
8926         *r->out.needed = regval_size(val);
8927
8928         if (*r->out.needed > r->in.offered) {
8929                 result = WERR_MORE_DATA;
8930                 goto done;
8931         }
8932
8933         *r->out.type = regval_type(val);
8934
8935         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
8936
8937  done:
8938         if (printer) {
8939                 free_a_printer(&printer, 2);
8940         }
8941
8942         return result;
8943 }
8944
8945 /****************************************************************
8946  _spoolss_SetPrinterDataEx
8947 ****************************************************************/
8948
8949 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8950                                  struct spoolss_SetPrinterDataEx *r)
8951 {
8952         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8953         int                     snum = 0;
8954         WERROR                  result = WERR_OK;
8955         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8956         char                    *oid_string;
8957
8958         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8959
8960         /* From MSDN documentation of SetPrinterDataEx: pass request to
8961            SetPrinterData if key is "PrinterDriverData" */
8962
8963         if (!Printer) {
8964                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8965                         OUR_HANDLE(r->in.handle)));
8966                 return WERR_BADFID;
8967         }
8968
8969         if (Printer->printer_type == SPLHND_SERVER) {
8970                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8971                         "Not implemented for server handles yet\n"));
8972                 return WERR_INVALID_PARAM;
8973         }
8974
8975         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8976                 return WERR_BADFID;
8977         }
8978
8979         /*
8980          * Access check : NT returns "access denied" if you make a
8981          * SetPrinterData call without the necessary privildge.
8982          * we were originally returning OK if nothing changed
8983          * which made Win2k issue **a lot** of SetPrinterData
8984          * when connecting to a printer  --jerry
8985          */
8986
8987         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8988                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8989                         "change denied by handle access permissions\n"));
8990                 return WERR_ACCESS_DENIED;
8991         }
8992
8993         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8994         if (!W_ERROR_IS_OK(result)) {
8995                 return result;
8996         }
8997
8998         /* check for OID in valuename */
8999
9000         oid_string = strchr(r->in.value_name, ',');
9001         if (oid_string) {
9002                 *oid_string = '\0';
9003                 oid_string++;
9004         }
9005
9006         /* save the registry data */
9007
9008         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9009                                     r->in.type, r->in.buffer, r->in.offered);
9010
9011         if (W_ERROR_IS_OK(result)) {
9012                 /* save the OID if one was specified */
9013                 if (oid_string) {
9014                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9015                                 r->in.key_name, SPOOL_OID_KEY);
9016                         if (!str) {
9017                                 result = WERR_NOMEM;
9018                                 goto done;
9019                         }
9020
9021                         /*
9022                          * I'm not checking the status here on purpose.  Don't know
9023                          * if this is right, but I'm returning the status from the
9024                          * previous set_printer_dataex() call.  I have no idea if
9025                          * this is right.    --jerry
9026                          */
9027
9028                         set_printer_dataex(printer, str, r->in.value_name,
9029                                            REG_SZ, (uint8_t *)oid_string,
9030                                            strlen(oid_string)+1);
9031                 }
9032
9033                 result = mod_a_printer(printer, 2);
9034         }
9035
9036  done:
9037         free_a_printer(&printer, 2);
9038
9039         return result;
9040 }
9041
9042 /****************************************************************
9043  _spoolss_DeletePrinterDataEx
9044 ****************************************************************/
9045
9046 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9047                                     struct spoolss_DeletePrinterDataEx *r)
9048 {
9049         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9050         int             snum=0;
9051         WERROR          status = WERR_OK;
9052         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9053
9054         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9055
9056         if (!Printer) {
9057                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9058                         "Invalid handle (%s:%u:%u).\n",
9059                         OUR_HANDLE(r->in.handle)));
9060                 return WERR_BADFID;
9061         }
9062
9063         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9064                 return WERR_BADFID;
9065
9066         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9067                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9068                         "printer properties change denied by handle\n"));
9069                 return WERR_ACCESS_DENIED;
9070         }
9071
9072         if (!r->in.value_name || !r->in.key_name) {
9073                 return WERR_NOMEM;
9074         }
9075
9076         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9077         if (!W_ERROR_IS_OK(status))
9078                 return status;
9079
9080         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9081
9082         if ( W_ERROR_IS_OK(status) )
9083                 mod_a_printer( printer, 2 );
9084
9085         free_a_printer(&printer, 2);
9086
9087         return status;
9088 }
9089
9090 /****************************************************************
9091  _spoolss_EnumPrinterKey
9092 ****************************************************************/
9093
9094 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9095                                struct spoolss_EnumPrinterKey *r)
9096 {
9097         fstring         *keynames = NULL;
9098         int             num_keys;
9099         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9100         NT_PRINTER_DATA *data;
9101         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9102         int             snum = 0;
9103         WERROR          result = WERR_BADFILE;
9104         int i;
9105         const char **array = NULL;
9106         DATA_BLOB blob;
9107
9108         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9109
9110         if (!Printer) {
9111                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9112                         OUR_HANDLE(r->in.handle)));
9113                 return WERR_BADFID;
9114         }
9115
9116         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9117                 return WERR_BADFID;
9118         }
9119
9120         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9121         if (!W_ERROR_IS_OK(result)) {
9122                 return result;
9123         }
9124
9125         /* get the list of subkey names */
9126
9127         data = printer->info_2->data;
9128
9129         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9130         if (num_keys == -1) {
9131                 result = WERR_BADFILE;
9132                 goto done;
9133         }
9134
9135         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9136         if (!array) {
9137                 result = WERR_NOMEM;
9138                 goto done;
9139         }
9140
9141         for (i=0; i < num_keys; i++) {
9142
9143                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9144                         keynames[i]));
9145
9146                 array[i] = talloc_strdup(array, keynames[i]);
9147                 if (!array[i]) {
9148                         result = WERR_NOMEM;
9149                         goto done;
9150                 }
9151         }
9152
9153         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9154                 result = WERR_NOMEM;
9155                 goto done;
9156         }
9157
9158         *r->out.needed = blob.length;
9159
9160         if (r->in.offered < *r->out.needed) {
9161                 result = WERR_MORE_DATA;
9162         } else {
9163                 result = WERR_OK;
9164                 r->out.key_buffer->string = array;
9165         }
9166
9167  done:
9168         if (!W_ERROR_IS_OK(result)) {
9169                 TALLOC_FREE(array);
9170                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9171                         *r->out.needed = 0;
9172                 }
9173         }
9174
9175         free_a_printer(&printer, 2);
9176         SAFE_FREE(keynames);
9177
9178         return result;
9179 }
9180
9181 /****************************************************************
9182  _spoolss_DeletePrinterKey
9183 ****************************************************************/
9184
9185 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9186                                  struct spoolss_DeletePrinterKey *r)
9187 {
9188         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9189         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9190         int                     snum=0;
9191         WERROR                  status;
9192
9193         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9194
9195         if (!Printer) {
9196                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9197                         OUR_HANDLE(r->in.handle)));
9198                 return WERR_BADFID;
9199         }
9200
9201         /* if keyname == NULL, return error */
9202
9203         if ( !r->in.key_name )
9204                 return WERR_INVALID_PARAM;
9205
9206         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9207                 return WERR_BADFID;
9208
9209         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9210                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9211                         "printer properties change denied by handle\n"));
9212                 return WERR_ACCESS_DENIED;
9213         }
9214
9215         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9216         if (!W_ERROR_IS_OK(status))
9217                 return status;
9218
9219         /* delete the key and all subneys */
9220
9221         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9222
9223         if ( W_ERROR_IS_OK(status) )
9224                 status = mod_a_printer(printer, 2);
9225
9226         free_a_printer( &printer, 2 );
9227
9228         return status;
9229 }
9230
9231 /****************************************************************
9232 ****************************************************************/
9233
9234 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9235                                                    struct regval_blob *v,
9236                                                    struct spoolss_PrinterEnumValues *r)
9237 {
9238         WERROR result;
9239
9240         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9241         W_ERROR_HAVE_NO_MEMORY(r->data);
9242
9243         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9244         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9245
9246         r->type         = regval_type(v);
9247         r->data_length  = regval_size(v);
9248
9249         if (r->data_length) {
9250                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9251                                                  regval_size(v));
9252                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9253                                                   r->data,
9254                                                   r->type);
9255                 if (!W_ERROR_IS_OK(result)) {
9256                         return result;
9257                 }
9258         }
9259
9260         return WERR_OK;
9261 }
9262
9263 /****************************************************************
9264  _spoolss_EnumPrinterDataEx
9265 ****************************************************************/
9266
9267 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9268                                   struct spoolss_EnumPrinterDataEx *r)
9269 {
9270         uint32_t        count = 0;
9271         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9272         struct spoolss_PrinterEnumValues *info = NULL;
9273         NT_PRINTER_DATA         *p_data;
9274         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9275         int             snum;
9276         WERROR          result;
9277         int             key_index;
9278         int             i;
9279
9280         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9281
9282         *r->out.count = 0;
9283         *r->out.needed = 0;
9284         *r->out.info = NULL;
9285
9286         if (!Printer) {
9287                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9288                         OUR_HANDLE(r->in.handle)));
9289                 return WERR_BADFID;
9290         }
9291
9292         /*
9293          * first check for a keyname of NULL or "".  Win2k seems to send
9294          * this a lot and we should send back WERR_INVALID_PARAM
9295          * no need to spend time looking up the printer in this case.
9296          * --jerry
9297          */
9298
9299         if (!strlen(r->in.key_name)) {
9300                 result = WERR_INVALID_PARAM;
9301                 goto done;
9302         }
9303
9304         /* get the printer off of disk */
9305
9306         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9307                 return WERR_BADFID;
9308         }
9309
9310         ZERO_STRUCT(printer);
9311         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9312         if (!W_ERROR_IS_OK(result)) {
9313                 return result;
9314         }
9315
9316         /* now look for a match on the key name */
9317
9318         p_data = printer->info_2->data;
9319
9320         key_index = lookup_printerkey(p_data, r->in.key_name);
9321         if (key_index == -1) {
9322                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9323                         r->in.key_name));
9324                 result = WERR_INVALID_PARAM;
9325                 goto done;
9326         }
9327
9328         /* allocate the memory for the array of pointers -- if necessary */
9329
9330         count = regval_ctr_numvals(p_data->keys[key_index].values);
9331         if (!count) {
9332                 result = WERR_OK; /* ??? */
9333                 goto done;
9334         }
9335
9336         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9337                                  struct spoolss_PrinterEnumValues,
9338                                  count);
9339         if (!info) {
9340                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9341                 result = WERR_NOMEM;
9342                 goto done;
9343         }
9344
9345         /*
9346          * loop through all params and build the array to pass
9347          * back to the  client
9348          */
9349
9350         for (i=0; i < count; i++) {
9351
9352                 struct regval_blob      *val;
9353
9354                 /* lookup the registry value */
9355
9356                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9357
9358                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9359
9360                 /* copy the data */
9361
9362                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9363                 if (!W_ERROR_IS_OK(result)) {
9364                         goto done;
9365                 }
9366         }
9367
9368 #if 0 /* FIXME - gd */
9369         /* housekeeping information in the reply */
9370
9371         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9372          * the hand marshalled container size is a multiple
9373          * of 4 bytes for RPC alignment.
9374          */
9375
9376         if (needed % 4) {
9377                 needed += 4-(needed % 4);
9378         }
9379 #endif
9380         *r->out.count   = count;
9381         *r->out.info    = info;
9382
9383  done:
9384
9385         if (printer) {
9386                 free_a_printer(&printer, 2);
9387         }
9388
9389         if (!W_ERROR_IS_OK(result)) {
9390                 return result;
9391         }
9392
9393         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9394                                                spoolss_EnumPrinterDataEx, NULL,
9395                                                *r->out.info,
9396                                                *r->out.count);
9397         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9398         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9399
9400         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9401 }
9402
9403 /****************************************************************************
9404 ****************************************************************************/
9405
9406 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9407                                                  const char *servername,
9408                                                  const char *environment,
9409                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9410 {
9411         WERROR werr;
9412         char *path = NULL;
9413
9414         werr = compose_spoolss_server_path(mem_ctx,
9415                                            servername,
9416                                            environment,
9417                                            SPOOLSS_PRTPROCS_PATH,
9418                                            &path);
9419         if (!W_ERROR_IS_OK(werr)) {
9420                 return werr;
9421         }
9422
9423         DEBUG(4,("print processor directory: [%s]\n", path));
9424
9425         r->directory_name = path;
9426
9427         return WERR_OK;
9428 }
9429
9430 /****************************************************************
9431  _spoolss_GetPrintProcessorDirectory
9432 ****************************************************************/
9433
9434 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9435                                            struct spoolss_GetPrintProcessorDirectory *r)
9436 {
9437         WERROR result;
9438
9439         /* that's an [in out] buffer */
9440
9441         if (!r->in.buffer && (r->in.offered != 0)) {
9442                 return WERR_INVALID_PARAM;
9443         }
9444
9445         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9446                 r->in.level));
9447
9448         *r->out.needed = 0;
9449
9450         /* r->in.level is ignored */
9451
9452         /* We always should reply with a local print processor directory so that
9453          * users are not forced to have a [prnproc$] share on the Samba spoolss
9454          * server - Guenther */
9455
9456         result = getprintprocessordirectory_level_1(p->mem_ctx,
9457                                                     NULL, /* r->in.server */
9458                                                     r->in.environment,
9459                                                     &r->out.info->info1);
9460         if (!W_ERROR_IS_OK(result)) {
9461                 TALLOC_FREE(r->out.info);
9462                 return result;
9463         }
9464
9465         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9466                                                r->out.info, r->in.level);
9467         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9468
9469         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9470 }
9471
9472 /*******************************************************************
9473  ********************************************************************/
9474
9475 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9476                                const char *dllname)
9477 {
9478         enum ndr_err_code ndr_err;
9479         struct spoolss_MonitorUi ui;
9480
9481         ui.dll_name = dllname;
9482
9483         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9484                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9485         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9486                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9487         }
9488         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9489 }
9490
9491 /*******************************************************************
9492  Streams the monitor UI DLL name in UNICODE
9493 *******************************************************************/
9494
9495 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9496                                NT_USER_TOKEN *token, DATA_BLOB *in,
9497                                DATA_BLOB *out, uint32_t *needed)
9498 {
9499         const char *dllname = "tcpmonui.dll";
9500
9501         *needed = (strlen(dllname)+1) * 2;
9502
9503         if (out->length < *needed) {
9504                 return WERR_INSUFFICIENT_BUFFER;
9505         }
9506
9507         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9508                 return WERR_NOMEM;
9509         }
9510
9511         return WERR_OK;
9512 }
9513
9514 /*******************************************************************
9515  ********************************************************************/
9516
9517 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9518                              struct spoolss_PortData1 *port1,
9519                              const DATA_BLOB *buf)
9520 {
9521         enum ndr_err_code ndr_err;
9522         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9523                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9524         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9525                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9526         }
9527         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9528 }
9529
9530 /*******************************************************************
9531  ********************************************************************/
9532
9533 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9534                              struct spoolss_PortData2 *port2,
9535                              const DATA_BLOB *buf)
9536 {
9537         enum ndr_err_code ndr_err;
9538         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9539                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9540         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9541                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9542         }
9543         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9544 }
9545
9546 /*******************************************************************
9547  Create a new TCP/IP port
9548 *******************************************************************/
9549
9550 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9551                              NT_USER_TOKEN *token, DATA_BLOB *in,
9552                              DATA_BLOB *out, uint32_t *needed)
9553 {
9554         struct spoolss_PortData1 port1;
9555         struct spoolss_PortData2 port2;
9556         char *device_uri = NULL;
9557         uint32_t version;
9558
9559         const char *portname;
9560         const char *hostaddress;
9561         const char *queue;
9562         uint32_t port_number;
9563         uint32_t protocol;
9564
9565         /* peek for spoolss_PortData version */
9566
9567         if (!in || (in->length < (128 + 4))) {
9568                 return WERR_GENERAL_FAILURE;
9569         }
9570
9571         version = IVAL(in->data, 128);
9572
9573         switch (version) {
9574                 case 1:
9575                         ZERO_STRUCT(port1);
9576
9577                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9578                                 return WERR_NOMEM;
9579                         }
9580
9581                         portname        = port1.portname;
9582                         hostaddress     = port1.hostaddress;
9583                         queue           = port1.queue;
9584                         protocol        = port1.protocol;
9585                         port_number     = port1.port_number;
9586
9587                         break;
9588                 case 2:
9589                         ZERO_STRUCT(port2);
9590
9591                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9592                                 return WERR_NOMEM;
9593                         }
9594
9595                         portname        = port2.portname;
9596                         hostaddress     = port2.hostaddress;
9597                         queue           = port2.queue;
9598                         protocol        = port2.protocol;
9599                         port_number     = port2.port_number;
9600
9601                         break;
9602                 default:
9603                         DEBUG(1,("xcvtcp_addport: "
9604                                 "unknown version of port_data: %d\n", version));
9605                         return WERR_UNKNOWN_PORT;
9606         }
9607
9608         /* create the device URI and call the add_port_hook() */
9609
9610         switch (protocol) {
9611         case PROTOCOL_RAWTCP_TYPE:
9612                 device_uri = talloc_asprintf(mem_ctx,
9613                                 "socket://%s:%d/", hostaddress,
9614                                 port_number);
9615                 break;
9616
9617         case PROTOCOL_LPR_TYPE:
9618                 device_uri = talloc_asprintf(mem_ctx,
9619                         "lpr://%s/%s", hostaddress, queue );
9620                 break;
9621
9622         default:
9623                 return WERR_UNKNOWN_PORT;
9624         }
9625
9626         if (!device_uri) {
9627                 return WERR_NOMEM;
9628         }
9629
9630         return add_port_hook(mem_ctx, token, portname, device_uri);
9631 }
9632
9633 /*******************************************************************
9634 *******************************************************************/
9635
9636 struct xcv_api_table xcvtcp_cmds[] = {
9637         { "MonitorUI",  xcvtcp_monitorui },
9638         { "AddPort",    xcvtcp_addport},
9639         { NULL,         NULL }
9640 };
9641
9642 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9643                                      NT_USER_TOKEN *token, const char *command,
9644                                      DATA_BLOB *inbuf,
9645                                      DATA_BLOB *outbuf,
9646                                      uint32_t *needed )
9647 {
9648         int i;
9649
9650         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9651
9652         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9653                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9654                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9655         }
9656
9657         return WERR_BADFUNC;
9658 }
9659
9660 /*******************************************************************
9661 *******************************************************************/
9662 #if 0   /* don't support management using the "Local Port" monitor */
9663
9664 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9665                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9666                                  DATA_BLOB *out, uint32_t *needed)
9667 {
9668         const char *dllname = "localui.dll";
9669
9670         *needed = (strlen(dllname)+1) * 2;
9671
9672         if (out->length < *needed) {
9673                 return WERR_INSUFFICIENT_BUFFER;
9674         }
9675
9676         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9677                 return WERR_NOMEM;
9678         }
9679
9680         return WERR_OK;
9681 }
9682
9683 /*******************************************************************
9684 *******************************************************************/
9685
9686 struct xcv_api_table xcvlocal_cmds[] = {
9687         { "MonitorUI",  xcvlocal_monitorui },
9688         { NULL,         NULL }
9689 };
9690 #else
9691 struct xcv_api_table xcvlocal_cmds[] = {
9692         { NULL,         NULL }
9693 };
9694 #endif
9695
9696
9697
9698 /*******************************************************************
9699 *******************************************************************/
9700
9701 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9702                                        NT_USER_TOKEN *token, const char *command,
9703                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9704                                        uint32_t *needed)
9705 {
9706         int i;
9707
9708         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9709
9710         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9711                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9712                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9713         }
9714         return WERR_BADFUNC;
9715 }
9716
9717 /****************************************************************
9718  _spoolss_XcvData
9719 ****************************************************************/
9720
9721 WERROR _spoolss_XcvData(pipes_struct *p,
9722                         struct spoolss_XcvData *r)
9723 {
9724         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9725         DATA_BLOB out_data = data_blob_null;
9726         WERROR werror;
9727
9728         if (!Printer) {
9729                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9730                         OUR_HANDLE(r->in.handle)));
9731                 return WERR_BADFID;
9732         }
9733
9734         /* Has to be a handle to the TCP/IP port monitor */
9735
9736         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9737                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9738                 return WERR_BADFID;
9739         }
9740
9741         /* requires administrative access to the server */
9742
9743         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9744                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9745                 return WERR_ACCESS_DENIED;
9746         }
9747
9748         /* Allocate the outgoing buffer */
9749
9750         if (r->in.out_data_size) {
9751                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9752                 if (out_data.data == NULL) {
9753                         return WERR_NOMEM;
9754                 }
9755         }
9756
9757         switch ( Printer->printer_type ) {
9758         case SPLHND_PORTMON_TCP:
9759                 werror = process_xcvtcp_command(p->mem_ctx,
9760                                                 p->server_info->ptok,
9761                                                 r->in.function_name,
9762                                                 &r->in.in_data, &out_data,
9763                                                 r->out.needed);
9764                 break;
9765         case SPLHND_PORTMON_LOCAL:
9766                 werror = process_xcvlocal_command(p->mem_ctx,
9767                                                   p->server_info->ptok,
9768                                                   r->in.function_name,
9769                                                   &r->in.in_data, &out_data,
9770                                                   r->out.needed);
9771                 break;
9772         default:
9773                 werror = WERR_INVALID_PRINT_MONITOR;
9774         }
9775
9776         if (!W_ERROR_IS_OK(werror)) {
9777                 return werror;
9778         }
9779
9780         *r->out.status_code = 0;
9781
9782         memcpy(r->out.out_data, out_data.data, out_data.length);
9783
9784         return WERR_OK;
9785 }
9786
9787 /****************************************************************
9788  _spoolss_AddPrintProcessor
9789 ****************************************************************/
9790
9791 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9792                                   struct spoolss_AddPrintProcessor *r)
9793 {
9794         /* for now, just indicate success and ignore the add.  We'll
9795            automatically set the winprint processor for printer
9796            entries later.  Used to debug the LexMark Optra S 1855 PCL
9797            driver --jerry */
9798
9799         return WERR_OK;
9800 }
9801
9802 /****************************************************************
9803  _spoolss_AddPort
9804 ****************************************************************/
9805
9806 WERROR _spoolss_AddPort(pipes_struct *p,
9807                         struct spoolss_AddPort *r)
9808 {
9809         /* do what w2k3 does */
9810
9811         return WERR_NOT_SUPPORTED;
9812 }
9813
9814 /****************************************************************
9815  _spoolss_GetPrinterDriver
9816 ****************************************************************/
9817
9818 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9819                                  struct spoolss_GetPrinterDriver *r)
9820 {
9821         p->rng_fault_state = true;
9822         return WERR_NOT_SUPPORTED;
9823 }
9824
9825 /****************************************************************
9826  _spoolss_ReadPrinter
9827 ****************************************************************/
9828
9829 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9830                             struct spoolss_ReadPrinter *r)
9831 {
9832         p->rng_fault_state = true;
9833         return WERR_NOT_SUPPORTED;
9834 }
9835
9836 /****************************************************************
9837  _spoolss_WaitForPrinterChange
9838 ****************************************************************/
9839
9840 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9841                                      struct spoolss_WaitForPrinterChange *r)
9842 {
9843         p->rng_fault_state = true;
9844         return WERR_NOT_SUPPORTED;
9845 }
9846
9847 /****************************************************************
9848  _spoolss_ConfigurePort
9849 ****************************************************************/
9850
9851 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9852                               struct spoolss_ConfigurePort *r)
9853 {
9854         p->rng_fault_state = true;
9855         return WERR_NOT_SUPPORTED;
9856 }
9857
9858 /****************************************************************
9859  _spoolss_DeletePort
9860 ****************************************************************/
9861
9862 WERROR _spoolss_DeletePort(pipes_struct *p,
9863                            struct spoolss_DeletePort *r)
9864 {
9865         p->rng_fault_state = true;
9866         return WERR_NOT_SUPPORTED;
9867 }
9868
9869 /****************************************************************
9870  _spoolss_CreatePrinterIC
9871 ****************************************************************/
9872
9873 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9874                                 struct spoolss_CreatePrinterIC *r)
9875 {
9876         p->rng_fault_state = true;
9877         return WERR_NOT_SUPPORTED;
9878 }
9879
9880 /****************************************************************
9881  _spoolss_PlayGDIScriptOnPrinterIC
9882 ****************************************************************/
9883
9884 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9885                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9886 {
9887         p->rng_fault_state = true;
9888         return WERR_NOT_SUPPORTED;
9889 }
9890
9891 /****************************************************************
9892  _spoolss_DeletePrinterIC
9893 ****************************************************************/
9894
9895 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9896                                 struct spoolss_DeletePrinterIC *r)
9897 {
9898         p->rng_fault_state = true;
9899         return WERR_NOT_SUPPORTED;
9900 }
9901
9902 /****************************************************************
9903  _spoolss_AddPrinterConnection
9904 ****************************************************************/
9905
9906 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9907                                      struct spoolss_AddPrinterConnection *r)
9908 {
9909         p->rng_fault_state = true;
9910         return WERR_NOT_SUPPORTED;
9911 }
9912
9913 /****************************************************************
9914  _spoolss_DeletePrinterConnection
9915 ****************************************************************/
9916
9917 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9918                                         struct spoolss_DeletePrinterConnection *r)
9919 {
9920         p->rng_fault_state = true;
9921         return WERR_NOT_SUPPORTED;
9922 }
9923
9924 /****************************************************************
9925  _spoolss_PrinterMessageBox
9926 ****************************************************************/
9927
9928 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9929                                   struct spoolss_PrinterMessageBox *r)
9930 {
9931         p->rng_fault_state = true;
9932         return WERR_NOT_SUPPORTED;
9933 }
9934
9935 /****************************************************************
9936  _spoolss_AddMonitor
9937 ****************************************************************/
9938
9939 WERROR _spoolss_AddMonitor(pipes_struct *p,
9940                            struct spoolss_AddMonitor *r)
9941 {
9942         p->rng_fault_state = true;
9943         return WERR_NOT_SUPPORTED;
9944 }
9945
9946 /****************************************************************
9947  _spoolss_DeleteMonitor
9948 ****************************************************************/
9949
9950 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9951                               struct spoolss_DeleteMonitor *r)
9952 {
9953         p->rng_fault_state = true;
9954         return WERR_NOT_SUPPORTED;
9955 }
9956
9957 /****************************************************************
9958  _spoolss_DeletePrintProcessor
9959 ****************************************************************/
9960
9961 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9962                                      struct spoolss_DeletePrintProcessor *r)
9963 {
9964         p->rng_fault_state = true;
9965         return WERR_NOT_SUPPORTED;
9966 }
9967
9968 /****************************************************************
9969  _spoolss_AddPrintProvidor
9970 ****************************************************************/
9971
9972 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9973                                  struct spoolss_AddPrintProvidor *r)
9974 {
9975         p->rng_fault_state = true;
9976         return WERR_NOT_SUPPORTED;
9977 }
9978
9979 /****************************************************************
9980  _spoolss_DeletePrintProvidor
9981 ****************************************************************/
9982
9983 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9984                                     struct spoolss_DeletePrintProvidor *r)
9985 {
9986         p->rng_fault_state = true;
9987         return WERR_NOT_SUPPORTED;
9988 }
9989
9990 /****************************************************************
9991  _spoolss_FindFirstPrinterChangeNotification
9992 ****************************************************************/
9993
9994 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9995                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9996 {
9997         p->rng_fault_state = true;
9998         return WERR_NOT_SUPPORTED;
9999 }
10000
10001 /****************************************************************
10002  _spoolss_FindNextPrinterChangeNotification
10003 ****************************************************************/
10004
10005 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10006                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10007 {
10008         p->rng_fault_state = true;
10009         return WERR_NOT_SUPPORTED;
10010 }
10011
10012 /****************************************************************
10013  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10014 ****************************************************************/
10015
10016 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10017                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10018 {
10019         p->rng_fault_state = true;
10020         return WERR_NOT_SUPPORTED;
10021 }
10022
10023 /****************************************************************
10024  _spoolss_ReplyOpenPrinter
10025 ****************************************************************/
10026
10027 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10028                                  struct spoolss_ReplyOpenPrinter *r)
10029 {
10030         p->rng_fault_state = true;
10031         return WERR_NOT_SUPPORTED;
10032 }
10033
10034 /****************************************************************
10035  _spoolss_RouterReplyPrinter
10036 ****************************************************************/
10037
10038 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10039                                    struct spoolss_RouterReplyPrinter *r)
10040 {
10041         p->rng_fault_state = true;
10042         return WERR_NOT_SUPPORTED;
10043 }
10044
10045 /****************************************************************
10046  _spoolss_ReplyClosePrinter
10047 ****************************************************************/
10048
10049 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10050                                   struct spoolss_ReplyClosePrinter *r)
10051 {
10052         p->rng_fault_state = true;
10053         return WERR_NOT_SUPPORTED;
10054 }
10055
10056 /****************************************************************
10057  _spoolss_AddPortEx
10058 ****************************************************************/
10059
10060 WERROR _spoolss_AddPortEx(pipes_struct *p,
10061                           struct spoolss_AddPortEx *r)
10062 {
10063         p->rng_fault_state = true;
10064         return WERR_NOT_SUPPORTED;
10065 }
10066
10067 /****************************************************************
10068  _spoolss_RouterFindFirstPrinterChangeNotification
10069 ****************************************************************/
10070
10071 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10072                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10073 {
10074         p->rng_fault_state = true;
10075         return WERR_NOT_SUPPORTED;
10076 }
10077
10078 /****************************************************************
10079  _spoolss_SpoolerInit
10080 ****************************************************************/
10081
10082 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10083                             struct spoolss_SpoolerInit *r)
10084 {
10085         p->rng_fault_state = true;
10086         return WERR_NOT_SUPPORTED;
10087 }
10088
10089 /****************************************************************
10090  _spoolss_ResetPrinterEx
10091 ****************************************************************/
10092
10093 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10094                                struct spoolss_ResetPrinterEx *r)
10095 {
10096         p->rng_fault_state = true;
10097         return WERR_NOT_SUPPORTED;
10098 }
10099
10100 /****************************************************************
10101  _spoolss_RouterReplyPrinterEx
10102 ****************************************************************/
10103
10104 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10105                                      struct spoolss_RouterReplyPrinterEx *r)
10106 {
10107         p->rng_fault_state = true;
10108         return WERR_NOT_SUPPORTED;
10109 }
10110
10111 /****************************************************************
10112  _spoolss_44
10113 ****************************************************************/
10114
10115 WERROR _spoolss_44(pipes_struct *p,
10116                    struct spoolss_44 *r)
10117 {
10118         p->rng_fault_state = true;
10119         return WERR_NOT_SUPPORTED;
10120 }
10121
10122 /****************************************************************
10123  _spoolss_47
10124 ****************************************************************/
10125
10126 WERROR _spoolss_47(pipes_struct *p,
10127                    struct spoolss_47 *r)
10128 {
10129         p->rng_fault_state = true;
10130         return WERR_NOT_SUPPORTED;
10131 }
10132
10133 /****************************************************************
10134  _spoolss_4a
10135 ****************************************************************/
10136
10137 WERROR _spoolss_4a(pipes_struct *p,
10138                    struct spoolss_4a *r)
10139 {
10140         p->rng_fault_state = true;
10141         return WERR_NOT_SUPPORTED;
10142 }
10143
10144 /****************************************************************
10145  _spoolss_4b
10146 ****************************************************************/
10147
10148 WERROR _spoolss_4b(pipes_struct *p,
10149                    struct spoolss_4b *r)
10150 {
10151         p->rng_fault_state = true;
10152         return WERR_NOT_SUPPORTED;
10153 }
10154
10155 /****************************************************************
10156  _spoolss_4c
10157 ****************************************************************/
10158
10159 WERROR _spoolss_4c(pipes_struct *p,
10160                    struct spoolss_4c *r)
10161 {
10162         p->rng_fault_state = true;
10163         return WERR_NOT_SUPPORTED;
10164 }
10165
10166 /****************************************************************
10167  _spoolss_53
10168 ****************************************************************/
10169
10170 WERROR _spoolss_53(pipes_struct *p,
10171                    struct spoolss_53 *r)
10172 {
10173         p->rng_fault_state = true;
10174         return WERR_NOT_SUPPORTED;
10175 }
10176
10177 /****************************************************************
10178  _spoolss_55
10179 ****************************************************************/
10180
10181 WERROR _spoolss_55(pipes_struct *p,
10182                    struct spoolss_55 *r)
10183 {
10184         p->rng_fault_state = true;
10185         return WERR_NOT_SUPPORTED;
10186 }
10187
10188 /****************************************************************
10189  _spoolss_56
10190 ****************************************************************/
10191
10192 WERROR _spoolss_56(pipes_struct *p,
10193                    struct spoolss_56 *r)
10194 {
10195         p->rng_fault_state = true;
10196         return WERR_NOT_SUPPORTED;
10197 }
10198
10199 /****************************************************************
10200  _spoolss_57
10201 ****************************************************************/
10202
10203 WERROR _spoolss_57(pipes_struct *p,
10204                    struct spoolss_57 *r)
10205 {
10206         p->rng_fault_state = true;
10207         return WERR_NOT_SUPPORTED;
10208 }
10209
10210 /****************************************************************
10211  _spoolss_5a
10212 ****************************************************************/
10213
10214 WERROR _spoolss_5a(pipes_struct *p,
10215                    struct spoolss_5a *r)
10216 {
10217         p->rng_fault_state = true;
10218         return WERR_NOT_SUPPORTED;
10219 }
10220
10221 /****************************************************************
10222  _spoolss_5b
10223 ****************************************************************/
10224
10225 WERROR _spoolss_5b(pipes_struct *p,
10226                    struct spoolss_5b *r)
10227 {
10228         p->rng_fault_state = true;
10229         return WERR_NOT_SUPPORTED;
10230 }
10231
10232 /****************************************************************
10233  _spoolss_5c
10234 ****************************************************************/
10235
10236 WERROR _spoolss_5c(pipes_struct *p,
10237                    struct spoolss_5c *r)
10238 {
10239         p->rng_fault_state = true;
10240         return WERR_NOT_SUPPORTED;
10241 }
10242
10243 /****************************************************************
10244  _spoolss_5d
10245 ****************************************************************/
10246
10247 WERROR _spoolss_5d(pipes_struct *p,
10248                    struct spoolss_5d *r)
10249 {
10250         p->rng_fault_state = true;
10251         return WERR_NOT_SUPPORTED;
10252 }
10253
10254 /****************************************************************
10255  _spoolss_5e
10256 ****************************************************************/
10257
10258 WERROR _spoolss_5e(pipes_struct *p,
10259                    struct spoolss_5e *r)
10260 {
10261         p->rng_fault_state = true;
10262         return WERR_NOT_SUPPORTED;
10263 }
10264
10265 /****************************************************************
10266  _spoolss_5f
10267 ****************************************************************/
10268
10269 WERROR _spoolss_5f(pipes_struct *p,
10270                    struct spoolss_5f *r)
10271 {
10272         p->rng_fault_state = true;
10273         return WERR_NOT_SUPPORTED;
10274 }
10275
10276 /****************************************************************
10277  _spoolss_60
10278 ****************************************************************/
10279
10280 WERROR _spoolss_60(pipes_struct *p,
10281                    struct spoolss_60 *r)
10282 {
10283         p->rng_fault_state = true;
10284         return WERR_NOT_SUPPORTED;
10285 }
10286
10287 /****************************************************************
10288  _spoolss_61
10289 ****************************************************************/
10290
10291 WERROR _spoolss_61(pipes_struct *p,
10292                    struct spoolss_61 *r)
10293 {
10294         p->rng_fault_state = true;
10295         return WERR_NOT_SUPPORTED;
10296 }
10297
10298 /****************************************************************
10299  _spoolss_62
10300 ****************************************************************/
10301
10302 WERROR _spoolss_62(pipes_struct *p,
10303                    struct spoolss_62 *r)
10304 {
10305         p->rng_fault_state = true;
10306         return WERR_NOT_SUPPORTED;
10307 }
10308
10309 /****************************************************************
10310  _spoolss_63
10311 ****************************************************************/
10312
10313 WERROR _spoolss_63(pipes_struct *p,
10314                    struct spoolss_63 *r)
10315 {
10316         p->rng_fault_state = true;
10317         return WERR_NOT_SUPPORTED;
10318 }
10319
10320 /****************************************************************
10321  _spoolss_64
10322 ****************************************************************/
10323
10324 WERROR _spoolss_64(pipes_struct *p,
10325                    struct spoolss_64 *r)
10326 {
10327         p->rng_fault_state = true;
10328         return WERR_NOT_SUPPORTED;
10329 }
10330
10331 /****************************************************************
10332  _spoolss_65
10333 ****************************************************************/
10334
10335 WERROR _spoolss_65(pipes_struct *p,
10336                    struct spoolss_65 *r)
10337 {
10338         p->rng_fault_state = true;
10339         return WERR_NOT_SUPPORTED;
10340 }
10341
10342 /****************************************************************
10343  _spoolss_GetCorePrinterDrivers
10344 ****************************************************************/
10345
10346 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10347                                       struct spoolss_GetCorePrinterDrivers *r)
10348 {
10349         p->rng_fault_state = true;
10350         return WERR_NOT_SUPPORTED;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_67
10355 ****************************************************************/
10356
10357 WERROR _spoolss_67(pipes_struct *p,
10358                    struct spoolss_67 *r)
10359 {
10360         p->rng_fault_state = true;
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_GetPrinterDriverPackagePath
10366 ****************************************************************/
10367
10368 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10369                                             struct spoolss_GetPrinterDriverPackagePath *r)
10370 {
10371         p->rng_fault_state = true;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_69
10377 ****************************************************************/
10378
10379 WERROR _spoolss_69(pipes_struct *p,
10380                    struct spoolss_69 *r)
10381 {
10382         p->rng_fault_state = true;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_6a
10388 ****************************************************************/
10389
10390 WERROR _spoolss_6a(pipes_struct *p,
10391                    struct spoolss_6a *r)
10392 {
10393         p->rng_fault_state = true;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_6b
10399 ****************************************************************/
10400
10401 WERROR _spoolss_6b(pipes_struct *p,
10402                    struct spoolss_6b *r)
10403 {
10404         p->rng_fault_state = true;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_6c
10410 ****************************************************************/
10411
10412 WERROR _spoolss_6c(pipes_struct *p,
10413                    struct spoolss_6c *r)
10414 {
10415         p->rng_fault_state = true;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_6d
10421 ****************************************************************/
10422
10423 WERROR _spoolss_6d(pipes_struct *p,
10424                    struct spoolss_6d *r)
10425 {
10426         p->rng_fault_state = true;
10427         return WERR_NOT_SUPPORTED;
10428 }