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