73e2a7436447f67dd8a9365143bfb896fe234ff6
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35         ((info)?ndr_size_##fn(info, level, ic, 0):0)
36
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
39
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
42
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44
45
46 extern userdom_struct current_user_info;
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_RPC_SRV
50
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
53 #endif
54
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32_t counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected == true) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected = false;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231                                                 struct policy_handle *hnd)
232 {
233         Printer_entry *find_printer = NULL;
234
235         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
237                 return NULL;
238         }
239
240         return find_printer;
241 }
242
243 /****************************************************************************
244  Close printer index by handle.
245 ****************************************************************************/
246
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
248 {
249         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250
251         if (!Printer) {
252                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
253                         OUR_HANDLE(hnd)));
254                 return false;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return true;
260 }
261
262 /****************************************************************************
263  Delete a printer given a handle.
264 ****************************************************************************/
265
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
267 {
268         char *cmd = lp_deleteprinter_cmd();
269         char *command = NULL;
270         int ret;
271         SE_PRIV se_printop = SE_PRINT_OPERATOR;
272         bool is_print_op = false;
273
274         /* can't fail if we don't try */
275
276         if ( !*cmd )
277                 return WERR_OK;
278
279         command = talloc_asprintf(ctx,
280                         "%s \"%s\"",
281                         cmd, sharename);
282         if (!command) {
283                 return WERR_NOMEM;
284         }
285         if ( token )
286                 is_print_op = user_has_privileges( token, &se_printop );
287
288         DEBUG(10,("Running [%s]\n", command));
289
290         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
291
292         if ( is_print_op )
293                 become_root();
294
295         if ( (ret = smbrun(command, NULL)) == 0 ) {
296                 /* Tell everyone we updated smb.conf. */
297                 message_send_all(smbd_messaging_context(),
298                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299         }
300
301         if ( is_print_op )
302                 unbecome_root();
303
304         /********** END SePrintOperatorPrivlege BLOCK **********/
305
306         DEBUGADD(10,("returned [%d]\n", ret));
307
308         TALLOC_FREE(command);
309
310         if (ret != 0)
311                 return WERR_BADFID; /* What to return here? */
312
313         /* go ahead and re-read the services immediately */
314         become_root();
315         reload_services(false);
316         unbecome_root();
317
318         if ( lp_servicenumber( sharename )  < 0 )
319                 return WERR_ACCESS_DENIED;
320
321         return WERR_OK;
322 }
323
324 /****************************************************************************
325  Delete a printer given a handle.
326 ****************************************************************************/
327
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
329 {
330         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331
332         if (!Printer) {
333                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
334                         OUR_HANDLE(hnd)));
335                 return WERR_BADFID;
336         }
337
338         /*
339          * It turns out that Windows allows delete printer on a handle
340          * opened by an admin user, then used on a pipe handle created
341          * by an anonymous user..... but they're working on security.... riiight !
342          * JRA.
343          */
344
345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347                 return WERR_ACCESS_DENIED;
348         }
349
350         /* this does not need a become root since the access check has been
351            done on the handle already */
352
353         if (del_a_printer( Printer->sharename ) != 0) {
354                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
355                 return WERR_BADFID;
356         }
357
358         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359                                    Printer->sharename );
360 }
361
362 /****************************************************************************
363  Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
365
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367                              int *number, struct share_params **params)
368 {
369         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370
371         if (!Printer) {
372                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
373                         OUR_HANDLE(hnd)));
374                 return false;
375         }
376
377         switch (Printer->printer_type) {
378                 case SPLHND_PRINTER:
379                         DEBUG(4,("short name:%s\n", Printer->sharename));
380                         *number = print_queue_snum(Printer->sharename);
381                         return (*number != -1);
382                 case SPLHND_SERVER:
383                         return false;
384                 default:
385                         return false;
386         }
387 }
388
389 /****************************************************************************
390  Set printer handle type.
391  Check if it's \\server or \\server\printer
392 ****************************************************************************/
393
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
395 {
396         DEBUG(3,("Setting printer type=%s\n", handlename));
397
398         if ( strlen(handlename) < 3 ) {
399                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
400                 return false;
401         }
402
403         /* it's a print server */
404         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405                 DEBUGADD(4,("Printer is a print server\n"));
406                 Printer->printer_type = SPLHND_SERVER;
407         }
408         /* it's a printer (set_printer_hnd_name() will handle port monitors */
409         else {
410                 DEBUGADD(4,("Printer is a printer\n"));
411                 Printer->printer_type = SPLHND_PRINTER;
412         }
413
414         return true;
415 }
416
417 /****************************************************************************
418  Set printer handle name..  Accept names like \\server, \\server\printer,
419  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
420  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421  XcvDataPort() interface.
422 ****************************************************************************/
423
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 {
426         int snum;
427         int n_services=lp_numservices();
428         char *aprinter, *printername;
429         const char *servername;
430         fstring sname;
431         bool found = false;
432         NT_PRINTER_INFO_LEVEL *printer = NULL;
433         WERROR result;
434
435         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436                 (unsigned long)strlen(handlename)));
437
438         aprinter = CONST_DISCARD(char *, handlename);
439         if ( *handlename == '\\' ) {
440                 servername = canon_servername(handlename);
441                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
442                         *aprinter = '\0';
443                         aprinter++;
444                 }
445         } else {
446                 servername = global_myname();
447         }
448
449         /* save the servername to fill in replies on this handle */
450
451         if ( !is_myname_or_ipaddr( servername ) )
452                 return false;
453
454         fstrcpy( Printer->servername, servername );
455
456         if ( Printer->printer_type == SPLHND_SERVER )
457                 return true;
458
459         if ( Printer->printer_type != SPLHND_PRINTER )
460                 return false;
461
462         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
463
464         /* check for the Port Monitor Interface */
465
466         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467                 Printer->printer_type = SPLHND_PORTMON_TCP;
468                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469                 found = true;
470         }
471         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474                 found = true;
475         }
476
477         /* Search all sharenames first as this is easier than pulling
478            the printer_info_2 off of disk. Don't use find_service() since
479            that calls out to map_username() */
480
481         /* do another loop to look for printernames */
482
483         for (snum=0; !found && snum<n_services; snum++) {
484
485                 /* no point going on if this is not a printer */
486
487                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488                         continue;
489
490                 fstrcpy(sname, lp_servicename(snum));
491                 if ( strequal( aprinter, sname ) ) {
492                         found = true;
493                         break;
494                 }
495
496                 /* no point looking up the printer object if
497                    we aren't allowing printername != sharename */
498
499                 if ( lp_force_printername(snum) )
500                         continue;
501
502                 fstrcpy(sname, lp_servicename(snum));
503
504                 printer = NULL;
505
506                 /* This call doesn't fill in the location or comment from
507                  * a CUPS server for efficiency with large numbers of printers.
508                  * JRA.
509                  */
510
511                 result = get_a_printer_search( NULL, &printer, 2, sname );
512                 if ( !W_ERROR_IS_OK(result) ) {
513                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514                                 sname, win_errstr(result)));
515                         continue;
516                 }
517
518                 /* printername is always returned as \\server\printername */
519                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521                                 printer->info_2->printername));
522                         free_a_printer( &printer, 2);
523                         continue;
524                 }
525
526                 printername++;
527
528                 if ( strequal(printername, aprinter) ) {
529                         free_a_printer( &printer, 2);
530                         found = true;
531                         break;
532                 }
533
534                 DEBUGADD(10, ("printername: %s\n", printername));
535
536                 free_a_printer( &printer, 2);
537         }
538
539         free_a_printer( &printer, 2);
540
541         if ( !found ) {
542                 DEBUGADD(4,("Printer not found\n"));
543                 return false;
544         }
545
546         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
547
548         fstrcpy(Printer->sharename, sname);
549
550         return true;
551 }
552
553 /****************************************************************************
554  Find first available printer slot. creates a printer handle for you.
555  ****************************************************************************/
556
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558                              const char *name, uint32_t access_granted)
559 {
560         Printer_entry *new_printer;
561
562         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
563
564         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565         if (new_printer == NULL) {
566                 return false;
567         }
568         talloc_set_destructor(new_printer, printer_entry_destructor);
569
570         if (!create_policy_hnd(p, hnd, new_printer)) {
571                 TALLOC_FREE(new_printer);
572                 return false;
573         }
574
575         /* Add to the internal list. */
576         DLIST_ADD(printers_list, new_printer);
577
578         new_printer->notify.option=NULL;
579
580         if (!set_printer_hnd_printertype(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return false;
583         }
584
585         if (!set_printer_hnd_name(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         new_printer->access_granted = access_granted;
591
592         DEBUG(5, ("%d printer handles active\n",
593                   (int)num_pipe_handles(p->pipe_handles)));
594
595         return true;
596 }
597
598 /***************************************************************************
599  check to see if the client motify handle is monitoring the notification
600  given by (notify_type, notify_field).
601  **************************************************************************/
602
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604                                       uint16_t notify_field)
605 {
606         return true;
607 }
608
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610                                 uint16_t notify_field)
611 {
612         struct spoolss_NotifyOption *option = p->notify.option;
613         uint32_t i, j;
614
615         /*
616          * Flags should always be zero when the change notify
617          * is registered by the client's spooler.  A user Win32 app
618          * might use the flags though instead of the NOTIFY_OPTION_INFO
619          * --jerry
620          */
621
622         if (!option) {
623                 return false;
624         }
625
626         if (p->notify.flags)
627                 return is_monitoring_event_flags(
628                         p->notify.flags, notify_type, notify_field);
629
630         for (i = 0; i < option->count; i++) {
631
632                 /* Check match for notify_type */
633
634                 if (option->types[i].type != notify_type)
635                         continue;
636
637                 /* Check match for field */
638
639                 for (j = 0; j < option->types[i].count; j++) {
640                         if (option->types[i].fields[j].field == notify_field) {
641                                 return true;
642                         }
643                 }
644         }
645
646         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647                    p->servername, p->sharename, notify_type, notify_field));
648
649         return false;
650 }
651
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653         _data->data.integer[0] = _integer; \
654         _data->data.integer[1] = 0;
655
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659         if (!_data->data.string.string) {\
660                 _data->data.string.size = 0; \
661         } \
662         _data->data.string.size = strlen_m_term(_p) * 2;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665         _data->data.devmode.devmode = _devmode;
666
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669         if (!_data->data.sd.sd) { \
670                 _data->data.sd.sd_size = 0; \
671         } \
672         _data->data.sd.sd_size = _size;
673
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
675                                    struct tm *t,
676                                    const char **pp,
677                                    uint32_t *plen)
678 {
679         struct spoolss_Time st;
680         uint32_t len = 16;
681         char *p;
682
683         if (!init_systemtime(&st, t)) {
684                 return;
685         }
686
687         p = talloc_array(mem_ctx, char, len);
688         if (!p) {
689                 return;
690         }
691
692         /*
693          * Systemtime must be linearized as a set of UINT16's.
694          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695          */
696
697         SSVAL(p, 0, st.year);
698         SSVAL(p, 2, st.month);
699         SSVAL(p, 4, st.day_of_week);
700         SSVAL(p, 6, st.day);
701         SSVAL(p, 8, st.hour);
702         SSVAL(p, 10, st.minute);
703         SSVAL(p, 12, st.second);
704         SSVAL(p, 14, st.millisecond);
705
706         *pp = p;
707         *plen = len;
708 }
709
710 /* Convert a notification message to a struct spoolss_Notify */
711
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713                              struct spoolss_Notify *data,
714                              TALLOC_CTX *mem_ctx)
715 {
716         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 }
718
719 static void notify_string(struct spoolss_notify_msg *msg,
720                           struct spoolss_Notify *data,
721                           TALLOC_CTX *mem_ctx)
722 {
723         /* The length of the message includes the trailing \0 */
724
725         data->data.string.size = msg->len * 2;
726         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727         if (!data->data.string.string) {
728                 data->data.string.size = 0;
729                 return;
730         }
731 }
732
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734                                struct spoolss_Notify *data,
735                                TALLOC_CTX *mem_ctx)
736 {
737         data->data.string.string = NULL;
738         data->data.string.size = 0;
739
740         if (msg->len != sizeof(time_t)) {
741                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
742                           msg->len));
743                 return;
744         }
745
746         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747                                &data->data.string.string,
748                                &data->data.string.size);
749 }
750
751 struct notify2_message_table {
752         const char *name;
753         void (*fn)(struct spoolss_notify_msg *msg,
754                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 };
756
757 static struct notify2_message_table printer_notify_table[] = {
758         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 };
778
779 static struct notify2_message_table job_notify_table[] = {
780         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 };
805
806
807 /***********************************************************************
808  Allocate talloc context for container object
809  **********************************************************************/
810
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 {
813         if ( !ctr )
814                 return;
815
816         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817
818         return;
819 }
820
821 /***********************************************************************
822  release all allocated memory and zero out structure
823  **********************************************************************/
824
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 {
827         if ( !ctr )
828                 return;
829
830         if ( ctr->ctx )
831                 talloc_destroy(ctr->ctx);
832
833         ZERO_STRUCTP(ctr);
834
835         return;
836 }
837
838 /***********************************************************************
839  **********************************************************************/
840
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 {
843         if ( !ctr )
844                 return NULL;
845
846         return ctr->ctx;
847 }
848
849 /***********************************************************************
850  **********************************************************************/
851
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
853 {
854         if ( !ctr || !ctr->msg_groups )
855                 return NULL;
856
857         if ( idx >= ctr->num_groups )
858                 return NULL;
859
860         return &ctr->msg_groups[idx];
861
862 }
863
864 /***********************************************************************
865  How many groups of change messages do we have ?
866  **********************************************************************/
867
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 {
870         if ( !ctr )
871                 return 0;
872
873         return ctr->num_groups;
874 }
875
876 /***********************************************************************
877  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878  **********************************************************************/
879
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 {
882         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
883         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
884         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
885         int                             i, new_slot;
886
887         if ( !ctr || !msg )
888                 return 0;
889
890         /* loop over all groups looking for a matching printer name */
891
892         for ( i=0; i<ctr->num_groups; i++ ) {
893                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894                         break;
895         }
896
897         /* add a new group? */
898
899         if ( i == ctr->num_groups ) {
900                 ctr->num_groups++;
901
902                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904                         return 0;
905                 }
906                 ctr->msg_groups = groups;
907
908                 /* clear the new entry and set the printer name */
909
910                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912         }
913
914         /* add the change messages; 'i' is the correct index now regardless */
915
916         msg_grp = &ctr->msg_groups[i];
917
918         msg_grp->num_msgs++;
919
920         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922                 return 0;
923         }
924         msg_grp->msgs = msg_list;
925
926         new_slot = msg_grp->num_msgs-1;
927         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928
929         /* need to allocate own copy of data */
930
931         if ( msg->len != 0 )
932                 msg_grp->msgs[new_slot].notify.data = (char *)
933                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934
935         return ctr->num_groups;
936 }
937
938 /***********************************************************************
939  Send a change notication message on all handles which have a call
940  back registered
941  **********************************************************************/
942
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 {
945         Printer_entry            *p;
946         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
947         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948         SPOOLSS_NOTIFY_MSG       *messages;
949         int                      sending_msg_count;
950
951         if ( !msg_group ) {
952                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953                 return;
954         }
955
956         messages = msg_group->msgs;
957
958         if ( !messages ) {
959                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960                 return;
961         }
962
963         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964
965         /* loop over all printers */
966
967         for (p = printers_list; p; p = p->next) {
968                 struct spoolss_Notify *notifies;
969                 uint32_t count = 0;
970                 uint32_t id;
971                 int     i;
972
973                 /* Is there notification on this handle? */
974
975                 if ( !p->notify.client_connected )
976                         continue;
977
978                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979
980                 /* For this printer?  Print servers always receive
981                    notifications. */
982
983                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
984                     ( !strequal(msg_group->printername, p->sharename) ) )
985                         continue;
986
987                 DEBUG(10,("Our printer\n"));
988
989                 /* allocate the max entries possible */
990
991                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
992                 if (!notifies) {
993                         return;
994                 }
995
996                 /* build the array of change notifications */
997
998                 sending_msg_count = 0;
999
1000                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1002
1003                         /* Are we monitoring this event? */
1004
1005                         if (!is_monitoring_event(p, msg->type, msg->field))
1006                                 continue;
1007
1008                         sending_msg_count++;
1009
1010
1011                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012                                 msg->type, msg->field, p->sharename));
1013
1014                         /*
1015                          * if the is a printer notification handle and not a job notification
1016                          * type, then set the id to 0.  Other wise just use what was specified
1017                          * in the message.
1018                          *
1019                          * When registering change notification on a print server handle
1020                          * we always need to send back the id (snum) matching the printer
1021                          * for which the change took place.  For change notify registered
1022                          * on a printer handle, this does not matter and the id should be 0.
1023                          *
1024                          * --jerry
1025                          */
1026
1027                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028                                 id = 0;
1029                         else
1030                                 id = msg->id;
1031
1032
1033                         /* Convert unix jobid to smb jobid */
1034
1035                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036                                 id = sysjob_to_jobid(msg->id);
1037
1038                                 if (id == -1) {
1039                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040                                         goto done;
1041                                 }
1042                         }
1043
1044                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1045
1046                         switch(msg->type) {
1047                         case PRINTER_NOTIFY_TYPE:
1048                                 if ( printer_notify_table[msg->field].fn )
1049                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1050                                 break;
1051
1052                         case JOB_NOTIFY_TYPE:
1053                                 if ( job_notify_table[msg->field].fn )
1054                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1055                                 break;
1056
1057                         default:
1058                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059                                 goto done;
1060                         }
1061
1062                         count++;
1063                 }
1064
1065                 if ( sending_msg_count ) {
1066                         NTSTATUS status;
1067                         WERROR werr;
1068                         union spoolss_ReplyPrinterInfo info;
1069                         struct spoolss_NotifyInfo info0;
1070                         uint32_t reply_result;
1071
1072                         info0.version   = 0x2;
1073                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074                         info0.count     = count;
1075                         info0.notifies  = notifies;
1076
1077                         info.info0 = &info0;
1078
1079                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080                                                                      &p->notify.client_hnd,
1081                                                                      p->notify.change, /* color */
1082                                                                      p->notify.flags,
1083                                                                      &reply_result,
1084                                                                      0, /* reply_type, must be 0 */
1085                                                                      info,
1086                                                                      &werr);
1087                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089                                         notify_cli_pipe->srv_name_slash,
1090                                         win_errstr(werr)));
1091                         }
1092                         switch (reply_result) {
1093                                 case 0:
1094                                         break;
1095                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1096                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1098                                         break;
1099                                 default:
1100                                         break;
1101                         }
1102                 }
1103         }
1104
1105 done:
1106         DEBUG(8,("send_notify2_changes: Exit...\n"));
1107         return;
1108 }
1109
1110 /***********************************************************************
1111  **********************************************************************/
1112
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 {
1115
1116         uint32_t tv_sec, tv_usec;
1117         size_t offset = 0;
1118
1119         /* Unpack message */
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122                              msg->printer);
1123
1124         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1125                                 &tv_sec, &tv_usec,
1126                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127
1128         if (msg->len == 0)
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130                            &msg->notify.value[0], &msg->notify.value[1]);
1131         else
1132                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133                            &msg->len, &msg->notify.data);
1134
1135         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1137
1138         tv->tv_sec = tv_sec;
1139         tv->tv_usec = tv_usec;
1140
1141         if (msg->len == 0)
1142                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143                           msg->notify.value[1]));
1144         else
1145                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1146
1147         return true;
1148 }
1149
1150 /********************************************************************
1151  Receive a notify2 message list
1152  ********************************************************************/
1153
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1155                                          void *private_data,
1156                                          uint32_t msg_type,
1157                                          struct server_id server_id,
1158                                          DATA_BLOB *data)
1159 {
1160         size_t                  msg_count, i;
1161         char                    *buf = (char *)data->data;
1162         char                    *msg_ptr;
1163         size_t                  msg_len;
1164         SPOOLSS_NOTIFY_MSG      notify;
1165         SPOOLSS_NOTIFY_MSG_CTR  messages;
1166         int                     num_groups;
1167
1168         if (data->length < 4) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170                 return;
1171         }
1172
1173         msg_count = IVAL(buf, 0);
1174         msg_ptr = buf + 4;
1175
1176         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1177
1178         if (msg_count == 0) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180                 return;
1181         }
1182
1183         /* initialize the container */
1184
1185         ZERO_STRUCT( messages );
1186         notify_msg_ctr_init( &messages );
1187
1188         /*
1189          * build message groups for each printer identified
1190          * in a change_notify msg.  Remember that a PCN message
1191          * includes the handle returned for the srv_spoolss_replyopenprinter()
1192          * call.  Therefore messages are grouped according to printer handle.
1193          */
1194
1195         for ( i=0; i<msg_count; i++ ) {
1196                 struct timeval msg_tv;
1197
1198                 if (msg_ptr + 4 - buf > data->length) {
1199                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200                         return;
1201                 }
1202
1203                 msg_len = IVAL(msg_ptr,0);
1204                 msg_ptr += 4;
1205
1206                 if (msg_ptr + msg_len - buf > data->length) {
1207                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208                         return;
1209                 }
1210
1211                 /* unpack messages */
1212
1213                 ZERO_STRUCT( notify );
1214                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215                 msg_ptr += msg_len;
1216
1217                 /* add to correct list in container */
1218
1219                 notify_msg_ctr_addmsg( &messages, &notify );
1220
1221                 /* free memory that might have been allocated by notify2_unpack_msg() */
1222
1223                 if ( notify.len != 0 )
1224                         SAFE_FREE( notify.notify.data );
1225         }
1226
1227         /* process each group of messages */
1228
1229         num_groups = notify_msg_ctr_numgroups( &messages );
1230         for ( i=0; i<num_groups; i++ )
1231                 send_notify2_changes( &messages, i );
1232
1233
1234         /* cleanup */
1235
1236         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237                 (uint32_t)msg_count ));
1238
1239         notify_msg_ctr_destroy( &messages );
1240
1241         return;
1242 }
1243
1244 /********************************************************************
1245  Send a message to ourself about new driver being installed
1246  so we can upgrade the information for each printer bound to this
1247  driver
1248  ********************************************************************/
1249
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1251 {
1252         int len = strlen(drivername);
1253
1254         if (!len)
1255                 return false;
1256
1257         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258                 drivername));
1259
1260         messaging_send_buf(smbd_messaging_context(), procid_self(),
1261                            MSG_PRINTER_DRVUPGRADE,
1262                            (uint8_t *)drivername, len+1);
1263
1264         return true;
1265 }
1266
1267 /**********************************************************************
1268  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269  over all printers, upgrading ones as necessary
1270  **********************************************************************/
1271
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1273                             void *private_data,
1274                             uint32_t msg_type,
1275                             struct server_id server_id,
1276                             DATA_BLOB *data)
1277 {
1278         fstring drivername;
1279         int snum;
1280         int n_services = lp_numservices();
1281         size_t len;
1282
1283         len = MIN(data->length,sizeof(drivername)-1);
1284         strncpy(drivername, (const char *)data->data, len);
1285
1286         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287
1288         /* Iterate the printer list */
1289
1290         for (snum=0; snum<n_services; snum++)
1291         {
1292                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293                 {
1294                         WERROR result;
1295                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1296
1297                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298                         if (!W_ERROR_IS_OK(result))
1299                                 continue;
1300
1301                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302                         {
1303                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304
1305                                 /* all we care about currently is the change_id */
1306
1307                                 result = mod_a_printer(printer, 2);
1308                                 if (!W_ERROR_IS_OK(result)) {
1309                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310                                                 win_errstr(result)));
1311                                 }
1312                         }
1313
1314                         free_a_printer(&printer, 2);
1315                 }
1316         }
1317
1318         /* all done */
1319 }
1320
1321 /********************************************************************
1322  Update the cache for all printq's with a registered client
1323  connection
1324  ********************************************************************/
1325
1326 void update_monitored_printq_cache( void )
1327 {
1328         Printer_entry *printer = printers_list;
1329         int snum;
1330
1331         /* loop through all printers and update the cache where
1332            client_connected == true */
1333         while ( printer )
1334         {
1335                 if ( (printer->printer_type == SPLHND_PRINTER)
1336                         && printer->notify.client_connected )
1337                 {
1338                         snum = print_queue_snum(printer->sharename);
1339                         print_queue_status( snum, NULL, NULL );
1340                 }
1341
1342                 printer = printer->next;
1343         }
1344
1345         return;
1346 }
1347 /********************************************************************
1348  Send a message to ourself about new driver being installed
1349  so we can upgrade the information for each printer bound to this
1350  driver
1351  ********************************************************************/
1352
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 {
1355         int len = strlen(drivername);
1356
1357         if (!len)
1358                 return false;
1359
1360         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361                 drivername));
1362
1363         messaging_send_buf(smbd_messaging_context(), procid_self(),
1364                            MSG_PRINTERDATA_INIT_RESET,
1365                            (uint8_t *)drivername, len+1);
1366
1367         return true;
1368 }
1369
1370 /**********************************************************************
1371  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372  over all printers, resetting printer data as neessary
1373  **********************************************************************/
1374
1375 void reset_all_printerdata(struct messaging_context *msg,
1376                            void *private_data,
1377                            uint32_t msg_type,
1378                            struct server_id server_id,
1379                            DATA_BLOB *data)
1380 {
1381         fstring drivername;
1382         int snum;
1383         int n_services = lp_numservices();
1384         size_t len;
1385
1386         len = MIN( data->length, sizeof(drivername)-1 );
1387         strncpy( drivername, (const char *)data->data, len );
1388
1389         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390
1391         /* Iterate the printer list */
1392
1393         for ( snum=0; snum<n_services; snum++ )
1394         {
1395                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396                 {
1397                         WERROR result;
1398                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1399
1400                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401                         if ( !W_ERROR_IS_OK(result) )
1402                                 continue;
1403
1404                         /*
1405                          * if the printer is bound to the driver,
1406                          * then reset to the new driver initdata
1407                          */
1408
1409                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410                         {
1411                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412
1413                                 if ( !set_driver_init(printer, 2) ) {
1414                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415                                                 printer->info_2->printername, printer->info_2->drivername));
1416                                 }
1417
1418                                 result = mod_a_printer( printer, 2 );
1419                                 if ( !W_ERROR_IS_OK(result) ) {
1420                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1421                                                 get_dos_error_msg(result)));
1422                                 }
1423                         }
1424
1425                         free_a_printer( &printer, 2 );
1426                 }
1427         }
1428
1429         /* all done */
1430
1431         return;
1432 }
1433
1434 /****************************************************************
1435  _spoolss_OpenPrinter
1436 ****************************************************************/
1437
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439                             struct spoolss_OpenPrinter *r)
1440 {
1441         struct spoolss_OpenPrinterEx e;
1442         WERROR werr;
1443
1444         ZERO_STRUCT(e.in.userlevel);
1445
1446         e.in.printername        = r->in.printername;
1447         e.in.datatype           = r->in.datatype;
1448         e.in.devmode_ctr        = r->in.devmode_ctr;
1449         e.in.access_mask        = r->in.access_mask;
1450         e.in.level              = 0;
1451
1452         e.out.handle            = r->out.handle;
1453
1454         werr = _spoolss_OpenPrinterEx(p, &e);
1455
1456         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457                 /* OpenPrinterEx returns this for a bad
1458                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1459                  * instead.
1460                  */
1461                 werr = WERR_INVALID_PRINTER_NAME;
1462         }
1463
1464         return werr;
1465 }
1466
1467 /********************************************************************
1468  ********************************************************************/
1469
1470 bool convert_devicemode(const char *printername,
1471                         const struct spoolss_DeviceMode *devmode,
1472                         NT_DEVICEMODE **pp_nt_devmode)
1473 {
1474         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475
1476         /*
1477          * Ensure nt_devmode is a valid pointer
1478          * as we will be overwriting it.
1479          */
1480
1481         if (nt_devmode == NULL) {
1482                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484                         return false;
1485         }
1486
1487         fstrcpy(nt_devmode->devicename, devmode->devicename);
1488         fstrcpy(nt_devmode->formname, devmode->formname);
1489
1490         nt_devmode->devicename[31] = '\0';
1491         nt_devmode->formname[31] = '\0';
1492
1493         nt_devmode->specversion         = devmode->specversion;
1494         nt_devmode->driverversion       = devmode->driverversion;
1495         nt_devmode->size                = devmode->size;
1496         nt_devmode->fields              = devmode->fields;
1497         nt_devmode->orientation         = devmode->orientation;
1498         nt_devmode->papersize           = devmode->papersize;
1499         nt_devmode->paperlength         = devmode->paperlength;
1500         nt_devmode->paperwidth          = devmode->paperwidth;
1501         nt_devmode->scale               = devmode->scale;
1502         nt_devmode->copies              = devmode->copies;
1503         nt_devmode->defaultsource       = devmode->defaultsource;
1504         nt_devmode->printquality        = devmode->printquality;
1505         nt_devmode->color               = devmode->color;
1506         nt_devmode->duplex              = devmode->duplex;
1507         nt_devmode->yresolution         = devmode->yresolution;
1508         nt_devmode->ttoption            = devmode->ttoption;
1509         nt_devmode->collate             = devmode->collate;
1510
1511         nt_devmode->logpixels           = devmode->logpixels;
1512         nt_devmode->bitsperpel          = devmode->bitsperpel;
1513         nt_devmode->pelswidth           = devmode->pelswidth;
1514         nt_devmode->pelsheight          = devmode->pelsheight;
1515         nt_devmode->displayflags        = devmode->displayflags;
1516         nt_devmode->displayfrequency    = devmode->displayfrequency;
1517         nt_devmode->icmmethod           = devmode->icmmethod;
1518         nt_devmode->icmintent           = devmode->icmintent;
1519         nt_devmode->mediatype           = devmode->mediatype;
1520         nt_devmode->dithertype          = devmode->dithertype;
1521         nt_devmode->reserved1           = devmode->reserved1;
1522         nt_devmode->reserved2           = devmode->reserved2;
1523         nt_devmode->panningwidth        = devmode->panningwidth;
1524         nt_devmode->panningheight       = devmode->panningheight;
1525
1526         /*
1527          * Only change private and driverextra if the incoming devmode
1528          * has a new one. JRA.
1529          */
1530
1531         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532                 SAFE_FREE(nt_devmode->nt_dev_private);
1533                 nt_devmode->driverextra = devmode->__driverextra_length;
1534                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1535                         return false;
1536                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1537         }
1538
1539         *pp_nt_devmode = nt_devmode;
1540
1541         return true;
1542 }
1543
1544 /****************************************************************
1545  _spoolss_OpenPrinterEx
1546 ****************************************************************/
1547
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549                               struct spoolss_OpenPrinterEx *r)
1550 {
1551         int snum;
1552         Printer_entry *Printer=NULL;
1553
1554         if (!r->in.printername) {
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         /* some sanity check because you can open a printer or a print server */
1559         /* aka: \\server\printer or \\server */
1560
1561         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1562
1563         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564                 ZERO_STRUCTP(r->out.handle);
1565                 return WERR_INVALID_PARAM;
1566         }
1567
1568         Printer = find_printer_index_by_hnd(p, r->out.handle);
1569         if ( !Printer ) {
1570                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1571                         "handle we created for printer %s\n", r->in.printername));
1572                 close_printer_handle(p, r->out.handle);
1573                 ZERO_STRUCTP(r->out.handle);
1574                 return WERR_INVALID_PARAM;
1575         }
1576
1577         /*
1578          * First case: the user is opening the print server:
1579          *
1580          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1582          *
1583          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585          * or if the user is listed in the smb.conf printer admin parameter.
1586          *
1587          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588          * client view printer folder, but does not show the MSAPW.
1589          *
1590          * Note: this test needs code to check access rights here too. Jeremy
1591          * could you look at this?
1592          *
1593          * Second case: the user is opening a printer:
1594          * NT doesn't let us connect to a printer if the connecting user
1595          * doesn't have print permission.
1596          *
1597          * Third case: user is opening a Port Monitor
1598          * access checks same as opening a handle to the print server.
1599          */
1600
1601         switch (Printer->printer_type )
1602         {
1603         case SPLHND_SERVER:
1604         case SPLHND_PORTMON_TCP:
1605         case SPLHND_PORTMON_LOCAL:
1606                 /* Printserver handles use global struct... */
1607
1608                 snum = -1;
1609
1610                 /* Map standard access rights to object specific access rights */
1611
1612                 se_map_standard(&r->in.access_mask,
1613                                 &printserver_std_mapping);
1614
1615                 /* Deny any object specific bits that don't apply to print
1616                    servers (i.e printer and job specific bits) */
1617
1618                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1619
1620                 if (r->in.access_mask &
1621                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623                         close_printer_handle(p, r->out.handle);
1624                         ZERO_STRUCTP(r->out.handle);
1625                         return WERR_ACCESS_DENIED;
1626                 }
1627
1628                 /* Allow admin access */
1629
1630                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1631                 {
1632                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1633
1634                         if (!lp_ms_add_printer_wizard()) {
1635                                 close_printer_handle(p, r->out.handle);
1636                                 ZERO_STRUCTP(r->out.handle);
1637                                 return WERR_ACCESS_DENIED;
1638                         }
1639
1640                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641                            and not a printer admin, then fail */
1642
1643                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644                             !user_has_privileges(p->server_info->ptok,
1645                                                  &se_printop ) &&
1646                             !token_contains_name_in_list(
1647                                     uidtoname(p->server_info->utok.uid),
1648                                     NULL, NULL,
1649                                     p->server_info->ptok,
1650                                     lp_printer_admin(snum))) {
1651                                 close_printer_handle(p, r->out.handle);
1652                                 ZERO_STRUCTP(r->out.handle);
1653                                 return WERR_ACCESS_DENIED;
1654                         }
1655
1656                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657                 }
1658                 else
1659                 {
1660                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661                 }
1662
1663                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1665
1666                 /* We fall through to return WERR_OK */
1667                 break;
1668
1669         case SPLHND_PRINTER:
1670                 /* NT doesn't let us connect to a printer if the connecting user
1671                    doesn't have print permission.  */
1672
1673                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674                         close_printer_handle(p, r->out.handle);
1675                         ZERO_STRUCTP(r->out.handle);
1676                         return WERR_BADFID;
1677                 }
1678
1679                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681                 }
1682
1683                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1684
1685                 /* map an empty access mask to the minimum access mask */
1686                 if (r->in.access_mask == 0x0)
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688
1689                 /*
1690                  * If we are not serving the printer driver for this printer,
1691                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1692                  * will keep NT clients happy  --jerry
1693                  */
1694
1695                 if (lp_use_client_driver(snum)
1696                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1697                 {
1698                         r->in.access_mask = PRINTER_ACCESS_USE;
1699                 }
1700
1701                 /* check smb.conf parameters and the the sec_desc */
1702
1703                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708
1709                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710                                    p->server_info->ptok, snum) ||
1711                     !print_access_check(p->server_info, snum,
1712                                         r->in.access_mask)) {
1713                         DEBUG(3, ("access DENIED for printer open\n"));
1714                         close_printer_handle(p, r->out.handle);
1715                         ZERO_STRUCTP(r->out.handle);
1716                         return WERR_ACCESS_DENIED;
1717                 }
1718
1719                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721                         close_printer_handle(p, r->out.handle);
1722                         ZERO_STRUCTP(r->out.handle);
1723                         return WERR_ACCESS_DENIED;
1724                 }
1725
1726                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1728                 else
1729                         r->in.access_mask = PRINTER_ACCESS_USE;
1730
1731                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1733
1734                 break;
1735
1736         default:
1737                 /* sanity check to prevent programmer error */
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_BADFID;
1740         }
1741
1742         Printer->access_granted = r->in.access_mask;
1743
1744         /*
1745          * If the client sent a devmode in the OpenPrinter() call, then
1746          * save it here in case we get a job submission on this handle
1747          */
1748
1749          if ((Printer->printer_type != SPLHND_SERVER) &&
1750              r->in.devmode_ctr.devmode) {
1751                 convert_devicemode(Printer->sharename,
1752                                    r->in.devmode_ctr.devmode,
1753                                    &Printer->nt_devmode);
1754          }
1755
1756 #if 0   /* JERRY -- I'm doubtful this is really effective */
1757         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758            optimization in Windows 2000 clients  --jerry */
1759
1760         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761                 && (RA_WIN2K == get_remote_arch()) )
1762         {
1763                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764                 sys_usleep( 500000 );
1765         }
1766 #endif
1767
1768         return WERR_OK;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775                                               NT_PRINTER_INFO_LEVEL_2 *d)
1776 {
1777         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1778
1779         if (!r || !d) {
1780                 return false;
1781         }
1782
1783         d->attributes           = r->attributes;
1784         d->priority             = r->priority;
1785         d->default_priority     = r->defaultpriority;
1786         d->starttime            = r->starttime;
1787         d->untiltime            = r->untiltime;
1788         d->status               = r->status;
1789         d->cjobs                = r->cjobs;
1790
1791         fstrcpy(d->servername,  r->servername);
1792         fstrcpy(d->printername, r->printername);
1793         fstrcpy(d->sharename,   r->sharename);
1794         fstrcpy(d->portname,    r->portname);
1795         fstrcpy(d->drivername,  r->drivername);
1796         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797         fstrcpy(d->location,    r->location);
1798         fstrcpy(d->sepfile,     r->sepfile);
1799         fstrcpy(d->printprocessor, r->printprocessor);
1800         fstrcpy(d->datatype,    r->datatype);
1801         fstrcpy(d->parameters,  r->parameters);
1802
1803         return true;
1804 }
1805
1806 /****************************************************************************
1807 ****************************************************************************/
1808
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810                                  NT_PRINTER_INFO_LEVEL *printer)
1811 {
1812         bool ret;
1813
1814         switch (info_ctr->level) {
1815         case 2:
1816                 /* allocate memory if needed.  Messy because
1817                    convert_printer_info is used to update an existing
1818                    printer or build a new one */
1819
1820                 if (!printer->info_2) {
1821                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822                         if (!printer->info_2) {
1823                                 DEBUG(0,("convert_printer_info: "
1824                                         "talloc() failed!\n"));
1825                                 return false;
1826                         }
1827                 }
1828
1829                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1830                                                         printer->info_2);
1831                 printer->info_2->setuptime = time(NULL);
1832                 return ret;
1833         }
1834
1835         return false;
1836 }
1837
1838 /****************************************************************
1839  _spoolss_ClosePrinter
1840 ****************************************************************/
1841
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843                              struct spoolss_ClosePrinter *r)
1844 {
1845         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1846
1847         if (Printer && Printer->document_started) {
1848                 struct spoolss_EndDocPrinter e;
1849
1850                 e.in.handle = r->in.handle;
1851
1852                 _spoolss_EndDocPrinter(p, &e);
1853         }
1854
1855         if (!close_printer_handle(p, r->in.handle))
1856                 return WERR_BADFID;
1857
1858         /* clear the returned printer handle.  Observed behavior
1859            from Win2k server.  Don't think this really matters.
1860            Previous code just copied the value of the closed
1861            handle.    --jerry */
1862
1863         ZERO_STRUCTP(r->out.handle);
1864
1865         return WERR_OK;
1866 }
1867
1868 /****************************************************************
1869  _spoolss_DeletePrinter
1870 ****************************************************************/
1871
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873                               struct spoolss_DeletePrinter *r)
1874 {
1875         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1876         WERROR result;
1877
1878         if (Printer && Printer->document_started) {
1879                 struct spoolss_EndDocPrinter e;
1880
1881                 e.in.handle = r->in.handle;
1882
1883                 _spoolss_EndDocPrinter(p, &e);
1884         }
1885
1886         result = delete_printer_handle(p, r->in.handle);
1887
1888         update_c_setprinter(false);
1889
1890         return result;
1891 }
1892
1893 /*******************************************************************
1894  * static function to lookup the version id corresponding to an
1895  * long architecture string
1896  ******************************************************************/
1897
1898 static const struct print_architecture_table_node archi_table[]= {
1899
1900         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1901         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1902         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1903         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1904         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1905         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1906         {"Windows x64",          SPL_ARCH_X64,          3 },
1907         {NULL,                   "",            -1 }
1908 };
1909
1910 static int get_version_id(const char *arch)
1911 {
1912         int i;
1913
1914         for (i=0; archi_table[i].long_archi != NULL; i++)
1915         {
1916                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917                         return (archi_table[i].version);
1918         }
1919
1920         return -1;
1921 }
1922
1923 /****************************************************************
1924  _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1926
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928                                     struct spoolss_DeletePrinterDriver *r)
1929 {
1930
1931         union spoolss_DriverInfo *info = NULL;
1932         union spoolss_DriverInfo *info_win2k = NULL;
1933         int                             version;
1934         WERROR                          status;
1935         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1936         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1937
1938         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1939            and not a printer admin, then fail */
1940
1941         if ( (p->server_info->utok.uid != sec_initial_uid())
1942                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1943                 && !token_contains_name_in_list(
1944                         uidtoname(p->server_info->utok.uid), NULL,
1945                         NULL, p->server_info->ptok,
1946                         lp_printer_admin(-1)) )
1947         {
1948                 return WERR_ACCESS_DENIED;
1949         }
1950
1951         /* check that we have a valid driver name first */
1952
1953         if ((version = get_version_id(r->in.architecture)) == -1)
1954                 return WERR_INVALID_ENVIRONMENT;
1955
1956         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
1957                                                 r->in.architecture,
1958                                                 version)))
1959         {
1960                 /* try for Win2k driver if "Windows NT x86" */
1961
1962                 if ( version == 2 ) {
1963                         version = 3;
1964                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1965                                                                 &info, 3,
1966                                                                 r->in.driver,
1967                                                                 r->in.architecture,
1968                                                                 version))) {
1969                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970                                 goto done;
1971                         }
1972                 }
1973                 /* otherwise it was a failure */
1974                 else {
1975                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1976                         goto done;
1977                 }
1978
1979         }
1980
1981         if (printer_driver_in_use(&info->info3)) {
1982                 status = WERR_PRINTER_DRIVER_IN_USE;
1983                 goto done;
1984         }
1985
1986         if ( version == 2 )
1987         {
1988                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1989                                                        &info_win2k, 3,
1990                                                        r->in.driver,
1991                                                        r->in.architecture, 3)))
1992                 {
1993                         /* if we get to here, we now have 2 driver info structures to remove */
1994                         /* remove the Win2k driver first*/
1995
1996                         status_win2k = delete_printer_driver(
1997                                 p, &info_win2k->info3, 3, false);
1998                         free_a_printer_driver(info_win2k);
1999
2000                         /* this should not have failed---if it did, report to client */
2001                         if ( !W_ERROR_IS_OK(status_win2k) )
2002                         {
2003                                 status = status_win2k;
2004                                 goto done;
2005                         }
2006                 }
2007         }
2008
2009         status = delete_printer_driver(p, &info->info3, version, false);
2010
2011         /* if at least one of the deletes succeeded return OK */
2012
2013         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2014                 status = WERR_OK;
2015
2016 done:
2017         free_a_printer_driver(info);
2018
2019         return status;
2020 }
2021
2022 /****************************************************************
2023  _spoolss_DeletePrinterDriverEx
2024 ****************************************************************/
2025
2026 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2027                                       struct spoolss_DeletePrinterDriverEx *r)
2028 {
2029         union spoolss_DriverInfo        *info = NULL;
2030         union spoolss_DriverInfo        *info_win2k = NULL;
2031         int                             version;
2032         bool                            delete_files;
2033         WERROR                          status;
2034         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2035         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2036
2037         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038            and not a printer admin, then fail */
2039
2040         if ( (p->server_info->utok.uid != sec_initial_uid())
2041                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2042                 && !token_contains_name_in_list(
2043                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2044                         p->server_info->ptok, lp_printer_admin(-1)) )
2045         {
2046                 return WERR_ACCESS_DENIED;
2047         }
2048
2049         /* check that we have a valid driver name first */
2050         if ((version = get_version_id(r->in.architecture)) == -1) {
2051                 /* this is what NT returns */
2052                 return WERR_INVALID_ENVIRONMENT;
2053         }
2054
2055         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2056                 version = r->in.version;
2057
2058         status = get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
2059                                       r->in.architecture, version);
2060
2061         if ( !W_ERROR_IS_OK(status) )
2062         {
2063                 /*
2064                  * if the client asked for a specific version,
2065                  * or this is something other than Windows NT x86,
2066                  * then we've failed
2067                  */
2068
2069                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2070                         goto done;
2071
2072                 /* try for Win2k driver if "Windows NT x86" */
2073
2074                 version = 3;
2075                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
2076                                                         r->in.architecture,
2077                                                         version))) {
2078                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2079                         goto done;
2080                 }
2081         }
2082
2083         if ( printer_driver_in_use(&info->info3) ) {
2084                 status = WERR_PRINTER_DRIVER_IN_USE;
2085                 goto done;
2086         }
2087
2088         /*
2089          * we have a couple of cases to consider.
2090          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2091          *     then the delete should fail if **any** files overlap with
2092          *     other drivers
2093          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094          *     non-overlapping files
2095          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096          *     is set, the do not delete any files
2097          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2098          */
2099
2100         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2101
2102         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2103
2104         if ( delete_files && printer_driver_files_in_use(info, &info->info3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2105                 /* no idea of the correct error here */
2106                 status = WERR_ACCESS_DENIED;
2107                 goto done;
2108         }
2109
2110
2111         /* also check for W32X86/3 if necessary; maybe we already have? */
2112
2113         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2114                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k, 3,
2115                                                        r->in.driver,
2116                                                        r->in.architecture, 3)))
2117                 {
2118
2119                         if ( delete_files && printer_driver_files_in_use(info, &info_win2k->info3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2120                                 /* no idea of the correct error here */
2121                                 free_a_printer_driver(info_win2k);
2122                                 status = WERR_ACCESS_DENIED;
2123                                 goto done;
2124                         }
2125
2126                         /* if we get to here, we now have 2 driver info structures to remove */
2127                         /* remove the Win2k driver first*/
2128
2129                         status_win2k = delete_printer_driver(
2130                                 p, &info_win2k->info3, 3, delete_files);
2131                         free_a_printer_driver(info_win2k);
2132
2133                         /* this should not have failed---if it did, report to client */
2134
2135                         if ( !W_ERROR_IS_OK(status_win2k) )
2136                                 goto done;
2137                 }
2138         }
2139
2140         status = delete_printer_driver(p, &info->info3, version, delete_files);
2141
2142         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2143                 status = WERR_OK;
2144 done:
2145         free_a_printer_driver(info);
2146
2147         return status;
2148 }
2149
2150
2151 /****************************************************************************
2152  Internal routine for removing printerdata
2153  ***************************************************************************/
2154
2155 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2156 {
2157         return delete_printer_data( printer->info_2, key, value );
2158 }
2159
2160 /****************************************************************************
2161  Internal routine for storing printerdata
2162  ***************************************************************************/
2163
2164 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2165                           const char *key, const char *value,
2166                           uint32_t type, uint8_t *data, int real_len)
2167 {
2168         /* the registry objects enforce uniqueness based on value name */
2169
2170         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2171 }
2172
2173 /********************************************************************
2174  GetPrinterData on a printer server Handle.
2175 ********************************************************************/
2176
2177 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2178                                             const char *value,
2179                                             enum winreg_Type *type,
2180                                             union spoolss_PrinterData *data)
2181 {
2182         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2183
2184         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2185                 *type = REG_DWORD;
2186                 data->value = 0x00;
2187                 return WERR_OK;
2188         }
2189
2190         if (!StrCaseCmp(value, "BeepEnabled")) {
2191                 *type = REG_DWORD;
2192                 data->value = 0x00;
2193                 return WERR_OK;
2194         }
2195
2196         if (!StrCaseCmp(value, "EventLog")) {
2197                 *type = REG_DWORD;
2198                 /* formally was 0x1b */
2199                 data->value = 0x00;
2200                 return WERR_OK;
2201         }
2202
2203         if (!StrCaseCmp(value, "NetPopup")) {
2204                 *type = REG_DWORD;
2205                 data->value = 0x00;
2206                 return WERR_OK;
2207         }
2208
2209         if (!StrCaseCmp(value, "MajorVersion")) {
2210                 *type = REG_DWORD;
2211
2212                 /* Windows NT 4.0 seems to not allow uploading of drivers
2213                    to a server that reports 0x3 as the MajorVersion.
2214                    need to investigate more how Win2k gets around this .
2215                    -- jerry */
2216
2217                 if (RA_WINNT == get_remote_arch()) {
2218                         data->value = 0x02;
2219                 } else {
2220                         data->value = 0x03;
2221                 }
2222
2223                 return WERR_OK;
2224         }
2225
2226         if (!StrCaseCmp(value, "MinorVersion")) {
2227                 *type = REG_DWORD;
2228                 data->value = 0x00;
2229                 return WERR_OK;
2230         }
2231
2232         /* REG_BINARY
2233          *  uint32_t size        = 0x114
2234          *  uint32_t major       = 5
2235          *  uint32_t minor       = [0|1]
2236          *  uint32_t build       = [2195|2600]
2237          *  extra unicode string = e.g. "Service Pack 3"
2238          */
2239         if (!StrCaseCmp(value, "OSVersion")) {
2240                 DATA_BLOB blob;
2241                 enum ndr_err_code ndr_err;
2242                 struct spoolss_OSVersion os;
2243
2244                 os.major                = 5;    /* Windows 2000 == 5.0 */
2245                 os.minor                = 0;
2246                 os.build                = 2195; /* build */
2247                 os.extra_string         = "";   /* leave extra string empty */
2248
2249                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2250                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2251                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2252                         return WERR_GENERAL_FAILURE;
2253                 }
2254
2255                 *type = REG_BINARY;
2256                 data->binary = blob;
2257
2258                 return WERR_OK;
2259         }
2260
2261
2262         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2263                 *type = REG_SZ;
2264
2265                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2266                 W_ERROR_HAVE_NO_MEMORY(data->string);
2267
2268                 return WERR_OK;
2269         }
2270
2271         if (!StrCaseCmp(value, "Architecture")) {
2272                 *type = REG_SZ;
2273
2274                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2275                 W_ERROR_HAVE_NO_MEMORY(data->string);
2276
2277                 return WERR_OK;
2278         }
2279
2280         if (!StrCaseCmp(value, "DsPresent")) {
2281                 *type = REG_DWORD;
2282
2283                 /* only show the publish check box if we are a
2284                    member of a AD domain */
2285
2286                 if (lp_security() == SEC_ADS) {
2287                         data->value = 0x01;
2288                 } else {
2289                         data->value = 0x00;
2290                 }
2291                 return WERR_OK;
2292         }
2293
2294         if (!StrCaseCmp(value, "DNSMachineName")) {
2295                 const char *hostname = get_mydnsfullname();
2296
2297                 if (!hostname) {
2298                         return WERR_BADFILE;
2299                 }
2300
2301                 *type = REG_SZ;
2302                 data->string = talloc_strdup(mem_ctx, hostname);
2303                 W_ERROR_HAVE_NO_MEMORY(data->string);
2304
2305                 return WERR_OK;
2306         }
2307
2308         *type = REG_NONE;
2309
2310         return WERR_INVALID_PARAM;
2311 }
2312
2313 /****************************************************************
2314  _spoolss_GetPrinterData
2315 ****************************************************************/
2316
2317 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2318                                struct spoolss_GetPrinterData *r)
2319 {
2320         struct spoolss_GetPrinterDataEx r2;
2321
2322         r2.in.handle            = r->in.handle;
2323         r2.in.key_name          = "PrinterDriverData";
2324         r2.in.value_name        = r->in.value_name;
2325         r2.in.offered           = r->in.offered;
2326         r2.out.type             = r->out.type;
2327         r2.out.data             = r->out.data;
2328         r2.out.needed           = r->out.needed;
2329
2330         return _spoolss_GetPrinterDataEx(p, &r2);
2331 }
2332
2333 /*********************************************************
2334  Connect to the client machine.
2335 **********************************************************/
2336
2337 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2338                         struct sockaddr_storage *client_ss, const char *remote_machine)
2339 {
2340         NTSTATUS ret;
2341         struct cli_state *the_cli;
2342         struct sockaddr_storage rm_addr;
2343
2344         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2345                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2346                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2347                         return false;
2348                 }
2349
2350                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2351                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2352                         return false;
2353                 }
2354         } else {
2355                 char addr[INET6_ADDRSTRLEN];
2356                 rm_addr = *client_ss;
2357                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2358                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2359                         addr));
2360         }
2361
2362         /* setup the connection */
2363
2364         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2365                 &rm_addr, 0, "IPC$", "IPC",
2366                 "", /* username */
2367                 "", /* domain */
2368                 "", /* password */
2369                 0, lp_client_signing(), NULL );
2370
2371         if ( !NT_STATUS_IS_OK( ret ) ) {
2372                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2373                         remote_machine ));
2374                 return false;
2375         }
2376
2377         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2378                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2379                 cli_shutdown(the_cli);
2380                 return false;
2381         }
2382
2383         /*
2384          * Ok - we have an anonymous connection to the IPC$ share.
2385          * Now start the NT Domain stuff :-).
2386          */
2387
2388         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2389         if (!NT_STATUS_IS_OK(ret)) {
2390                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2391                         remote_machine, nt_errstr(ret)));
2392                 cli_shutdown(the_cli);
2393                 return false;
2394         }
2395
2396         return true;
2397 }
2398
2399 /***************************************************************************
2400  Connect to the client.
2401 ****************************************************************************/
2402
2403 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2404                                         uint32_t localprinter, uint32_t type,
2405                                         struct policy_handle *handle,
2406                                         struct sockaddr_storage *client_ss)
2407 {
2408         WERROR result;
2409         NTSTATUS status;
2410
2411         /*
2412          * If it's the first connection, contact the client
2413          * and connect to the IPC$ share anonymously
2414          */
2415         if (smb_connections==0) {
2416                 fstring unix_printer;
2417
2418                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2419
2420                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2421                         return false;
2422
2423                 messaging_register(smbd_messaging_context(), NULL,
2424                                    MSG_PRINTER_NOTIFY2,
2425                                    receive_notify2_message_list);
2426                 /* Tell the connections db we're now interested in printer
2427                  * notify messages. */
2428                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2429         }
2430
2431         /*
2432          * Tell the specific printing tdb we want messages for this printer
2433          * by registering our PID.
2434          */
2435
2436         if (!print_notify_register_pid(snum))
2437                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2438
2439         smb_connections++;
2440
2441         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2442                                                  printer,
2443                                                  localprinter,
2444                                                  type,
2445                                                  0,
2446                                                  NULL,
2447                                                  handle,
2448                                                  &result);
2449         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2450                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2451                         win_errstr(result)));
2452
2453         return (W_ERROR_IS_OK(result));
2454 }
2455
2456 /****************************************************************
2457  ****************************************************************/
2458
2459 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2460                                                              const struct spoolss_NotifyOption *r)
2461 {
2462         struct spoolss_NotifyOption *option;
2463         uint32_t i,k;
2464
2465         if (!r) {
2466                 return NULL;
2467         }
2468
2469         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2470         if (!option) {
2471                 return NULL;
2472         }
2473
2474         *option = *r;
2475
2476         if (!option->count) {
2477                 return option;
2478         }
2479
2480         option->types = talloc_zero_array(option,
2481                 struct spoolss_NotifyOptionType, option->count);
2482         if (!option->types) {
2483                 talloc_free(option);
2484                 return NULL;
2485         }
2486
2487         for (i=0; i < option->count; i++) {
2488                 option->types[i] = r->types[i];
2489
2490                 if (option->types[i].count) {
2491                         option->types[i].fields = talloc_zero_array(option,
2492                                 union spoolss_Field, option->types[i].count);
2493                         if (!option->types[i].fields) {
2494                                 talloc_free(option);
2495                                 return NULL;
2496                         }
2497                         for (k=0; k<option->types[i].count; k++) {
2498                                 option->types[i].fields[k] =
2499                                         r->types[i].fields[k];
2500                         }
2501                 }
2502         }
2503
2504         return option;
2505 }
2506
2507 /****************************************************************
2508  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2509  *
2510  * before replying OK: status=0 a rpc call is made to the workstation
2511  * asking ReplyOpenPrinter
2512  *
2513  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2514  * called from api_spoolss_rffpcnex
2515 ****************************************************************/
2516
2517 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2518                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2519 {
2520         int snum = -1;
2521         struct spoolss_NotifyOption *option = r->in.notify_options;
2522         struct sockaddr_storage client_ss;
2523
2524         /* store the notify value in the printer struct */
2525
2526         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2527
2528         if (!Printer) {
2529                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2530                         "Invalid handle (%s:%u:%u).\n",
2531                         OUR_HANDLE(r->in.handle)));
2532                 return WERR_BADFID;
2533         }
2534
2535         Printer->notify.flags           = r->in.flags;
2536         Printer->notify.options         = r->in.options;
2537         Printer->notify.printerlocal    = r->in.printer_local;
2538
2539         TALLOC_FREE(Printer->notify.option);
2540         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2541
2542         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2543
2544         /* Connect to the client machine and send a ReplyOpenPrinter */
2545
2546         if ( Printer->printer_type == SPLHND_SERVER)
2547                 snum = -1;
2548         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2549                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2550                 return WERR_BADFID;
2551
2552         if (!interpret_string_addr(&client_ss, p->client_address,
2553                                    AI_NUMERICHOST)) {
2554                 return WERR_SERVER_UNAVAILABLE;
2555         }
2556
2557         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2558                                         Printer->notify.printerlocal, 1,
2559                                         &Printer->notify.client_hnd, &client_ss))
2560                 return WERR_SERVER_UNAVAILABLE;
2561
2562         Printer->notify.client_connected = true;
2563
2564         return WERR_OK;
2565 }
2566
2567 /*******************************************************************
2568  * fill a notify_info_data with the servername
2569  ********************************************************************/
2570
2571 void spoolss_notify_server_name(int snum,
2572                                        struct spoolss_Notify *data,
2573                                        print_queue_struct *queue,
2574                                        NT_PRINTER_INFO_LEVEL *printer,
2575                                        TALLOC_CTX *mem_ctx)
2576 {
2577         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2578 }
2579
2580 /*******************************************************************
2581  * fill a notify_info_data with the printername (not including the servername).
2582  ********************************************************************/
2583
2584 void spoolss_notify_printer_name(int snum,
2585                                         struct spoolss_Notify *data,
2586                                         print_queue_struct *queue,
2587                                         NT_PRINTER_INFO_LEVEL *printer,
2588                                         TALLOC_CTX *mem_ctx)
2589 {
2590         /* the notify name should not contain the \\server\ part */
2591         char *p = strrchr(printer->info_2->printername, '\\');
2592
2593         if (!p) {
2594                 p = printer->info_2->printername;
2595         } else {
2596                 p++;
2597         }
2598
2599         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2600 }
2601
2602 /*******************************************************************
2603  * fill a notify_info_data with the servicename
2604  ********************************************************************/
2605
2606 void spoolss_notify_share_name(int snum,
2607                                       struct spoolss_Notify *data,
2608                                       print_queue_struct *queue,
2609                                       NT_PRINTER_INFO_LEVEL *printer,
2610                                       TALLOC_CTX *mem_ctx)
2611 {
2612         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2613 }
2614
2615 /*******************************************************************
2616  * fill a notify_info_data with the port name
2617  ********************************************************************/
2618
2619 void spoolss_notify_port_name(int snum,
2620                                      struct spoolss_Notify *data,
2621                                      print_queue_struct *queue,
2622                                      NT_PRINTER_INFO_LEVEL *printer,
2623                                      TALLOC_CTX *mem_ctx)
2624 {
2625         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2626 }
2627
2628 /*******************************************************************
2629  * fill a notify_info_data with the printername
2630  * but it doesn't exist, have to see what to do
2631  ********************************************************************/
2632
2633 void spoolss_notify_driver_name(int snum,
2634                                        struct spoolss_Notify *data,
2635                                        print_queue_struct *queue,
2636                                        NT_PRINTER_INFO_LEVEL *printer,
2637                                        TALLOC_CTX *mem_ctx)
2638 {
2639         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2640 }
2641
2642 /*******************************************************************
2643  * fill a notify_info_data with the comment
2644  ********************************************************************/
2645
2646 void spoolss_notify_comment(int snum,
2647                                    struct spoolss_Notify *data,
2648                                    print_queue_struct *queue,
2649                                    NT_PRINTER_INFO_LEVEL *printer,
2650                                    TALLOC_CTX *mem_ctx)
2651 {
2652         char *p;
2653
2654         if (*printer->info_2->comment == '\0') {
2655                 p = lp_comment(snum);
2656         } else {
2657                 p = printer->info_2->comment;
2658         }
2659
2660         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2661 }
2662
2663 /*******************************************************************
2664  * fill a notify_info_data with the comment
2665  * location = "Room 1, floor 2, building 3"
2666  ********************************************************************/
2667
2668 void spoolss_notify_location(int snum,
2669                                     struct spoolss_Notify *data,
2670                                     print_queue_struct *queue,
2671                                     NT_PRINTER_INFO_LEVEL *printer,
2672                                     TALLOC_CTX *mem_ctx)
2673 {
2674         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2675 }
2676
2677 /*******************************************************************
2678  * fill a notify_info_data with the device mode
2679  * jfm:xxxx don't to it for know but that's a real problem !!!
2680  ********************************************************************/
2681
2682 static void spoolss_notify_devmode(int snum,
2683                                    struct spoolss_Notify *data,
2684                                    print_queue_struct *queue,
2685                                    NT_PRINTER_INFO_LEVEL *printer,
2686                                    TALLOC_CTX *mem_ctx)
2687 {
2688         /* for a dummy implementation we have to zero the fields */
2689         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2690 }
2691
2692 /*******************************************************************
2693  * fill a notify_info_data with the separator file name
2694  ********************************************************************/
2695
2696 void spoolss_notify_sepfile(int snum,
2697                                    struct spoolss_Notify *data,
2698                                    print_queue_struct *queue,
2699                                    NT_PRINTER_INFO_LEVEL *printer,
2700                                    TALLOC_CTX *mem_ctx)
2701 {
2702         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2703 }
2704
2705 /*******************************************************************
2706  * fill a notify_info_data with the print processor
2707  * jfm:xxxx return always winprint to indicate we don't do anything to it
2708  ********************************************************************/
2709
2710 void spoolss_notify_print_processor(int snum,
2711                                            struct spoolss_Notify *data,
2712                                            print_queue_struct *queue,
2713                                            NT_PRINTER_INFO_LEVEL *printer,
2714                                            TALLOC_CTX *mem_ctx)
2715 {
2716         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2717 }
2718
2719 /*******************************************************************
2720  * fill a notify_info_data with the print processor options
2721  * jfm:xxxx send an empty string
2722  ********************************************************************/
2723
2724 void spoolss_notify_parameters(int snum,
2725                                       struct spoolss_Notify *data,
2726                                       print_queue_struct *queue,
2727                                       NT_PRINTER_INFO_LEVEL *printer,
2728                                       TALLOC_CTX *mem_ctx)
2729 {
2730         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2731 }
2732
2733 /*******************************************************************
2734  * fill a notify_info_data with the data type
2735  * jfm:xxxx always send RAW as data type
2736  ********************************************************************/
2737
2738 void spoolss_notify_datatype(int snum,
2739                                     struct spoolss_Notify *data,
2740                                     print_queue_struct *queue,
2741                                     NT_PRINTER_INFO_LEVEL *printer,
2742                                     TALLOC_CTX *mem_ctx)
2743 {
2744         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2745 }
2746
2747 /*******************************************************************
2748  * fill a notify_info_data with the security descriptor
2749  * jfm:xxxx send an null pointer to say no security desc
2750  * have to implement security before !
2751  ********************************************************************/
2752
2753 static void spoolss_notify_security_desc(int snum,
2754                                          struct spoolss_Notify *data,
2755                                          print_queue_struct *queue,
2756                                          NT_PRINTER_INFO_LEVEL *printer,
2757                                          TALLOC_CTX *mem_ctx)
2758 {
2759         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2760                                           printer->info_2->secdesc_buf->sd_size,
2761                                           printer->info_2->secdesc_buf->sd);
2762 }
2763
2764 /*******************************************************************
2765  * fill a notify_info_data with the attributes
2766  * jfm:xxxx a samba printer is always shared
2767  ********************************************************************/
2768
2769 void spoolss_notify_attributes(int snum,
2770                                       struct spoolss_Notify *data,
2771                                       print_queue_struct *queue,
2772                                       NT_PRINTER_INFO_LEVEL *printer,
2773                                       TALLOC_CTX *mem_ctx)
2774 {
2775         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2776 }
2777
2778 /*******************************************************************
2779  * fill a notify_info_data with the priority
2780  ********************************************************************/
2781
2782 static void spoolss_notify_priority(int snum,
2783                                     struct spoolss_Notify *data,
2784                                     print_queue_struct *queue,
2785                                     NT_PRINTER_INFO_LEVEL *printer,
2786                                     TALLOC_CTX *mem_ctx)
2787 {
2788         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the default priority
2793  ********************************************************************/
2794
2795 static void spoolss_notify_default_priority(int snum,
2796                                             struct spoolss_Notify *data,
2797                                             print_queue_struct *queue,
2798                                             NT_PRINTER_INFO_LEVEL *printer,
2799                                             TALLOC_CTX *mem_ctx)
2800 {
2801         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2802 }
2803
2804 /*******************************************************************
2805  * fill a notify_info_data with the start time
2806  ********************************************************************/
2807
2808 static void spoolss_notify_start_time(int snum,
2809                                       struct spoolss_Notify *data,
2810                                       print_queue_struct *queue,
2811                                       NT_PRINTER_INFO_LEVEL *printer,
2812                                       TALLOC_CTX *mem_ctx)
2813 {
2814         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the until time
2819  ********************************************************************/
2820
2821 static void spoolss_notify_until_time(int snum,
2822                                       struct spoolss_Notify *data,
2823                                       print_queue_struct *queue,
2824                                       NT_PRINTER_INFO_LEVEL *printer,
2825                                       TALLOC_CTX *mem_ctx)
2826 {
2827         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2828 }
2829
2830 /*******************************************************************
2831  * fill a notify_info_data with the status
2832  ********************************************************************/
2833
2834 static void spoolss_notify_status(int snum,
2835                                   struct spoolss_Notify *data,
2836                                   print_queue_struct *queue,
2837                                   NT_PRINTER_INFO_LEVEL *printer,
2838                                   TALLOC_CTX *mem_ctx)
2839 {
2840         print_status_struct status;
2841
2842         print_queue_length(snum, &status);
2843         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the number of jobs queued
2848  ********************************************************************/
2849
2850 void spoolss_notify_cjobs(int snum,
2851                                  struct spoolss_Notify *data,
2852                                  print_queue_struct *queue,
2853                                  NT_PRINTER_INFO_LEVEL *printer,
2854                                  TALLOC_CTX *mem_ctx)
2855 {
2856         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2857 }
2858
2859 /*******************************************************************
2860  * fill a notify_info_data with the average ppm
2861  ********************************************************************/
2862
2863 static void spoolss_notify_average_ppm(int snum,
2864                                        struct spoolss_Notify *data,
2865                                        print_queue_struct *queue,
2866                                        NT_PRINTER_INFO_LEVEL *printer,
2867                                        TALLOC_CTX *mem_ctx)
2868 {
2869         /* always respond 8 pages per minutes */
2870         /* a little hard ! */
2871         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2872 }
2873
2874 /*******************************************************************
2875  * fill a notify_info_data with username
2876  ********************************************************************/
2877
2878 static void spoolss_notify_username(int snum,
2879                                     struct spoolss_Notify *data,
2880                                     print_queue_struct *queue,
2881                                     NT_PRINTER_INFO_LEVEL *printer,
2882                                     TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with job status
2889  ********************************************************************/
2890
2891 static void spoolss_notify_job_status(int snum,
2892                                       struct spoolss_Notify *data,
2893                                       print_queue_struct *queue,
2894                                       NT_PRINTER_INFO_LEVEL *printer,
2895                                       TALLOC_CTX *mem_ctx)
2896 {
2897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2898 }
2899
2900 /*******************************************************************
2901  * fill a notify_info_data with job name
2902  ********************************************************************/
2903
2904 static void spoolss_notify_job_name(int snum,
2905                                     struct spoolss_Notify *data,
2906                                     print_queue_struct *queue,
2907                                     NT_PRINTER_INFO_LEVEL *printer,
2908                                     TALLOC_CTX *mem_ctx)
2909 {
2910         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2911 }
2912
2913 /*******************************************************************
2914  * fill a notify_info_data with job status
2915  ********************************************************************/
2916
2917 static void spoolss_notify_job_status_string(int snum,
2918                                              struct spoolss_Notify *data,
2919                                              print_queue_struct *queue,
2920                                              NT_PRINTER_INFO_LEVEL *printer,
2921                                              TALLOC_CTX *mem_ctx)
2922 {
2923         /*
2924          * Now we're returning job status codes we just return a "" here. JRA.
2925          */
2926
2927         const char *p = "";
2928
2929 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2930         p = "unknown";
2931
2932         switch (queue->status) {
2933         case LPQ_QUEUED:
2934                 p = "Queued";
2935                 break;
2936         case LPQ_PAUSED:
2937                 p = "";    /* NT provides the paused string */
2938                 break;
2939         case LPQ_SPOOLING:
2940                 p = "Spooling";
2941                 break;
2942         case LPQ_PRINTING:
2943                 p = "Printing";
2944                 break;
2945         }
2946 #endif /* NO LONGER NEEDED. */
2947
2948         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2949 }
2950
2951 /*******************************************************************
2952  * fill a notify_info_data with job time
2953  ********************************************************************/
2954
2955 static void spoolss_notify_job_time(int snum,
2956                                     struct spoolss_Notify *data,
2957                                     print_queue_struct *queue,
2958                                     NT_PRINTER_INFO_LEVEL *printer,
2959                                     TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with job size
2966  ********************************************************************/
2967
2968 static void spoolss_notify_job_size(int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     NT_PRINTER_INFO_LEVEL *printer,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with page info
2979  ********************************************************************/
2980 static void spoolss_notify_total_pages(int snum,
2981                                 struct spoolss_Notify *data,
2982                                 print_queue_struct *queue,
2983                                 NT_PRINTER_INFO_LEVEL *printer,
2984                                 TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with pages printed info.
2991  ********************************************************************/
2992 static void spoolss_notify_pages_printed(int snum,
2993                                 struct spoolss_Notify *data,
2994                                 print_queue_struct *queue,
2995                                 NT_PRINTER_INFO_LEVEL *printer,
2996                                 TALLOC_CTX *mem_ctx)
2997 {
2998         /* Add code when back-end tracks this */
2999         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3000 }
3001
3002 /*******************************************************************
3003  Fill a notify_info_data with job position.
3004  ********************************************************************/
3005
3006 static void spoolss_notify_job_position(int snum,
3007                                         struct spoolss_Notify *data,
3008                                         print_queue_struct *queue,
3009                                         NT_PRINTER_INFO_LEVEL *printer,
3010                                         TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3013 }
3014
3015 /*******************************************************************
3016  Fill a notify_info_data with submitted time.
3017  ********************************************************************/
3018
3019 static void spoolss_notify_submitted_time(int snum,
3020                                           struct spoolss_Notify *data,
3021                                           print_queue_struct *queue,
3022                                           NT_PRINTER_INFO_LEVEL *printer,
3023                                           TALLOC_CTX *mem_ctx)
3024 {
3025         data->data.string.string = NULL;
3026         data->data.string.size = 0;
3027
3028         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3029                                &data->data.string.string,
3030                                &data->data.string.size);
3031
3032 }
3033
3034 struct s_notify_info_data_table
3035 {
3036         enum spoolss_NotifyType type;
3037         uint16_t field;
3038         const char *name;
3039         enum spoolss_NotifyTable variable_type;
3040         void (*fn) (int snum, struct spoolss_Notify *data,
3041                     print_queue_struct *queue,
3042                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3043 };
3044
3045 /* A table describing the various print notification constants and
3046    whether the notification data is a pointer to a variable sized
3047    buffer, a one value uint32_t or a two value uint32_t. */
3048
3049 static const struct s_notify_info_data_table notify_info_data_table[] =
3050 {
3051 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3052 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3053 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3054 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3055 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3056 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3077 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3078 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3079 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3080 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3081 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3082 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3083 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3084 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3085 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3086 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3087 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3088 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3100 };
3101
3102 /*******************************************************************
3103  Return the variable_type of info_data structure.
3104 ********************************************************************/
3105
3106 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3107                                                   uint16_t field)
3108 {
3109         int i=0;
3110
3111         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3112                 if ( (notify_info_data_table[i].type == type) &&
3113                      (notify_info_data_table[i].field == field) ) {
3114                         return notify_info_data_table[i].variable_type;
3115                 }
3116         }
3117
3118         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3119
3120         return 0;
3121 }
3122
3123 /****************************************************************************
3124 ****************************************************************************/
3125
3126 static bool search_notify(enum spoolss_NotifyType type,
3127                           uint16_t field,
3128                           int *value)
3129 {
3130         int i;
3131
3132         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3133                 if (notify_info_data_table[i].type == type &&
3134                     notify_info_data_table[i].field == field &&
3135                     notify_info_data_table[i].fn != NULL) {
3136                         *value = i;
3137                         return true;
3138                 }
3139         }
3140
3141         return false;
3142 }
3143
3144 /****************************************************************************
3145 ****************************************************************************/
3146
3147 void construct_info_data(struct spoolss_Notify *info_data,
3148                          enum spoolss_NotifyType type,
3149                          uint16_t field,
3150                          int id)
3151 {
3152         info_data->type                 = type;
3153         info_data->field.field          = field;
3154         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3155         info_data->job_id               = id;
3156 }
3157
3158 /*******************************************************************
3159  *
3160  * fill a notify_info struct with info asked
3161  *
3162  ********************************************************************/
3163
3164 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3165                                           struct spoolss_NotifyInfo *info,
3166                                           int snum,
3167                                           const struct spoolss_NotifyOptionType *option_type,
3168                                           uint32_t id,
3169                                           TALLOC_CTX *mem_ctx)
3170 {
3171         int field_num,j;
3172         enum spoolss_NotifyType type;
3173         uint16_t field;
3174
3175         struct spoolss_Notify *current_data;
3176         NT_PRINTER_INFO_LEVEL *printer = NULL;
3177         print_queue_struct *queue=NULL;
3178
3179         type = option_type->type;
3180
3181         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3182                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3183                 option_type->count, lp_servicename(snum)));
3184
3185         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3186                 return false;
3187
3188         for(field_num=0; field_num < option_type->count; field_num++) {
3189                 field = option_type->fields[field_num].field;
3190
3191                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3192
3193                 if (!search_notify(type, field, &j) )
3194                         continue;
3195
3196                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3197                                                       struct spoolss_Notify,
3198                                                       info->count + 1);
3199                 if (info->notifies == NULL) {
3200                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3201                         free_a_printer(&printer, 2);
3202                         return false;
3203                 }
3204
3205                 current_data = &info->notifies[info->count];
3206
3207                 construct_info_data(current_data, type, field, id);
3208
3209                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3210                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3211
3212                 notify_info_data_table[j].fn(snum, current_data, queue,
3213                                              printer, mem_ctx);
3214
3215                 info->count++;
3216         }
3217
3218         free_a_printer(&printer, 2);
3219         return true;
3220 }
3221
3222 /*******************************************************************
3223  *
3224  * fill a notify_info struct with info asked
3225  *
3226  ********************************************************************/
3227
3228 static bool construct_notify_jobs_info(print_queue_struct *queue,
3229                                        struct spoolss_NotifyInfo *info,
3230                                        NT_PRINTER_INFO_LEVEL *printer,
3231                                        int snum,
3232                                        const struct spoolss_NotifyOptionType *option_type,
3233                                        uint32_t id,
3234                                        TALLOC_CTX *mem_ctx)
3235 {
3236         int field_num,j;
3237         enum spoolss_NotifyType type;
3238         uint16_t field;
3239         struct spoolss_Notify *current_data;
3240
3241         DEBUG(4,("construct_notify_jobs_info\n"));
3242
3243         type = option_type->type;
3244
3245         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3246                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3247                 option_type->count));
3248
3249         for(field_num=0; field_num<option_type->count; field_num++) {
3250                 field = option_type->fields[field_num].field;
3251
3252                 if (!search_notify(type, field, &j) )
3253                         continue;
3254
3255                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3256                                                       struct spoolss_Notify,
3257                                                       info->count + 1);
3258                 if (info->notifies == NULL) {
3259                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3260                         return false;
3261                 }
3262
3263                 current_data=&(info->notifies[info->count]);
3264
3265                 construct_info_data(current_data, type, field, id);
3266                 notify_info_data_table[j].fn(snum, current_data, queue,
3267                                              printer, mem_ctx);
3268                 info->count++;
3269         }
3270
3271         return true;
3272 }
3273
3274 /*
3275  * JFM: The enumeration is not that simple, it's even non obvious.
3276  *
3277  * let's take an example: I want to monitor the PRINTER SERVER for
3278  * the printer's name and the number of jobs currently queued.
3279  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3280  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3281  *
3282  * I have 3 printers on the back of my server.
3283  *
3284  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3285  * structures.
3286  *   Number     Data                    Id
3287  *      1       printer 1 name          1
3288  *      2       printer 1 cjob          1
3289  *      3       printer 2 name          2
3290  *      4       printer 2 cjob          2
3291  *      5       printer 3 name          3
3292  *      6       printer 3 name          3
3293  *
3294  * that's the print server case, the printer case is even worse.
3295  */
3296
3297 /*******************************************************************
3298  *
3299  * enumerate all printers on the printserver
3300  * fill a notify_info struct with info asked
3301  *
3302  ********************************************************************/
3303
3304 static WERROR printserver_notify_info(pipes_struct *p,
3305                                       struct policy_handle *hnd,
3306                                       struct spoolss_NotifyInfo *info,
3307                                       TALLOC_CTX *mem_ctx)
3308 {
3309         int snum;
3310         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3311         int n_services=lp_numservices();
3312         int i;
3313         struct spoolss_NotifyOption *option;
3314         struct spoolss_NotifyOptionType option_type;
3315
3316         DEBUG(4,("printserver_notify_info\n"));
3317
3318         if (!Printer)
3319                 return WERR_BADFID;
3320
3321         option = Printer->notify.option;
3322
3323         info->version   = 2;
3324         info->notifies  = NULL;
3325         info->count     = 0;
3326
3327         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3328            sending a ffpcn() request first */
3329
3330         if ( !option )
3331                 return WERR_BADFID;
3332
3333         for (i=0; i<option->count; i++) {
3334                 option_type = option->types[i];
3335
3336                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3337                         continue;
3338
3339                 for (snum=0; snum<n_services; snum++)
3340                 {
3341                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3342                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3343                 }
3344         }
3345
3346 #if 0
3347         /*
3348          * Debugging information, don't delete.
3349          */
3350
3351         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3352         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3353         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3354
3355         for (i=0; i<info->count; i++) {
3356                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3357                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3358                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3359         }
3360 #endif
3361
3362         return WERR_OK;
3363 }
3364
3365 /*******************************************************************
3366  *
3367  * fill a notify_info struct with info asked
3368  *
3369  ********************************************************************/
3370
3371 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3372                                   struct spoolss_NotifyInfo *info,
3373                                   TALLOC_CTX *mem_ctx)
3374 {
3375         int snum;
3376         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3377         int i;
3378         uint32_t id;
3379         struct spoolss_NotifyOption *option;
3380         struct spoolss_NotifyOptionType option_type;
3381         int count,j;
3382         print_queue_struct *queue=NULL;
3383         print_status_struct status;
3384
3385         DEBUG(4,("printer_notify_info\n"));
3386
3387         if (!Printer)
3388                 return WERR_BADFID;
3389
3390         option = Printer->notify.option;
3391         id = 0x0;
3392
3393         info->version   = 2;
3394         info->notifies  = NULL;
3395         info->count     = 0;
3396
3397         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3398            sending a ffpcn() request first */
3399
3400         if ( !option )
3401                 return WERR_BADFID;
3402
3403         get_printer_snum(p, hnd, &snum, NULL);
3404
3405         for (i=0; i<option->count; i++) {
3406                 option_type = option->types[i];
3407
3408                 switch (option_type.type) {
3409                 case PRINTER_NOTIFY_TYPE:
3410                         if(construct_notify_printer_info(Printer, info, snum,
3411                                                          &option_type, id,
3412                                                          mem_ctx))
3413                                 id--;
3414                         break;
3415
3416                 case JOB_NOTIFY_TYPE: {
3417                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3418
3419                         count = print_queue_status(snum, &queue, &status);
3420
3421                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3422                                 goto done;
3423
3424                         for (j=0; j<count; j++) {
3425                                 construct_notify_jobs_info(&queue[j], info,
3426                                                            printer, snum,
3427                                                            &option_type,
3428                                                            queue[j].job,
3429                                                            mem_ctx);
3430                         }
3431
3432                         free_a_printer(&printer, 2);
3433
3434                 done:
3435                         SAFE_FREE(queue);
3436                         break;
3437                 }
3438                 }
3439         }
3440
3441         /*
3442          * Debugging information, don't delete.
3443          */
3444         /*
3445         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3446         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3447         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3448
3449         for (i=0; i<info->count; i++) {
3450                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3451                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3452                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3453         }
3454         */
3455         return WERR_OK;
3456 }
3457
3458 /****************************************************************
3459  _spoolss_RouterRefreshPrinterChangeNotify
3460 ****************************************************************/
3461
3462 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3463                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3464 {
3465         struct spoolss_NotifyInfo *info;
3466
3467         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3468         WERROR result = WERR_BADFID;
3469
3470         /* we always have a spoolss_NotifyInfo struct */
3471         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3472         if (!info) {
3473                 result = WERR_NOMEM;
3474                 goto done;
3475         }
3476
3477         *r->out.info = info;
3478
3479         if (!Printer) {
3480                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3481                         "Invalid handle (%s:%u:%u).\n",
3482                         OUR_HANDLE(r->in.handle)));
3483                 goto done;
3484         }
3485
3486         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3487
3488         /*
3489          *      We are now using the change value, and
3490          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3491          *      I don't have a global notification system, I'm sending back all the
3492          *      informations even when _NOTHING_ has changed.
3493          */
3494
3495         /* We need to keep track of the change value to send back in
3496            RRPCN replies otherwise our updates are ignored. */
3497
3498         Printer->notify.fnpcn = true;
3499
3500         if (Printer->notify.client_connected) {
3501                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3502                         "Saving change value in request [%x]\n",
3503                         r->in.change_low));
3504                 Printer->notify.change = r->in.change_low;
3505         }
3506
3507         /* just ignore the spoolss_NotifyOption */
3508
3509         switch (Printer->printer_type) {
3510                 case SPLHND_SERVER:
3511                         result = printserver_notify_info(p, r->in.handle,
3512                                                          info, p->mem_ctx);
3513                         break;
3514
3515                 case SPLHND_PRINTER:
3516                         result = printer_notify_info(p, r->in.handle,
3517                                                      info, p->mem_ctx);
3518                         break;
3519         }
3520
3521         Printer->notify.fnpcn = false;
3522
3523 done:
3524         return result;
3525 }
3526
3527 /********************************************************************
3528  * construct_printer_info_0
3529  * fill a printer_info_0 struct
3530  ********************************************************************/
3531
3532 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3533                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3534                                       struct spoolss_PrinterInfo0 *r,
3535                                       int snum)
3536 {
3537         int count;
3538         counter_printer_0 *session_counter;
3539         time_t setuptime;
3540         print_status_struct status;
3541
3542         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3543         W_ERROR_HAVE_NO_MEMORY(r->printername);
3544
3545         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3546         W_ERROR_HAVE_NO_MEMORY(r->servername);
3547
3548         count = print_queue_length(snum, &status);
3549
3550         /* check if we already have a counter for this printer */
3551         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3552                 if (session_counter->snum == snum)
3553                         break;
3554         }
3555
3556         /* it's the first time, add it to the list */
3557         if (session_counter == NULL) {
3558                 session_counter = SMB_MALLOC_P(counter_printer_0);
3559                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3560                 ZERO_STRUCTP(session_counter);
3561                 session_counter->snum           = snum;
3562                 session_counter->counter        = 0;
3563                 DLIST_ADD(counter_list, session_counter);
3564         }
3565
3566         /* increment it */
3567         session_counter->counter++;
3568
3569         r->cjobs                        = count;
3570         r->total_jobs                   = 0;
3571         r->total_bytes                  = 0;
3572
3573         setuptime = (time_t)ntprinter->info_2->setuptime;
3574
3575         init_systemtime(&r->time, gmtime(&setuptime));
3576
3577         /* JFM:
3578          * the global_counter should be stored in a TDB as it's common to all the clients
3579          * and should be zeroed on samba startup
3580          */
3581         r->global_counter               = session_counter->counter;
3582         r->total_pages                  = 0;
3583         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3584         r->version                      = 0x0005;       /* NT 5 */
3585         r->free_build                   = 0x0893;       /* build 2195 */
3586         r->spooling                     = 0;
3587         r->max_spooling                 = 0;
3588         r->session_counter              = session_counter->counter;
3589         r->num_error_out_of_paper       = 0x0;
3590         r->num_error_not_ready          = 0x0;          /* number of print failure */
3591         r->job_error                    = 0x0;
3592         r->number_of_processors         = 0x1;
3593         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3594         r->high_part_total_bytes        = 0x0;
3595         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3596         r->last_error                   = WERR_OK;
3597         r->status                       = nt_printq_status(status.status);
3598         r->enumerate_network_printers   = 0x0;
3599         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3600         r->processor_architecture       = 0x0;
3601         r->processor_level              = 0x6;          /* 6  ???*/
3602         r->ref_ic                       = 0;
3603         r->reserved2                    = 0;
3604         r->reserved3                    = 0;
3605
3606         return WERR_OK;
3607 }
3608
3609 /****************************************************************************
3610  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3611  should be valid upon entry
3612 ****************************************************************************/
3613
3614 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3615                                     struct spoolss_DeviceMode *r,
3616                                     const NT_DEVICEMODE *ntdevmode)
3617 {
3618         if (!r || !ntdevmode) {
3619                 return WERR_INVALID_PARAM;
3620         }
3621
3622         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3623         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3624
3625         r->specversion          = ntdevmode->specversion;
3626         r->driverversion        = ntdevmode->driverversion;
3627         r->size                 = ntdevmode->size;
3628         r->__driverextra_length = ntdevmode->driverextra;
3629         r->fields               = ntdevmode->fields;
3630
3631         r->orientation          = ntdevmode->orientation;
3632         r->papersize            = ntdevmode->papersize;
3633         r->paperlength          = ntdevmode->paperlength;
3634         r->paperwidth           = ntdevmode->paperwidth;
3635         r->scale                = ntdevmode->scale;
3636         r->copies               = ntdevmode->copies;
3637         r->defaultsource        = ntdevmode->defaultsource;
3638         r->printquality         = ntdevmode->printquality;
3639         r->color                = ntdevmode->color;
3640         r->duplex               = ntdevmode->duplex;
3641         r->yresolution          = ntdevmode->yresolution;
3642         r->ttoption             = ntdevmode->ttoption;
3643         r->collate              = ntdevmode->collate;
3644
3645         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3646         W_ERROR_HAVE_NO_MEMORY(r->formname);
3647
3648         /* all 0 below are values that have not been set in the old parsing/copy
3649          * function, maybe they should... - gd */
3650
3651         r->logpixels            = 0;
3652         r->bitsperpel           = 0;
3653         r->pelswidth            = 0;
3654         r->pelsheight           = 0;
3655         r->displayflags         = 0;
3656         r->displayfrequency     = 0;
3657         r->icmmethod            = ntdevmode->icmmethod;
3658         r->icmintent            = ntdevmode->icmintent;
3659         r->mediatype            = ntdevmode->mediatype;
3660         r->dithertype           = ntdevmode->dithertype;
3661         r->reserved1            = 0;
3662         r->reserved2            = 0;
3663         r->panningwidth         = 0;
3664         r->panningheight        = 0;
3665
3666         if (ntdevmode->nt_dev_private != NULL) {
3667                 r->driverextra_data = data_blob_talloc(mem_ctx,
3668                         ntdevmode->nt_dev_private,
3669                         ntdevmode->driverextra);
3670                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3671         }
3672
3673         return WERR_OK;
3674 }
3675
3676
3677 /****************************************************************************
3678  Create a spoolss_DeviceMode struct. Returns talloced memory.
3679 ****************************************************************************/
3680
3681 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3682                                               const char *servicename)
3683 {
3684         WERROR result;
3685         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3686         struct spoolss_DeviceMode *devmode = NULL;
3687
3688         DEBUG(7,("construct_dev_mode\n"));
3689
3690         DEBUGADD(8,("getting printer characteristics\n"));
3691
3692         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3693                 return NULL;
3694
3695         if (!printer->info_2->devmode) {
3696                 DEBUG(5, ("BONG! There was no device mode!\n"));
3697                 goto done;
3698         }
3699
3700         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3701         if (!devmode) {
3702                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3703                 goto done;
3704         }
3705
3706         DEBUGADD(8,("loading DEVICEMODE\n"));
3707
3708         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3709         if (!W_ERROR_IS_OK(result)) {
3710                 TALLOC_FREE(devmode);
3711         }
3712
3713 done:
3714         free_a_printer(&printer,2);
3715
3716         return devmode;
3717 }
3718
3719 /********************************************************************
3720  * construct_printer_info1
3721  * fill a spoolss_PrinterInfo1 struct
3722 ********************************************************************/
3723
3724 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3725                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3726                                       uint32_t flags,
3727                                       struct spoolss_PrinterInfo1 *r,
3728                                       int snum)
3729 {
3730         r->flags                = flags;
3731
3732         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3733                                                   ntprinter->info_2->printername,
3734                                                   ntprinter->info_2->drivername,
3735                                                   ntprinter->info_2->location);
3736         W_ERROR_HAVE_NO_MEMORY(r->description);
3737
3738         if (*ntprinter->info_2->comment == '\0') {
3739                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3740         } else {
3741                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3742         }
3743         W_ERROR_HAVE_NO_MEMORY(r->comment);
3744
3745         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3746         W_ERROR_HAVE_NO_MEMORY(r->name);
3747
3748         return WERR_OK;
3749 }
3750
3751 /********************************************************************
3752  * construct_printer_info2
3753  * fill a spoolss_PrinterInfo2 struct
3754 ********************************************************************/
3755
3756 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3757                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3758                                       struct spoolss_PrinterInfo2 *r,
3759                                       int snum)
3760 {
3761         int count;
3762
3763         print_status_struct status;
3764
3765         count = print_queue_length(snum, &status);
3766
3767         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3768         W_ERROR_HAVE_NO_MEMORY(r->servername);
3769         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3770         W_ERROR_HAVE_NO_MEMORY(r->printername);
3771         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3772         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3773         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3774         W_ERROR_HAVE_NO_MEMORY(r->portname);
3775         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3776         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3777
3778         if (*ntprinter->info_2->comment == '\0') {
3779                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3780         } else {
3781                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3782         }
3783         W_ERROR_HAVE_NO_MEMORY(r->comment);
3784
3785         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3786         W_ERROR_HAVE_NO_MEMORY(r->location);
3787         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3788         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3789         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3790         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3791         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3792         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3793         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3794         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3795
3796         r->attributes           = ntprinter->info_2->attributes;
3797
3798         r->priority             = ntprinter->info_2->priority;
3799         r->defaultpriority      = ntprinter->info_2->default_priority;
3800         r->starttime            = ntprinter->info_2->starttime;
3801         r->untiltime            = ntprinter->info_2->untiltime;
3802         r->status               = nt_printq_status(status.status);
3803         r->cjobs                = count;
3804         r->averageppm           = ntprinter->info_2->averageppm;
3805
3806         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3807         if (!r->devmode) {
3808                 DEBUG(8,("Returning NULL Devicemode!\n"));
3809         }
3810
3811         r->secdesc              = NULL;
3812
3813         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3814                 /* don't use talloc_steal() here unless you do a deep steal of all
3815                    the SEC_DESC members */
3816
3817                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3818         }
3819
3820         return WERR_OK;
3821 }
3822
3823 /********************************************************************
3824  * construct_printer_info3
3825  * fill a spoolss_PrinterInfo3 struct
3826  ********************************************************************/
3827
3828 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3829                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3830                                       struct spoolss_PrinterInfo3 *r,
3831                                       int snum)
3832 {
3833         /* These are the components of the SD we are returning. */
3834
3835         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3836                 /* don't use talloc_steal() here unless you do a deep steal of all
3837                    the SEC_DESC members */
3838
3839                 r->secdesc = dup_sec_desc(mem_ctx,
3840                                           ntprinter->info_2->secdesc_buf->sd);
3841                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3842         }
3843
3844         return WERR_OK;
3845 }
3846
3847 /********************************************************************
3848  * construct_printer_info4
3849  * fill a spoolss_PrinterInfo4 struct
3850  ********************************************************************/
3851
3852 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3853                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3854                                       struct spoolss_PrinterInfo4 *r,
3855                                       int snum)
3856 {
3857         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3858         W_ERROR_HAVE_NO_MEMORY(r->printername);
3859         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3860         W_ERROR_HAVE_NO_MEMORY(r->servername);
3861
3862         r->attributes   = ntprinter->info_2->attributes;
3863
3864         return WERR_OK;
3865 }
3866
3867 /********************************************************************
3868  * construct_printer_info5
3869  * fill a spoolss_PrinterInfo5 struct
3870  ********************************************************************/
3871
3872 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3873                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3874                                       struct spoolss_PrinterInfo5 *r,
3875                                       int snum)
3876 {
3877         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3878         W_ERROR_HAVE_NO_MEMORY(r->printername);
3879         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3880         W_ERROR_HAVE_NO_MEMORY(r->portname);
3881
3882         r->attributes   = ntprinter->info_2->attributes;
3883
3884         /* these two are not used by NT+ according to MSDN */
3885
3886         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3887         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3888
3889         return WERR_OK;
3890 }
3891
3892 /********************************************************************
3893  * construct_printer_info_6
3894  * fill a spoolss_PrinterInfo6 struct
3895  ********************************************************************/
3896
3897 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3898                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3899                                       struct spoolss_PrinterInfo6 *r,
3900                                       int snum)
3901 {
3902         int count;
3903         print_status_struct status;
3904
3905         count = print_queue_length(snum, &status);
3906
3907         r->status = nt_printq_status(status.status);
3908
3909         return WERR_OK;
3910 }
3911
3912 /********************************************************************
3913  * construct_printer_info7
3914  * fill a spoolss_PrinterInfo7 struct
3915  ********************************************************************/
3916
3917 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3918                                       Printer_entry *print_hnd,
3919                                       struct spoolss_PrinterInfo7 *r,
3920                                       int snum)
3921 {
3922         struct GUID guid;
3923
3924         if (is_printer_published(print_hnd, snum, &guid)) {
3925                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3926                 r->action = DSPRINT_PUBLISH;
3927         } else {
3928                 r->guid = talloc_strdup(mem_ctx, "");
3929                 r->action = DSPRINT_UNPUBLISH;
3930         }
3931         W_ERROR_HAVE_NO_MEMORY(r->guid);
3932
3933         return WERR_OK;
3934 }
3935
3936 /********************************************************************
3937  * construct_printer_info8
3938  * fill a spoolss_PrinterInfo8 struct
3939  ********************************************************************/
3940
3941 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3942                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3943                                       struct spoolss_DeviceModeInfo *r,
3944                                       int snum)
3945 {
3946         struct spoolss_DeviceMode *devmode;
3947         WERROR result;
3948
3949         if (!ntprinter->info_2->devmode) {
3950                 r->devmode = NULL;
3951                 return WERR_OK;
3952         }
3953
3954         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3955         W_ERROR_HAVE_NO_MEMORY(devmode);
3956
3957         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
3958         if (!W_ERROR_IS_OK(result)) {
3959                 TALLOC_FREE(devmode);
3960                 return result;
3961         }
3962
3963         r->devmode      = devmode;
3964
3965         return WERR_OK;
3966 }
3967
3968
3969 /********************************************************************
3970 ********************************************************************/
3971
3972 static bool snum_is_shared_printer(int snum)
3973 {
3974         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3975 }
3976
3977 /********************************************************************
3978  Spoolss_enumprinters.
3979 ********************************************************************/
3980
3981 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3982                                            uint32_t level,
3983                                            uint32_t flags,
3984                                            union spoolss_PrinterInfo **info_p,
3985                                            uint32_t *count_p)
3986 {
3987         int snum;
3988         int n_services = lp_numservices();
3989         union spoolss_PrinterInfo *info = NULL;
3990         uint32_t count = 0;
3991         WERROR result = WERR_OK;
3992
3993         *count_p = 0;
3994         *info_p = NULL;
3995
3996         for (snum = 0; snum < n_services; snum++) {
3997
3998                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999
4000                 if (!snum_is_shared_printer(snum)) {
4001                         continue;
4002                 }
4003
4004                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4005                         lp_servicename(snum), snum));
4006
4007                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4008                                             union spoolss_PrinterInfo,
4009                                             count + 1);
4010                 if (!info) {
4011                         result = WERR_NOMEM;
4012                         goto out;
4013                 }
4014
4015                 result = get_a_printer(NULL, &ntprinter, 2,
4016                                        lp_const_servicename(snum));
4017                 if (!W_ERROR_IS_OK(result)) {
4018                         goto out;
4019                 }
4020
4021                 switch (level) {
4022                 case 0:
4023                         result = construct_printer_info0(info, ntprinter,
4024                                                          &info[count].info0, snum);
4025                         break;
4026                 case 1:
4027                         result = construct_printer_info1(info, ntprinter, flags,
4028                                                          &info[count].info1, snum);
4029                         break;
4030                 case 2:
4031                         result = construct_printer_info2(info, ntprinter,
4032                                                          &info[count].info2, snum);
4033                         break;
4034                 case 4:
4035                         result = construct_printer_info4(info, ntprinter,
4036                                                          &info[count].info4, snum);
4037                         break;
4038                 case 5:
4039                         result = construct_printer_info5(info, ntprinter,
4040                                                          &info[count].info5, snum);
4041                         break;
4042
4043                 default:
4044                         result = WERR_UNKNOWN_LEVEL;
4045                         free_a_printer(&ntprinter, 2);
4046                         goto out;
4047                 }
4048
4049                 free_a_printer(&ntprinter, 2);
4050                 if (!W_ERROR_IS_OK(result)) {
4051                         goto out;
4052                 }
4053
4054                 count++;
4055         }
4056
4057         *count_p = count;
4058         *info_p = info;
4059
4060  out:
4061         if (!W_ERROR_IS_OK(result)) {
4062                 TALLOC_FREE(info);
4063                 return result;
4064         }
4065
4066         *info_p = info;
4067
4068         return WERR_OK;
4069 }
4070
4071 /********************************************************************
4072  * handle enumeration of printers at level 0
4073  ********************************************************************/
4074
4075 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4076                                   uint32_t flags,
4077                                   const char *servername,
4078                                   union spoolss_PrinterInfo **info,
4079                                   uint32_t *count)
4080 {
4081         DEBUG(4,("enum_all_printers_info_0\n"));
4082
4083         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4084 }
4085
4086
4087 /********************************************************************
4088 ********************************************************************/
4089
4090 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4091                                        uint32_t flags,
4092                                        union spoolss_PrinterInfo **info,
4093                                        uint32_t *count)
4094 {
4095         DEBUG(4,("enum_all_printers_info_1\n"));
4096
4097         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4098 }
4099
4100 /********************************************************************
4101  enum_all_printers_info_1_local.
4102 *********************************************************************/
4103
4104 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4105                                              union spoolss_PrinterInfo **info,
4106                                              uint32_t *count)
4107 {
4108         DEBUG(4,("enum_all_printers_info_1_local\n"));
4109
4110         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4111 }
4112
4113 /********************************************************************
4114  enum_all_printers_info_1_name.
4115 *********************************************************************/
4116
4117 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4118                                             const char *name,
4119                                             union spoolss_PrinterInfo **info,
4120                                             uint32_t *count)
4121 {
4122         const char *s = name;
4123
4124         DEBUG(4,("enum_all_printers_info_1_name\n"));
4125
4126         if ((name[0] == '\\') && (name[1] == '\\')) {
4127                 s = name + 2;
4128         }
4129
4130         if (!is_myname_or_ipaddr(s)) {
4131                 return WERR_INVALID_NAME;
4132         }
4133
4134         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4135 }
4136
4137 /********************************************************************
4138  enum_all_printers_info_1_network.
4139 *********************************************************************/
4140
4141 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4142                                                const char *name,
4143                                                union spoolss_PrinterInfo **info,
4144                                                uint32_t *count)
4145 {
4146         const char *s = name;
4147
4148         DEBUG(4,("enum_all_printers_info_1_network\n"));
4149
4150         /* If we respond to a enum_printers level 1 on our name with flags
4151            set to PRINTER_ENUM_REMOTE with a list of printers then these
4152            printers incorrectly appear in the APW browse list.
4153            Specifically the printers for the server appear at the workgroup
4154            level where all the other servers in the domain are
4155            listed. Windows responds to this call with a
4156            WERR_CAN_NOT_COMPLETE so we should do the same. */
4157
4158         if (name[0] == '\\' && name[1] == '\\') {
4159                  s = name + 2;
4160         }
4161
4162         if (is_myname_or_ipaddr(s)) {
4163                  return WERR_CAN_NOT_COMPLETE;
4164         }
4165
4166         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4167 }
4168
4169 /********************************************************************
4170  * api_spoolss_enumprinters
4171  *
4172  * called from api_spoolss_enumprinters (see this to understand)
4173  ********************************************************************/
4174
4175 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4176                                        union spoolss_PrinterInfo **info,
4177                                        uint32_t *count)
4178 {
4179         DEBUG(4,("enum_all_printers_info_2\n"));
4180
4181         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4182 }
4183
4184 /********************************************************************
4185  * handle enumeration of printers at level 1
4186  ********************************************************************/
4187
4188 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4189                                   uint32_t flags,
4190                                   const char *name,
4191                                   union spoolss_PrinterInfo **info,
4192                                   uint32_t *count)
4193 {
4194         /* Not all the flags are equals */
4195
4196         if (flags & PRINTER_ENUM_LOCAL) {
4197                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4198         }
4199
4200         if (flags & PRINTER_ENUM_NAME) {
4201                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4202         }
4203
4204         if (flags & PRINTER_ENUM_NETWORK) {
4205                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4206         }
4207
4208         return WERR_OK; /* NT4sp5 does that */
4209 }
4210
4211 /********************************************************************
4212  * handle enumeration of printers at level 2
4213  ********************************************************************/
4214
4215 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4216                                   uint32_t flags,
4217                                   const char *servername,
4218                                   union spoolss_PrinterInfo **info,
4219                                   uint32_t *count)
4220 {
4221         if (flags & PRINTER_ENUM_LOCAL) {
4222                 return enum_all_printers_info_2(mem_ctx, info, count);
4223         }
4224
4225         if (flags & PRINTER_ENUM_NAME) {
4226                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4227                         return WERR_INVALID_NAME;
4228                 }
4229
4230                 return enum_all_printers_info_2(mem_ctx, info, count);
4231         }
4232
4233         if (flags & PRINTER_ENUM_REMOTE) {
4234                 return WERR_UNKNOWN_LEVEL;
4235         }
4236
4237         return WERR_OK;
4238 }
4239
4240 /********************************************************************
4241  * handle enumeration of printers at level 4
4242  ********************************************************************/
4243
4244 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4245                                   uint32_t flags,
4246                                   const char *servername,
4247                                   union spoolss_PrinterInfo **info,
4248                                   uint32_t *count)
4249 {
4250         DEBUG(4,("enum_all_printers_info_4\n"));
4251
4252         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4253 }
4254
4255
4256 /********************************************************************
4257  * handle enumeration of printers at level 5
4258  ********************************************************************/
4259
4260 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4261                                   uint32_t flags,
4262                                   const char *servername,
4263                                   union spoolss_PrinterInfo **info,
4264                                   uint32_t *count)
4265 {
4266         DEBUG(4,("enum_all_printers_info_5\n"));
4267
4268         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4269 }
4270
4271 /****************************************************************
4272  _spoolss_EnumPrinters
4273 ****************************************************************/
4274
4275 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4276                              struct spoolss_EnumPrinters *r)
4277 {
4278         const char *name;
4279         WERROR result;
4280
4281         /* that's an [in out] buffer */
4282
4283         if (!r->in.buffer && (r->in.offered != 0)) {
4284                 return WERR_INVALID_PARAM;
4285         }
4286
4287         DEBUG(4,("_spoolss_EnumPrinters\n"));
4288
4289         *r->out.needed = 0;
4290         *r->out.count = 0;
4291         *r->out.info = NULL;
4292
4293         /*
4294          * Level 1:
4295          *          flags==PRINTER_ENUM_NAME
4296          *           if name=="" then enumerates all printers
4297          *           if name!="" then enumerate the printer
4298          *          flags==PRINTER_ENUM_REMOTE
4299          *          name is NULL, enumerate printers
4300          * Level 2: name!="" enumerates printers, name can't be NULL
4301          * Level 3: doesn't exist
4302          * Level 4: does a local registry lookup
4303          * Level 5: same as Level 2
4304          */
4305
4306         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4307         W_ERROR_HAVE_NO_MEMORY(name);
4308
4309         switch (r->in.level) {
4310         case 0:
4311                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4312                                              r->out.info, r->out.count);
4313                 break;
4314         case 1:
4315                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4316                                              r->out.info, r->out.count);
4317                 break;
4318         case 2:
4319                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4320                                              r->out.info, r->out.count);
4321                 break;
4322         case 4:
4323                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4324                                              r->out.info, r->out.count);
4325                 break;
4326         case 5:
4327                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4328                                              r->out.info, r->out.count);
4329                 break;
4330         default:
4331                 return WERR_UNKNOWN_LEVEL;
4332         }
4333
4334         if (!W_ERROR_IS_OK(result)) {
4335                 return result;
4336         }
4337
4338         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4339                                                      spoolss_EnumPrinters, NULL,
4340                                                      *r->out.info, r->in.level,
4341                                                      *r->out.count);
4342         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4343         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4344
4345         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4346 }
4347
4348 /****************************************************************
4349  _spoolss_GetPrinter
4350 ****************************************************************/
4351
4352 WERROR _spoolss_GetPrinter(pipes_struct *p,
4353                            struct spoolss_GetPrinter *r)
4354 {
4355         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4356         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4357         WERROR result = WERR_OK;
4358
4359         int snum;
4360
4361         /* that's an [in out] buffer */
4362
4363         if (!r->in.buffer && (r->in.offered != 0)) {
4364                 return WERR_INVALID_PARAM;
4365         }
4366
4367         *r->out.needed = 0;
4368
4369         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4370                 return WERR_BADFID;
4371         }
4372
4373         result = get_a_printer(Printer, &ntprinter, 2,
4374                                lp_const_servicename(snum));
4375         if (!W_ERROR_IS_OK(result)) {
4376                 return result;
4377         }
4378
4379         switch (r->in.level) {
4380         case 0:
4381                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4382                                                  &r->out.info->info0, snum);
4383                 break;
4384         case 1:
4385                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4386                                                  PRINTER_ENUM_ICON8,
4387                                                  &r->out.info->info1, snum);
4388                 break;
4389         case 2:
4390                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4391                                                  &r->out.info->info2, snum);
4392                 break;
4393         case 3:
4394                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4395                                                  &r->out.info->info3, snum);
4396                 break;
4397         case 4:
4398                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4399                                                  &r->out.info->info4, snum);
4400                 break;
4401         case 5:
4402                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4403                                                  &r->out.info->info5, snum);
4404                 break;
4405         case 6:
4406                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4407                                                  &r->out.info->info6, snum);
4408                 break;
4409         case 7:
4410                 result = construct_printer_info7(p->mem_ctx, Printer,
4411                                                  &r->out.info->info7, snum);
4412                 break;
4413         case 8:
4414                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4415                                                  &r->out.info->info8, snum);
4416                 break;
4417         default:
4418                 result = WERR_UNKNOWN_LEVEL;
4419                 break;
4420         }
4421
4422         free_a_printer(&ntprinter, 2);
4423
4424         if (!W_ERROR_IS_OK(result)) {
4425                 TALLOC_FREE(r->out.info);
4426                 return result;
4427         }
4428
4429         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4430                                                r->out.info, r->in.level);
4431         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4432
4433         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4434 }
4435
4436 /********************************************************************
4437  ********************************************************************/
4438
4439 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4440                                                   const char **string_array,
4441                                                   const char *cservername)
4442 {
4443         int i, num_strings = 0;
4444         const char **array = NULL;
4445
4446         if (!string_array) {
4447                 return NULL;
4448         }
4449
4450         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4451
4452                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4453                                                   cservername, string_array[i]);
4454                 if (!str) {
4455                         TALLOC_FREE(array);
4456                         return NULL;
4457                 }
4458
4459
4460                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4461                         TALLOC_FREE(array);
4462                         return NULL;
4463                 }
4464         }
4465
4466         if (i > 0) {
4467                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4468                              &array, &num_strings);
4469         }
4470
4471         return array;
4472 }
4473
4474 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4475         do { \
4476                 if (in && strlen(in)) { \
4477                         out = talloc_strdup(mem_ctx, in); \
4478                         W_ERROR_HAVE_NO_MEMORY(out); \
4479                 } \
4480         } while (0);
4481
4482 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4483         do { \
4484                 if (in && strlen(in)) { \
4485                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4486                 } else { \
4487                         out = talloc_strdup(mem_ctx, ""); \
4488                 } \
4489                 W_ERROR_HAVE_NO_MEMORY(out); \
4490         } while (0);
4491
4492 /********************************************************************
4493  * fill a spoolss_DriverInfo1 struct
4494  ********************************************************************/
4495
4496 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4497                                         struct spoolss_DriverInfo1 *r,
4498                                         const struct spoolss_DriverInfo3 *driver,
4499                                         const char *servername,
4500                                         const char *architecture)
4501 {
4502         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4503         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4504
4505         return WERR_OK;
4506 }
4507
4508 /********************************************************************
4509  * fill a spoolss_DriverInfo2 struct
4510  ********************************************************************/
4511
4512 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4513                                         struct spoolss_DriverInfo2 *r,
4514                                         const struct spoolss_DriverInfo3 *driver,
4515                                         const char *servername)
4516
4517 {
4518         const char *cservername = canon_servername(servername);
4519
4520         r->version              = driver->version;
4521
4522         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4523         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4524         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4525         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4526
4527         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4528                                driver->driver_path,
4529                                r->driver_path);
4530
4531         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4532                                driver->data_file,
4533                                r->data_file);
4534
4535         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536                                driver->config_file,
4537                                r->config_file);
4538
4539         return WERR_OK;
4540 }
4541
4542 /********************************************************************
4543  * fill a spoolss_DriverInfo3 struct
4544  ********************************************************************/
4545
4546 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4547                                         struct spoolss_DriverInfo3 *r,
4548                                         const struct spoolss_DriverInfo3 *driver,
4549                                         const char *servername)
4550 {
4551         const char *cservername = canon_servername(servername);
4552
4553         r->version              = driver->version;
4554
4555         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4556         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4557         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4558         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4559
4560         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4561                                driver->driver_path,
4562                                r->driver_path);
4563
4564         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4565                                driver->data_file,
4566                                r->data_file);
4567
4568         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4569                                driver->config_file,
4570                                r->config_file);
4571
4572         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573                                driver->help_file,
4574                                r->help_file);
4575
4576         FILL_DRIVER_STRING(mem_ctx,
4577                            driver->monitor_name,
4578                            r->monitor_name);
4579
4580         FILL_DRIVER_STRING(mem_ctx,
4581                            driver->default_datatype,
4582                            r->default_datatype);
4583
4584         r->dependent_files = string_array_from_driver_info(mem_ctx,
4585                                                            driver->dependent_files,
4586                                                            cservername);
4587         return WERR_OK;
4588 }
4589
4590 /********************************************************************
4591  * fill a spoolss_DriverInfo4 struct
4592  ********************************************************************/
4593
4594 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4595                                         struct spoolss_DriverInfo4 *r,
4596                                         const struct spoolss_DriverInfo3 *driver,
4597                                         const char *servername)
4598 {
4599         const char *cservername = canon_servername(servername);
4600
4601         r->version              = driver->version;
4602
4603         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4604         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4605         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4606         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4607
4608         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4609                                driver->driver_path,
4610                                r->driver_path);
4611
4612         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4613                                driver->data_file,
4614                                r->data_file);
4615
4616         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4617                                driver->config_file,
4618                                r->config_file);
4619
4620         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4621                                driver->help_file,
4622                                r->help_file);
4623
4624         r->dependent_files = string_array_from_driver_info(mem_ctx,
4625                                                            driver->dependent_files,
4626                                                            cservername);
4627
4628         FILL_DRIVER_STRING(mem_ctx,
4629                            driver->monitor_name,
4630                            r->monitor_name);
4631
4632         FILL_DRIVER_STRING(mem_ctx,
4633                            driver->default_datatype,
4634                            r->default_datatype);
4635
4636         r->previous_names = string_array_from_driver_info(mem_ctx,
4637                                                           NULL,
4638                                                           cservername);
4639
4640         return WERR_OK;
4641 }
4642
4643 /********************************************************************
4644  * fill a spoolss_DriverInfo5 struct
4645  ********************************************************************/
4646
4647 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4648                                         struct spoolss_DriverInfo5 *r,
4649                                         const struct spoolss_DriverInfo3 *driver,
4650                                         const char *servername)
4651 {
4652         const char *cservername = canon_servername(servername);
4653
4654         r->version              = driver->version;
4655
4656         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4657         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4658         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4659         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4660
4661         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4662                                driver->driver_path,
4663                                r->driver_path);
4664
4665         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4666                                driver->data_file,
4667                                r->data_file);
4668
4669         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4670                                driver->config_file,
4671                                r->config_file);
4672
4673         r->driver_attributes    = 0;
4674         r->config_version       = 0;
4675         r->driver_version       = 0;
4676
4677         return WERR_OK;
4678 }
4679 /********************************************************************
4680  * fill a spoolss_DriverInfo6 struct
4681  ********************************************************************/
4682
4683 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4684                                         struct spoolss_DriverInfo6 *r,
4685                                         const struct spoolss_DriverInfo3 *driver,
4686                                         const char *servername)
4687 {
4688         const char *cservername = canon_servername(servername);
4689
4690         r->version              = driver->version;
4691
4692         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4693         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4694         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4695         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4696
4697         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4698                                driver->driver_path,
4699                                r->driver_path);
4700
4701         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4702                                driver->data_file,
4703                                r->data_file);
4704
4705         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4706                                driver->config_file,
4707                                r->config_file);
4708
4709         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4710                                driver->help_file,
4711                                r->help_file);
4712
4713         FILL_DRIVER_STRING(mem_ctx,
4714                            driver->monitor_name,
4715                            r->monitor_name);
4716
4717         FILL_DRIVER_STRING(mem_ctx,
4718                            driver->default_datatype,
4719                            r->default_datatype);
4720
4721         r->dependent_files = string_array_from_driver_info(mem_ctx,
4722                                                            driver->dependent_files,
4723                                                            cservername);
4724         r->previous_names = string_array_from_driver_info(mem_ctx,
4725                                                           NULL,
4726                                                           cservername);
4727
4728         r->driver_date          = 0;
4729         r->driver_version       = 0;
4730
4731         FILL_DRIVER_STRING(mem_ctx, "",
4732                            r->manufacturer_name);
4733         FILL_DRIVER_STRING(mem_ctx, "",
4734                            r->manufacturer_url);
4735         FILL_DRIVER_STRING(mem_ctx, "",
4736                            r->hardware_id);
4737         FILL_DRIVER_STRING(mem_ctx, "",
4738                            r->provider);
4739
4740         return WERR_OK;
4741 }
4742
4743 /********************************************************************
4744  ********************************************************************/
4745
4746 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4747                                           struct spoolss_DriverFileInfo *r,
4748                                           const char *cservername,
4749                                           const char *file_name,
4750                                           enum spoolss_DriverFileType file_type,
4751                                           uint32_t file_version)
4752 {
4753         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4754                                           cservername, file_name);
4755         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4756         r->file_type    = file_type;
4757         r->file_version = file_version;
4758
4759         return WERR_OK;
4760 }
4761
4762 /********************************************************************
4763  ********************************************************************/
4764
4765 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4766                                                  const struct spoolss_DriverInfo3 *driver,
4767                                                  const char *cservername,
4768                                                  struct spoolss_DriverFileInfo **info_p,
4769                                                  uint32_t *count_p)
4770 {
4771         struct spoolss_DriverFileInfo *info = NULL;
4772         uint32_t count = 0;
4773         WERROR result;
4774         uint32_t i;
4775
4776         *info_p = NULL;
4777         *count_p = 0;
4778
4779         if (strlen(driver->driver_path)) {
4780                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4781                                             struct spoolss_DriverFileInfo,
4782                                             count + 1);
4783                 W_ERROR_HAVE_NO_MEMORY(info);
4784                 result = fill_spoolss_DriverFileInfo(info,
4785                                                      &info[count],
4786                                                      cservername,
4787                                                      driver->driver_path,
4788                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4789                                                      0);
4790                 W_ERROR_NOT_OK_RETURN(result);
4791                 count++;
4792         }
4793
4794         if (strlen(driver->config_file)) {
4795                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4796                                             struct spoolss_DriverFileInfo,
4797                                             count + 1);
4798                 W_ERROR_HAVE_NO_MEMORY(info);
4799                 result = fill_spoolss_DriverFileInfo(info,
4800                                                      &info[count],
4801                                                      cservername,
4802                                                      driver->config_file,
4803                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4804                                                      0);
4805                 W_ERROR_NOT_OK_RETURN(result);
4806                 count++;
4807         }
4808
4809         if (strlen(driver->data_file)) {
4810                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4811                                             struct spoolss_DriverFileInfo,
4812                                             count + 1);
4813                 W_ERROR_HAVE_NO_MEMORY(info);
4814                 result = fill_spoolss_DriverFileInfo(info,
4815                                                      &info[count],
4816                                                      cservername,
4817                                                      driver->data_file,
4818                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4819                                                      0);
4820                 W_ERROR_NOT_OK_RETURN(result);
4821                 count++;
4822         }
4823
4824         if (strlen(driver->help_file)) {
4825                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4826                                             struct spoolss_DriverFileInfo,
4827                                             count + 1);
4828                 W_ERROR_HAVE_NO_MEMORY(info);
4829                 result = fill_spoolss_DriverFileInfo(info,
4830                                                      &info[count],
4831                                                      cservername,
4832                                                      driver->help_file,
4833                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4834                                                      0);
4835                 W_ERROR_NOT_OK_RETURN(result);
4836                 count++;
4837         }
4838
4839         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4840                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4841                                             struct spoolss_DriverFileInfo,
4842                                             count + 1);
4843                 W_ERROR_HAVE_NO_MEMORY(info);
4844                 result = fill_spoolss_DriverFileInfo(info,
4845                                                      &info[count],
4846                                                      cservername,
4847                                                      driver->dependent_files[i],
4848                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4849                                                      0);
4850                 W_ERROR_NOT_OK_RETURN(result);
4851                 count++;
4852         }
4853
4854         *info_p = info;
4855         *count_p = count;
4856
4857         return WERR_OK;
4858 }
4859
4860 /********************************************************************
4861  * fill a spoolss_DriverInfo101 sttruct
4862  ********************************************************************/
4863
4864 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4865                                           struct spoolss_DriverInfo101 *r,
4866                                           const struct spoolss_DriverInfo3 *driver,
4867                                           const char *servername)
4868 {
4869         const char *cservername = canon_servername(servername);
4870         WERROR result;
4871
4872         r->version              = driver->version;
4873
4874         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4875         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4876         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4877         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4878
4879         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4880                                                     cservername,
4881                                                     &r->file_info,
4882                                                     &r->file_count);
4883         if (!W_ERROR_IS_OK(result)) {
4884                 return result;
4885         }
4886
4887         FILL_DRIVER_STRING(mem_ctx,
4888                            driver->monitor_name,
4889                            r->monitor_name);
4890
4891         FILL_DRIVER_STRING(mem_ctx,
4892                            driver->default_datatype,
4893                            r->default_datatype);
4894
4895         r->previous_names = string_array_from_driver_info(mem_ctx,
4896                                                           NULL,
4897                                                           cservername);
4898         r->driver_date          = 0;
4899         r->driver_version       = 0;
4900
4901         FILL_DRIVER_STRING(mem_ctx, "",
4902                            r->manufacturer_name);
4903         FILL_DRIVER_STRING(mem_ctx, "",
4904                            r->manufacturer_url);
4905         FILL_DRIVER_STRING(mem_ctx, "",
4906                            r->hardware_id);
4907         FILL_DRIVER_STRING(mem_ctx, "",
4908                            r->provider);
4909
4910         return WERR_OK;
4911 }
4912
4913 /********************************************************************
4914  * construct_printer_driver_info_1
4915  ********************************************************************/
4916
4917 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4918                                               struct spoolss_DriverInfo1 *r,
4919                                               int snum,
4920                                               const char *servername,
4921                                               const char *architecture,
4922                                               uint32_t version)
4923 {
4924         NT_PRINTER_INFO_LEVEL *printer = NULL;
4925         union spoolss_DriverInfo *driver;
4926         WERROR result;
4927
4928         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4929                 return WERR_INVALID_PRINTER_NAME;
4930
4931         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
4932                 free_a_printer(&printer, 2);
4933                 return WERR_UNKNOWN_PRINTER_DRIVER;
4934         }
4935
4936         result = fill_printer_driver_info1(mem_ctx, r, &driver->info3, servername, architecture);
4937
4938         free_a_printer_driver(driver);
4939         free_a_printer(&printer,2);
4940
4941         return result;
4942 }
4943
4944 /********************************************************************
4945  * construct_printer_driver_info_2
4946  * fill a printer_info_2 struct
4947  ********************************************************************/
4948
4949 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
4950                                               struct spoolss_DriverInfo2 *r,
4951                                               int snum,
4952                                               const char *servername,
4953                                               const char *architecture,
4954                                               uint32_t version)
4955 {
4956         NT_PRINTER_INFO_LEVEL *printer = NULL;
4957         union spoolss_DriverInfo *driver;
4958         WERROR result;
4959
4960         ZERO_STRUCT(printer);
4961
4962         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4963                 return WERR_INVALID_PRINTER_NAME;
4964
4965         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
4966                 free_a_printer(&printer, 2);
4967                 return WERR_UNKNOWN_PRINTER_DRIVER;
4968         }
4969
4970         result = fill_printer_driver_info2(mem_ctx, r, &driver->info3, servername);
4971
4972         free_a_printer_driver(driver);
4973         free_a_printer(&printer,2);
4974
4975         return result;
4976 }
4977
4978 /********************************************************************
4979  * construct_printer_info_3
4980  * fill a printer_info_3 struct
4981  ********************************************************************/
4982
4983 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
4984                                               struct spoolss_DriverInfo3 *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 status;
4993         ZERO_STRUCT(driver);
4994
4995         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
4996         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4997         if (!W_ERROR_IS_OK(status))
4998                 return WERR_INVALID_PRINTER_NAME;
4999
5000         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5001         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5002
5003 #if 0   /* JERRY */
5004
5005         /*
5006          * I put this code in during testing.  Helpful when commenting out the
5007          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5008          * as win2k always queries the driver using an infor level of 6.
5009          * I've left it in (but ifdef'd out) because I'll probably
5010          * use it in experimentation again in the future.   --jerry 22/01/2002
5011          */
5012
5013         if (!W_ERROR_IS_OK(status)) {
5014                 /*
5015                  * Is this a W2k client ?
5016                  */
5017                 if (version == 3) {
5018                         /* Yes - try again with a WinNT driver. */
5019                         version = 2;
5020                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5021                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5022                 }
5023 #endif
5024
5025                 if (!W_ERROR_IS_OK(status)) {
5026                         free_a_printer(&printer,2);
5027                         return WERR_UNKNOWN_PRINTER_DRIVER;
5028                 }
5029
5030 #if 0   /* JERRY */
5031         }
5032 #endif
5033
5034
5035         status = fill_printer_driver_info3(mem_ctx, r, &driver->info3, servername);
5036
5037         free_a_printer_driver(driver);
5038         free_a_printer(&printer,2);
5039
5040         return status;
5041 }
5042
5043 /********************************************************************
5044  * construct_printer_info_6
5045  * fill a printer_info_6 struct
5046  ********************************************************************/
5047
5048 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5049                                               struct spoolss_DriverInfo6 *r,
5050                                               int snum,
5051                                               const char *servername,
5052                                               const char *architecture,
5053                                               uint32_t version)
5054 {
5055         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5056         union spoolss_DriverInfo *driver;
5057         WERROR                          status;
5058
5059         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5060
5061         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5062
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
5068         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5069
5070         if (!W_ERROR_IS_OK(status))
5071         {
5072                 /*
5073                  * Is this a W2k client ?
5074                  */
5075
5076                 if (version < 3) {
5077                         free_a_printer(&printer,2);
5078                         return WERR_UNKNOWN_PRINTER_DRIVER;
5079                 }
5080
5081                 /* Yes - try again with a WinNT driver. */
5082                 version = 2;
5083                 status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5084                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5085                 if (!W_ERROR_IS_OK(status)) {
5086                         free_a_printer(&printer,2);
5087                         return WERR_UNKNOWN_PRINTER_DRIVER;
5088                 }
5089         }
5090
5091         status = fill_printer_driver_info6(mem_ctx, r, &driver->info3, servername);
5092
5093         free_a_printer(&printer,2);
5094         free_a_printer_driver(driver);
5095
5096         return status;
5097 }
5098
5099 /********************************************************************
5100  * construct_printer_info_101
5101  * fill a printer_info_101 struct
5102  ********************************************************************/
5103
5104 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5105                                                 struct spoolss_DriverInfo101 *r,
5106                                                 int snum,
5107                                                 const char *servername,
5108                                                 const char *architecture,
5109                                                 uint32_t version)
5110 {
5111         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5112         union spoolss_DriverInfo *driver;
5113         WERROR                          result;
5114
5115         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5116
5117         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5118                 win_errstr(result)));
5119
5120         if (!W_ERROR_IS_OK(result)) {
5121                 return WERR_INVALID_PRINTER_NAME;
5122         }
5123
5124         result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5125                                       architecture, version);
5126
5127         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5128                 win_errstr(result)));
5129
5130         if (!W_ERROR_IS_OK(result)) {
5131                 /*
5132                  * Is this a W2k client ?
5133                  */
5134
5135                 if (version < 3) {
5136                         free_a_printer(&printer, 2);
5137                         return WERR_UNKNOWN_PRINTER_DRIVER;
5138                 }
5139
5140                 /* Yes - try again with a WinNT driver. */
5141                 version = 2;
5142                 result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5143                                               architecture, version);
5144                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5145                         win_errstr(result)));
5146                 if (!W_ERROR_IS_OK(result)) {
5147                         free_a_printer(&printer, 2);
5148                         return WERR_UNKNOWN_PRINTER_DRIVER;
5149                 }
5150         }
5151
5152         result = fill_printer_driver_info101(mem_ctx, r, &driver->info3, servername);
5153
5154         free_a_printer(&printer, 2);
5155         free_a_printer_driver(driver);
5156
5157         return result;
5158 }
5159
5160 /****************************************************************
5161  _spoolss_GetPrinterDriver2
5162 ****************************************************************/
5163
5164 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5165                                   struct spoolss_GetPrinterDriver2 *r)
5166 {
5167         Printer_entry *printer;
5168         WERROR result;
5169
5170         const char *servername;
5171         int snum;
5172
5173         /* that's an [in out] buffer */
5174
5175         if (!r->in.buffer && (r->in.offered != 0)) {
5176                 return WERR_INVALID_PARAM;
5177         }
5178
5179         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5180
5181         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5182                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5183                 return WERR_INVALID_PRINTER_NAME;
5184         }
5185
5186         *r->out.needed = 0;
5187         *r->out.server_major_version = 0;
5188         *r->out.server_minor_version = 0;
5189
5190         servername = get_server_name(printer);
5191
5192         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5193                 return WERR_BADFID;
5194         }
5195
5196         switch (r->in.level) {
5197         case 1:
5198                 result = construct_printer_driver_info_1(p->mem_ctx,
5199                                                          &r->out.info->info1,
5200                                                          snum,
5201                                                          servername,
5202                                                          r->in.architecture,
5203                                                          r->in.client_major_version);
5204                 break;
5205         case 2:
5206                 result = construct_printer_driver_info_2(p->mem_ctx,
5207                                                          &r->out.info->info2,
5208                                                          snum,
5209                                                          servername,
5210                                                          r->in.architecture,
5211                                                          r->in.client_major_version);
5212                 break;
5213         case 3:
5214                 result = construct_printer_driver_info_3(p->mem_ctx,
5215                                                          &r->out.info->info3,
5216                                                          snum,
5217                                                          servername,
5218                                                          r->in.architecture,
5219                                                          r->in.client_major_version);
5220                 break;
5221         case 6:
5222                 result = construct_printer_driver_info_6(p->mem_ctx,
5223                                                          &r->out.info->info6,
5224                                                          snum,
5225                                                          servername,
5226                                                          r->in.architecture,
5227                                                          r->in.client_major_version);
5228                 break;
5229         case 101:
5230                 result = construct_printer_driver_info_101(p->mem_ctx,
5231                                                            &r->out.info->info101,
5232                                                            snum,
5233                                                            servername,
5234                                                            r->in.architecture,
5235                                                            r->in.client_major_version);
5236                 break;
5237         default:
5238                 result = WERR_UNKNOWN_LEVEL;
5239                 break;
5240         }
5241
5242         if (!W_ERROR_IS_OK(result)) {
5243                 TALLOC_FREE(r->out.info);
5244                 return result;
5245         }
5246
5247         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5248                                                r->out.info, r->in.level);
5249         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5250
5251         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5252 }
5253
5254
5255 /****************************************************************
5256  _spoolss_StartPagePrinter
5257 ****************************************************************/
5258
5259 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5260                                  struct spoolss_StartPagePrinter *r)
5261 {
5262         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5263
5264         if (!Printer) {
5265                 DEBUG(3,("_spoolss_StartPagePrinter: "
5266                         "Error in startpageprinter printer handle\n"));
5267                 return WERR_BADFID;
5268         }
5269
5270         Printer->page_started = true;
5271         return WERR_OK;
5272 }
5273
5274 /****************************************************************
5275  _spoolss_EndPagePrinter
5276 ****************************************************************/
5277
5278 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5279                                struct spoolss_EndPagePrinter *r)
5280 {
5281         int snum;
5282
5283         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5284
5285         if (!Printer) {
5286                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5287                         OUR_HANDLE(r->in.handle)));
5288                 return WERR_BADFID;
5289         }
5290
5291         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5292                 return WERR_BADFID;
5293
5294         Printer->page_started = false;
5295         print_job_endpage(snum, Printer->jobid);
5296
5297         return WERR_OK;
5298 }
5299
5300 /****************************************************************
5301  _spoolss_StartDocPrinter
5302 ****************************************************************/
5303
5304 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5305                                 struct spoolss_StartDocPrinter *r)
5306 {
5307         struct spoolss_DocumentInfo1 *info_1;
5308         int snum;
5309         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5310
5311         if (!Printer) {
5312                 DEBUG(2,("_spoolss_StartDocPrinter: "
5313                         "Invalid handle (%s:%u:%u)\n",
5314                         OUR_HANDLE(r->in.handle)));
5315                 return WERR_BADFID;
5316         }
5317
5318         if (r->in.level != 1) {
5319                 return WERR_UNKNOWN_LEVEL;
5320         }
5321
5322         info_1 = r->in.info.info1;
5323
5324         /*
5325          * a nice thing with NT is it doesn't listen to what you tell it.
5326          * when asked to send _only_ RAW datas, it tries to send datas
5327          * in EMF format.
5328          *
5329          * So I add checks like in NT Server ...
5330          */
5331
5332         if (info_1->datatype) {
5333                 if (strcmp(info_1->datatype, "RAW") != 0) {
5334                         *r->out.job_id = 0;
5335                         return WERR_INVALID_DATATYPE;
5336                 }
5337         }
5338
5339         /* get the share number of the printer */
5340         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5341                 return WERR_BADFID;
5342         }
5343
5344         Printer->jobid = print_job_start(p->server_info, snum,
5345                                          info_1->document_name,
5346                                          Printer->nt_devmode);
5347
5348         /* An error occured in print_job_start() so return an appropriate
5349            NT error code. */
5350
5351         if (Printer->jobid == -1) {
5352                 return map_werror_from_unix(errno);
5353         }
5354
5355         Printer->document_started = true;
5356         *r->out.job_id = Printer->jobid;
5357
5358         return WERR_OK;
5359 }
5360
5361 /****************************************************************
5362  _spoolss_EndDocPrinter
5363 ****************************************************************/
5364
5365 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5366                               struct spoolss_EndDocPrinter *r)
5367 {
5368         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5369         int snum;
5370
5371         if (!Printer) {
5372                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5373                         OUR_HANDLE(r->in.handle)));
5374                 return WERR_BADFID;
5375         }
5376
5377         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5378                 return WERR_BADFID;
5379         }
5380
5381         Printer->document_started = false;
5382         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5383         /* error codes unhandled so far ... */
5384
5385         return WERR_OK;
5386 }
5387
5388 /****************************************************************
5389  _spoolss_WritePrinter
5390 ****************************************************************/
5391
5392 WERROR _spoolss_WritePrinter(pipes_struct *p,
5393                              struct spoolss_WritePrinter *r)
5394 {
5395         uint32_t buffer_written;
5396         int snum;
5397         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5398
5399         if (!Printer) {
5400                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5401                         OUR_HANDLE(r->in.handle)));
5402                 *r->out.num_written = r->in._data_size;
5403                 return WERR_BADFID;
5404         }
5405
5406         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5407                 return WERR_BADFID;
5408
5409         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5410                                                    (const char *)r->in.data.data,
5411                                                    (SMB_OFF_T)-1,
5412                                                    (size_t)r->in._data_size);
5413         if (buffer_written == (uint32_t)-1) {
5414                 *r->out.num_written = 0;
5415                 if (errno == ENOSPC)
5416                         return WERR_NO_SPOOL_SPACE;
5417                 else
5418                         return WERR_ACCESS_DENIED;
5419         }
5420
5421         *r->out.num_written = r->in._data_size;
5422
5423         return WERR_OK;
5424 }
5425
5426 /********************************************************************
5427  * api_spoolss_getprinter
5428  * called from the spoolss dispatcher
5429  *
5430  ********************************************************************/
5431
5432 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5433                               pipes_struct *p)
5434 {
5435         int snum;
5436         WERROR errcode = WERR_BADFUNC;
5437         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5438
5439         if (!Printer) {
5440                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5441                         OUR_HANDLE(handle)));
5442                 return WERR_BADFID;
5443         }
5444
5445         if (!get_printer_snum(p, handle, &snum, NULL))
5446                 return WERR_BADFID;
5447
5448         switch (command) {
5449         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5450                 errcode = print_queue_pause(p->server_info, snum);
5451                 break;
5452         case SPOOLSS_PRINTER_CONTROL_RESUME:
5453         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5454                 errcode = print_queue_resume(p->server_info, snum);
5455                 break;
5456         case SPOOLSS_PRINTER_CONTROL_PURGE:
5457                 errcode = print_queue_purge(p->server_info, snum);
5458                 break;
5459         default:
5460                 return WERR_UNKNOWN_LEVEL;
5461         }
5462
5463         return errcode;
5464 }
5465
5466
5467 /****************************************************************
5468  _spoolss_AbortPrinter
5469  * From MSDN: "Deletes printer's spool file if printer is configured
5470  * for spooling"
5471 ****************************************************************/
5472
5473 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5474                              struct spoolss_AbortPrinter *r)
5475 {
5476         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5477         int             snum;
5478         WERROR          errcode = WERR_OK;
5479
5480         if (!Printer) {
5481                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5482                         OUR_HANDLE(r->in.handle)));
5483                 return WERR_BADFID;
5484         }
5485
5486         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5487                 return WERR_BADFID;
5488
5489         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5490
5491         return errcode;
5492 }
5493
5494 /********************************************************************
5495  * called by spoolss_api_setprinter
5496  * when updating a printer description
5497  ********************************************************************/
5498
5499 static WERROR update_printer_sec(struct policy_handle *handle,
5500                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5501 {
5502         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5503         WERROR result;
5504         int snum;
5505
5506         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5507
5508         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5509                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5510                          OUR_HANDLE(handle)));
5511
5512                 result = WERR_BADFID;
5513                 goto done;
5514         }
5515
5516         if (!secdesc_ctr) {
5517                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5518                 result = WERR_INVALID_PARAM;
5519                 goto done;
5520         }
5521
5522         /* Check the user has permissions to change the security
5523            descriptor.  By experimentation with two NT machines, the user
5524            requires Full Access to the printer to change security
5525            information. */
5526
5527         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5528                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5529                 result = WERR_ACCESS_DENIED;
5530                 goto done;
5531         }
5532
5533         /* NT seems to like setting the security descriptor even though
5534            nothing may have actually changed. */
5535
5536         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5537                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5538                 result = WERR_BADFID;
5539                 goto done;
5540         }
5541
5542         if (DEBUGLEVEL >= 10) {
5543                 SEC_ACL *the_acl;
5544                 int i;
5545
5546                 the_acl = old_secdesc_ctr->sd->dacl;
5547                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5548                            PRINTERNAME(snum), the_acl->num_aces));
5549
5550                 for (i = 0; i < the_acl->num_aces; i++) {
5551                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5552                                            &the_acl->aces[i].trustee),
5553                                   the_acl->aces[i].access_mask));
5554                 }
5555
5556                 the_acl = secdesc_ctr->sd->dacl;
5557
5558                 if (the_acl) {
5559                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5560                                    PRINTERNAME(snum), the_acl->num_aces));
5561
5562                         for (i = 0; i < the_acl->num_aces; i++) {
5563                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5564                                                    &the_acl->aces[i].trustee),
5565                                            the_acl->aces[i].access_mask));
5566                         }
5567                 } else {
5568                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5569                 }
5570         }
5571
5572         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5573         if (!new_secdesc_ctr) {
5574                 result = WERR_NOMEM;
5575                 goto done;
5576         }
5577
5578         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5579                 result = WERR_OK;
5580                 goto done;
5581         }
5582
5583         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5584
5585  done:
5586
5587         return result;
5588 }
5589
5590 /********************************************************************
5591  Canonicalize printer info from a client
5592
5593  ATTN: It does not matter what we set the servername to hear
5594  since we do the necessary work in get_a_printer() to set it to
5595  the correct value based on what the client sent in the
5596  _spoolss_open_printer_ex().
5597  ********************************************************************/
5598
5599 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5600 {
5601         fstring printername;
5602         const char *p;
5603
5604         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5605                 "portname=%s drivername=%s comment=%s location=%s\n",
5606                 info->servername, info->printername, info->sharename,
5607                 info->portname, info->drivername, info->comment, info->location));
5608
5609         /* we force some elements to "correct" values */
5610         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5611         fstrcpy(info->sharename, lp_servicename(snum));
5612
5613         /* check to see if we allow printername != sharename */
5614
5615         if ( lp_force_printername(snum) ) {
5616                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5617                         global_myname(), info->sharename );
5618         } else {
5619
5620                 /* make sure printername is in \\server\printername format */
5621
5622                 fstrcpy( printername, info->printername );
5623                 p = printername;
5624                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5625                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5626                                 p++;
5627                 }
5628
5629                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5630                          global_myname(), p );
5631         }
5632
5633         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5634         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5635
5636
5637
5638         return true;
5639 }
5640
5641 /****************************************************************************
5642 ****************************************************************************/
5643
5644 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5645 {
5646         char *cmd = lp_addport_cmd();
5647         char *command = NULL;
5648         int ret;
5649         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5650         bool is_print_op = false;
5651
5652         if ( !*cmd ) {
5653                 return WERR_ACCESS_DENIED;
5654         }
5655
5656         command = talloc_asprintf(ctx,
5657                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5658         if (!command) {
5659                 return WERR_NOMEM;
5660         }
5661
5662         if ( token )
5663                 is_print_op = user_has_privileges( token, &se_printop );
5664
5665         DEBUG(10,("Running [%s]\n", command));
5666
5667         /********* BEGIN SePrintOperatorPrivilege **********/
5668
5669         if ( is_print_op )
5670                 become_root();
5671
5672         ret = smbrun(command, NULL);
5673
5674         if ( is_print_op )
5675                 unbecome_root();
5676
5677         /********* END SePrintOperatorPrivilege **********/
5678
5679         DEBUGADD(10,("returned [%d]\n", ret));
5680
5681         TALLOC_FREE(command);
5682
5683         if ( ret != 0 ) {
5684                 return WERR_ACCESS_DENIED;
5685         }
5686
5687         return WERR_OK;
5688 }
5689
5690 /****************************************************************************
5691 ****************************************************************************/
5692
5693 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5694 {
5695         char *cmd = lp_addprinter_cmd();
5696         char **qlines;
5697         char *command = NULL;
5698         int numlines;
5699         int ret;
5700         int fd;
5701         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5702         bool is_print_op = false;
5703         char *remote_machine = talloc_strdup(ctx, "%m");
5704
5705         if (!remote_machine) {
5706                 return false;
5707         }
5708         remote_machine = talloc_sub_basic(ctx,
5709                                 current_user_info.smb_name,
5710                                 current_user_info.domain,
5711                                 remote_machine);
5712         if (!remote_machine) {
5713                 return false;
5714         }
5715
5716         command = talloc_asprintf(ctx,
5717                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5718                         cmd, printer->info_2->printername, printer->info_2->sharename,
5719                         printer->info_2->portname, printer->info_2->drivername,
5720                         printer->info_2->location, printer->info_2->comment, remote_machine);
5721         if (!command) {
5722                 return false;
5723         }
5724
5725         if ( token )
5726                 is_print_op = user_has_privileges( token, &se_printop );
5727
5728         DEBUG(10,("Running [%s]\n", command));
5729
5730         /********* BEGIN SePrintOperatorPrivilege **********/
5731
5732         if ( is_print_op )
5733                 become_root();
5734
5735         if ( (ret = smbrun(command, &fd)) == 0 ) {
5736                 /* Tell everyone we updated smb.conf. */
5737                 message_send_all(smbd_messaging_context(),
5738                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5739         }
5740
5741         if ( is_print_op )
5742                 unbecome_root();
5743
5744         /********* END SePrintOperatorPrivilege **********/
5745
5746         DEBUGADD(10,("returned [%d]\n", ret));
5747
5748         TALLOC_FREE(command);
5749         TALLOC_FREE(remote_machine);
5750
5751         if ( ret != 0 ) {
5752                 if (fd != -1)
5753                         close(fd);
5754                 return false;
5755         }
5756
5757         /* reload our services immediately */
5758         become_root();
5759         reload_services(false);
5760         unbecome_root();
5761
5762         numlines = 0;
5763         /* Get lines and convert them back to dos-codepage */
5764         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5765         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5766         close(fd);
5767
5768         /* Set the portname to what the script says the portname should be. */
5769         /* but don't require anything to be return from the script exit a good error code */
5770
5771         if (numlines) {
5772                 /* Set the portname to what the script says the portname should be. */
5773                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5774                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5775         }
5776
5777         TALLOC_FREE(qlines);
5778         return true;
5779 }
5780
5781
5782 /********************************************************************
5783  * Called by spoolss_api_setprinter
5784  * when updating a printer description.
5785  ********************************************************************/
5786
5787 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5788                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5789                              struct spoolss_DeviceMode *devmode)
5790 {
5791         int snum;
5792         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5793         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5794         WERROR result;
5795         DATA_BLOB buffer;
5796         fstring asc_buffer;
5797
5798         DEBUG(8,("update_printer\n"));
5799
5800         result = WERR_OK;
5801
5802         if (!Printer) {
5803                 result = WERR_BADFID;
5804                 goto done;
5805         }
5806
5807         if (!get_printer_snum(p, handle, &snum, NULL)) {
5808                 result = WERR_BADFID;
5809                 goto done;
5810         }
5811
5812         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5813             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5814                 result = WERR_BADFID;
5815                 goto done;
5816         }
5817
5818         DEBUGADD(8,("Converting info_2 struct\n"));
5819
5820         /*
5821          * convert_printer_info converts the incoming
5822          * info from the client and overwrites the info
5823          * just read from the tdb in the pointer 'printer'.
5824          */
5825
5826         if (!convert_printer_info(info_ctr, printer)) {
5827                 result =  WERR_NOMEM;
5828                 goto done;
5829         }
5830
5831         if (devmode) {
5832                 /* we have a valid devmode
5833                    convert it and link it*/
5834
5835                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5836                 if (!convert_devicemode(printer->info_2->printername, devmode,
5837                                         &printer->info_2->devmode)) {
5838                         result =  WERR_NOMEM;
5839                         goto done;
5840                 }
5841         }
5842
5843         /* Do sanity check on the requested changes for Samba */
5844
5845         if (!check_printer_ok(printer->info_2, snum)) {
5846                 result = WERR_INVALID_PARAM;
5847                 goto done;
5848         }
5849
5850         /* FIXME!!! If the driver has changed we really should verify that
5851            it is installed before doing much else   --jerry */
5852
5853         /* Check calling user has permission to update printer description */
5854
5855         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5856                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5857                 result = WERR_ACCESS_DENIED;
5858                 goto done;
5859         }
5860
5861         /* Call addprinter hook */
5862         /* Check changes to see if this is really needed */
5863
5864         if ( *lp_addprinter_cmd()
5865                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5866                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5867                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5868                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5869         {
5870                 /* add_printer_hook() will call reload_services() */
5871
5872                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5873                                        printer) ) {
5874                         result = WERR_ACCESS_DENIED;
5875                         goto done;
5876                 }
5877         }
5878
5879         /*
5880          * When a *new* driver is bound to a printer, the drivername is used to
5881          * lookup previously saved driver initialization info, which is then
5882          * bound to the printer, simulating what happens in the Windows arch.
5883          */
5884         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5885         {
5886                 if (!set_driver_init(printer, 2))
5887                 {
5888                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5889                                 printer->info_2->drivername));
5890                 }
5891
5892                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5893                         printer->info_2->drivername));
5894
5895                 notify_printer_driver(snum, printer->info_2->drivername);
5896         }
5897
5898         /*
5899          * flag which changes actually occured.  This is a small subset of
5900          * all the possible changes.  We also have to update things in the
5901          * DsSpooler key.
5902          */
5903
5904         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5905                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5906                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5907                         REG_SZ, buffer.data, buffer.length);
5908
5909                 notify_printer_comment(snum, printer->info_2->comment);
5910         }
5911
5912         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5913                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5914                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5915                         REG_SZ, buffer.data, buffer.length);
5916
5917                 notify_printer_sharename(snum, printer->info_2->sharename);
5918         }
5919
5920         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5921                 char *pname;
5922
5923                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5924                         pname++;
5925                 else
5926                         pname = printer->info_2->printername;
5927
5928
5929                 push_reg_sz(talloc_tos(), &buffer, pname);
5930                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5931                         REG_SZ, buffer.data, buffer.length);
5932
5933                 notify_printer_printername( snum, pname );
5934         }
5935
5936         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5937                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5938                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5939                         REG_SZ, buffer.data, buffer.length);
5940
5941                 notify_printer_port(snum, printer->info_2->portname);
5942         }
5943
5944         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5945                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5946                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5947                         REG_SZ, buffer.data, buffer.length);
5948
5949                 notify_printer_location(snum, printer->info_2->location);
5950         }
5951
5952         /* here we need to update some more DsSpooler keys */
5953         /* uNCName, serverName, shortServerName */
5954
5955         push_reg_sz(talloc_tos(), &buffer, global_myname());
5956         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5957                 REG_SZ, buffer.data, buffer.length);
5958         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5959                 REG_SZ, buffer.data, buffer.length);
5960
5961         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5962                  global_myname(), printer->info_2->sharename );
5963         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5964         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5965                 REG_SZ, buffer.data, buffer.length);
5966
5967         /* Update printer info */
5968         result = mod_a_printer(printer, 2);
5969
5970 done:
5971         free_a_printer(&printer, 2);
5972         free_a_printer(&old_printer, 2);
5973
5974
5975         return result;
5976 }
5977
5978 /****************************************************************************
5979 ****************************************************************************/
5980 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5981                                            struct policy_handle *handle,
5982                                            struct spoolss_SetPrinterInfo7 *info7)
5983 {
5984 #ifdef HAVE_ADS
5985         int snum;
5986         Printer_entry *Printer;
5987
5988         if ( lp_security() != SEC_ADS ) {
5989                 return WERR_UNKNOWN_LEVEL;
5990         }
5991
5992         Printer = find_printer_index_by_hnd(p, handle);
5993
5994         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5995
5996         if (!Printer)
5997                 return WERR_BADFID;
5998
5999         if (!get_printer_snum(p, handle, &snum, NULL))
6000                 return WERR_BADFID;
6001
6002         nt_printer_publish(Printer, snum, info7->action);
6003
6004         return WERR_OK;
6005 #else
6006         return WERR_UNKNOWN_LEVEL;
6007 #endif
6008 }
6009
6010 /****************************************************************
6011  _spoolss_SetPrinter
6012 ****************************************************************/
6013
6014 WERROR _spoolss_SetPrinter(pipes_struct *p,
6015                            struct spoolss_SetPrinter *r)
6016 {
6017         WERROR result;
6018
6019         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6020
6021         if (!Printer) {
6022                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6023                         OUR_HANDLE(r->in.handle)));
6024                 return WERR_BADFID;
6025         }
6026
6027         /* check the level */
6028         switch (r->in.info_ctr->level) {
6029                 case 0:
6030                         return control_printer(r->in.handle, r->in.command, p);
6031                 case 2:
6032                         result = update_printer(p, r->in.handle,
6033                                                 r->in.info_ctr,
6034                                                 r->in.devmode_ctr->devmode);
6035                         if (!W_ERROR_IS_OK(result))
6036                                 return result;
6037                         if (r->in.secdesc_ctr->sd)
6038                                 result = update_printer_sec(r->in.handle, p,
6039                                                             r->in.secdesc_ctr);
6040                         return result;
6041                 case 3:
6042                         return update_printer_sec(r->in.handle, p,
6043                                                   r->in.secdesc_ctr);
6044                 case 7:
6045                         return publish_or_unpublish_printer(p, r->in.handle,
6046                                                             r->in.info_ctr->info.info7);
6047                 default:
6048                         return WERR_UNKNOWN_LEVEL;
6049         }
6050 }
6051
6052 /****************************************************************
6053  _spoolss_FindClosePrinterNotify
6054 ****************************************************************/
6055
6056 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6057                                        struct spoolss_FindClosePrinterNotify *r)
6058 {
6059         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6060
6061         if (!Printer) {
6062                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6063                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6064                 return WERR_BADFID;
6065         }
6066
6067         if (Printer->notify.client_connected == true) {
6068                 int snum = -1;
6069
6070                 if ( Printer->printer_type == SPLHND_SERVER)
6071                         snum = -1;
6072                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6073                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6074                         return WERR_BADFID;
6075
6076                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6077         }
6078
6079         Printer->notify.flags=0;
6080         Printer->notify.options=0;
6081         Printer->notify.localmachine[0]='\0';
6082         Printer->notify.printerlocal=0;
6083         TALLOC_FREE(Printer->notify.option);
6084         Printer->notify.client_connected = false;
6085
6086         return WERR_OK;
6087 }
6088
6089 /****************************************************************
6090  _spoolss_AddJob
6091 ****************************************************************/
6092
6093 WERROR _spoolss_AddJob(pipes_struct *p,
6094                        struct spoolss_AddJob *r)
6095 {
6096         if (!r->in.buffer && (r->in.offered != 0)) {
6097                 return WERR_INVALID_PARAM;
6098         }
6099
6100         /* this is what a NT server returns for AddJob. AddJob must fail on
6101          * non-local printers */
6102
6103         if (r->in.level != 1) {
6104                 return WERR_UNKNOWN_LEVEL;
6105         }
6106
6107         return WERR_INVALID_PARAM;
6108 }
6109
6110 /****************************************************************************
6111 fill_job_info1
6112 ****************************************************************************/
6113
6114 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6115                              struct spoolss_JobInfo1 *r,
6116                              const print_queue_struct *queue,
6117                              int position, int snum,
6118                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6119 {
6120         struct tm *t;
6121
6122         t = gmtime(&queue->time);
6123
6124         r->job_id               = queue->job;
6125
6126         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6127         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6128         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6129         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6130         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6131         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6132         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6133         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6134         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6135         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6136         r->text_status          = talloc_strdup(mem_ctx, "");
6137         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6138
6139         r->status               = nt_printj_status(queue->status);
6140         r->priority             = queue->priority;
6141         r->position             = position;
6142         r->total_pages          = queue->page_count;
6143         r->pages_printed        = 0; /* ??? */
6144
6145         init_systemtime(&r->submitted, t);
6146
6147         return WERR_OK;
6148 }
6149
6150 /****************************************************************************
6151 fill_job_info2
6152 ****************************************************************************/
6153
6154 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6155                              struct spoolss_JobInfo2 *r,
6156                              const print_queue_struct *queue,
6157                              int position, int snum,
6158                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6159                              struct spoolss_DeviceMode *devmode)
6160 {
6161         struct tm *t;
6162
6163         t = gmtime(&queue->time);
6164
6165         r->job_id               = queue->job;
6166
6167         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6168         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6169         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6170         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6171         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6172         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6173         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6174         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6175         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6176         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6177         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6178         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6179         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6180         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6181         r->parameters           = talloc_strdup(mem_ctx, "");
6182         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6183         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6184         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6185
6186         r->devmode              = devmode;
6187
6188         r->text_status          = talloc_strdup(mem_ctx, "");
6189         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6190
6191         r->secdesc              = NULL;
6192
6193         r->status               = nt_printj_status(queue->status);
6194         r->priority             = queue->priority;
6195         r->position             = position;
6196         r->start_time           = 0;
6197         r->until_time           = 0;
6198         r->total_pages          = queue->page_count;
6199         r->size                 = queue->size;
6200         init_systemtime(&r->submitted, t);
6201         r->time                 = 0;
6202         r->pages_printed        = 0; /* ??? */
6203
6204         return WERR_OK;
6205 }
6206
6207 /****************************************************************************
6208  Enumjobs at level 1.
6209 ****************************************************************************/
6210
6211 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6212                               const print_queue_struct *queue,
6213                               uint32_t num_queues, int snum,
6214                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6215                               union spoolss_JobInfo **info_p,
6216                               uint32_t *count)
6217 {
6218         union spoolss_JobInfo *info;
6219         int i;
6220         WERROR result = WERR_OK;
6221
6222         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6223         W_ERROR_HAVE_NO_MEMORY(info);
6224
6225         *count = num_queues;
6226
6227         for (i=0; i<*count; i++) {
6228                 result = fill_job_info1(info,
6229                                         &info[i].info1,
6230                                         &queue[i],
6231                                         i,
6232                                         snum,
6233                                         ntprinter);
6234                 if (!W_ERROR_IS_OK(result)) {
6235                         goto out;
6236                 }
6237         }
6238
6239  out:
6240         if (!W_ERROR_IS_OK(result)) {
6241                 TALLOC_FREE(info);
6242                 *count = 0;
6243                 return result;
6244         }
6245
6246         *info_p = info;
6247
6248         return WERR_OK;
6249 }
6250
6251 /****************************************************************************
6252  Enumjobs at level 2.
6253 ****************************************************************************/
6254
6255 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6256                               const print_queue_struct *queue,
6257                               uint32_t num_queues, int snum,
6258                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6259                               union spoolss_JobInfo **info_p,
6260                               uint32_t *count)
6261 {
6262         union spoolss_JobInfo *info;
6263         int i;
6264         WERROR result = WERR_OK;
6265
6266         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6267         W_ERROR_HAVE_NO_MEMORY(info);
6268
6269         *count = num_queues;
6270
6271         for (i=0; i<*count; i++) {
6272
6273                 struct spoolss_DeviceMode *devmode;
6274
6275                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6276                 if (!devmode) {
6277                         result = WERR_NOMEM;
6278                         goto out;
6279                 }
6280
6281                 result = fill_job_info2(info,
6282                                         &info[i].info2,
6283                                         &queue[i],
6284                                         i,
6285                                         snum,
6286                                         ntprinter,
6287                                         devmode);
6288                 if (!W_ERROR_IS_OK(result)) {
6289                         goto out;
6290                 }
6291         }
6292
6293  out:
6294         if (!W_ERROR_IS_OK(result)) {
6295                 TALLOC_FREE(info);
6296                 *count = 0;
6297                 return result;
6298         }
6299
6300         *info_p = info;
6301
6302         return WERR_OK;
6303 }
6304
6305 /****************************************************************
6306  _spoolss_EnumJobs
6307 ****************************************************************/
6308
6309 WERROR _spoolss_EnumJobs(pipes_struct *p,
6310                          struct spoolss_EnumJobs *r)
6311 {
6312         WERROR result;
6313         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6314         int snum;
6315         print_status_struct prt_status;
6316         print_queue_struct *queue = NULL;
6317         uint32_t count;
6318
6319         /* that's an [in out] buffer */
6320
6321         if (!r->in.buffer && (r->in.offered != 0)) {
6322                 return WERR_INVALID_PARAM;
6323         }
6324
6325         DEBUG(4,("_spoolss_EnumJobs\n"));
6326
6327         *r->out.needed = 0;
6328         *r->out.count = 0;
6329         *r->out.info = NULL;
6330
6331         /* lookup the printer snum and tdb entry */
6332
6333         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6334                 return WERR_BADFID;
6335         }
6336
6337         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6338         if (!W_ERROR_IS_OK(result)) {
6339                 return result;
6340         }
6341
6342         count = print_queue_status(snum, &queue, &prt_status);
6343         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6344                 count, prt_status.status, prt_status.message));
6345
6346         if (count == 0) {
6347                 SAFE_FREE(queue);
6348                 free_a_printer(&ntprinter, 2);
6349                 return WERR_OK;
6350         }
6351
6352         switch (r->in.level) {
6353         case 1:
6354                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6355                                          ntprinter, r->out.info, r->out.count);
6356                 break;
6357         case 2:
6358                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6359                                          ntprinter, r->out.info, r->out.count);
6360                 break;
6361         default:
6362                 result = WERR_UNKNOWN_LEVEL;
6363                 break;
6364         }
6365
6366         SAFE_FREE(queue);
6367         free_a_printer(&ntprinter, 2);
6368
6369         if (!W_ERROR_IS_OK(result)) {
6370                 return result;
6371         }
6372
6373         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6374                                                      spoolss_EnumJobs, NULL,
6375                                                      *r->out.info, r->in.level,
6376                                                      *r->out.count);
6377         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6378         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6379
6380         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6381 }
6382
6383 /****************************************************************
6384  _spoolss_ScheduleJob
6385 ****************************************************************/
6386
6387 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6388                             struct spoolss_ScheduleJob *r)
6389 {
6390         return WERR_OK;
6391 }
6392
6393 /****************************************************************
6394  _spoolss_SetJob
6395 ****************************************************************/
6396
6397 WERROR _spoolss_SetJob(pipes_struct *p,
6398                        struct spoolss_SetJob *r)
6399 {
6400         int snum;
6401         WERROR errcode = WERR_BADFUNC;
6402
6403         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6404                 return WERR_BADFID;
6405         }
6406
6407         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6408                 return WERR_INVALID_PRINTER_NAME;
6409         }
6410
6411         switch (r->in.command) {
6412         case SPOOLSS_JOB_CONTROL_CANCEL:
6413         case SPOOLSS_JOB_CONTROL_DELETE:
6414                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6415                         errcode = WERR_OK;
6416                 }
6417                 break;
6418         case SPOOLSS_JOB_CONTROL_PAUSE:
6419                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6420                         errcode = WERR_OK;
6421                 }
6422                 break;
6423         case SPOOLSS_JOB_CONTROL_RESTART:
6424         case SPOOLSS_JOB_CONTROL_RESUME:
6425                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6426                         errcode = WERR_OK;
6427                 }
6428                 break;
6429         default:
6430                 return WERR_UNKNOWN_LEVEL;
6431         }
6432
6433         return errcode;
6434 }
6435
6436 /****************************************************************************
6437  Enumerates all printer drivers by level and architecture.
6438 ****************************************************************************/
6439
6440 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6441                                                        const char *servername,
6442                                                        const char *architecture,
6443                                                        uint32_t level,
6444                                                        union spoolss_DriverInfo **info_p,
6445                                                        uint32_t *count_p)
6446 {
6447         int i;
6448         int ndrivers;
6449         uint32_t version;
6450         fstring *list = NULL;
6451         union spoolss_DriverInfo *driver;
6452         union spoolss_DriverInfo *info = NULL;
6453         uint32_t count = 0;
6454         WERROR result = WERR_OK;
6455
6456         *count_p = 0;
6457         *info_p = NULL;
6458
6459         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6460                 list = NULL;
6461                 ndrivers = get_ntdrivers(&list, architecture, version);
6462                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6463                         ndrivers, architecture, version));
6464
6465                 if (ndrivers == -1) {
6466                         result = WERR_NOMEM;
6467                         goto out;
6468                 }
6469
6470                 if (ndrivers != 0) {
6471                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6472                                                     union spoolss_DriverInfo,
6473                                                     count + ndrivers);
6474                         if (!info) {
6475                                 DEBUG(0,("enumprinterdrivers_level1: "
6476                                         "failed to enlarge driver info buffer!\n"));
6477                                 result = WERR_NOMEM;
6478                                 goto out;
6479                         }
6480                 }
6481
6482                 for (i=0; i<ndrivers; i++) {
6483                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6484                         ZERO_STRUCT(driver);
6485                         result = get_a_printer_driver(mem_ctx, &driver, 3, list[i],
6486                                                       architecture, version);
6487                         if (!W_ERROR_IS_OK(result)) {
6488                                 goto out;
6489                         }
6490
6491                         switch (level) {
6492                         case 1:
6493                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6494                                                                    &driver->info3, servername,
6495                                                                    architecture);
6496                                 break;
6497                         case 2:
6498                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6499                                                                    &driver->info3, servername);
6500                                 break;
6501                         case 3:
6502                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6503                                                                    &driver->info3, servername);
6504                                 break;
6505                         case 4:
6506                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6507                                                                    &driver->info3, servername);
6508                                 break;
6509                         case 5:
6510                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6511                                                                    &driver->info3, servername);
6512                                 break;
6513                         case 6:
6514                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6515                                                                    &driver->info3, servername);
6516                                 break;
6517                         default:
6518                                 result = WERR_UNKNOWN_LEVEL;
6519                                 break;
6520                         }
6521
6522                         free_a_printer_driver(driver);
6523
6524                         if (!W_ERROR_IS_OK(result)) {
6525                                 goto out;
6526                         }
6527                 }
6528
6529                 count += ndrivers;
6530                 SAFE_FREE(list);
6531         }
6532
6533  out:
6534         SAFE_FREE(list);
6535
6536         if (!W_ERROR_IS_OK(result)) {
6537                 TALLOC_FREE(info);
6538                 return result;
6539         }
6540
6541         *info_p = info;
6542         *count_p = count;
6543
6544         return WERR_OK;
6545 }
6546
6547 /****************************************************************************
6548  Enumerates all printer drivers by level.
6549 ****************************************************************************/
6550
6551 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6552                                        const char *servername,
6553                                        const char *architecture,
6554                                        uint32_t level,
6555                                        union spoolss_DriverInfo **info_p,
6556                                        uint32_t *count_p)
6557 {
6558         uint32_t a,i;
6559         WERROR result = WERR_OK;
6560
6561         if (strequal(architecture, "all")) {
6562
6563                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6564
6565                         union spoolss_DriverInfo *info = NULL;
6566                         uint32_t count = 0;
6567
6568                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6569                                                                           servername,
6570                                                                           archi_table[a].long_archi,
6571                                                                           level,
6572                                                                           &info,
6573                                                                           &count);
6574                         if (!W_ERROR_IS_OK(result)) {
6575                                 continue;
6576                         }
6577
6578                         for (i=0; i < count; i++) {
6579                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6580                                              info[i], info_p, count_p);
6581                         }
6582                 }
6583
6584                 return result;
6585         }
6586
6587         return enumprinterdrivers_level_by_architecture(mem_ctx,
6588                                                         servername,
6589                                                         architecture,
6590                                                         level,
6591                                                         info_p,
6592                                                         count_p);
6593 }
6594
6595 /****************************************************************************
6596  Enumerates all printer drivers at level 1.
6597 ****************************************************************************/
6598
6599 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6600                                         const char *servername,
6601                                         const char *architecture,
6602                                         union spoolss_DriverInfo **info_p,
6603                                         uint32_t *count)
6604 {
6605         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6606                                         info_p, count);
6607 }
6608
6609 /****************************************************************************
6610  Enumerates all printer drivers at level 2.
6611 ****************************************************************************/
6612
6613 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6614                                         const char *servername,
6615                                         const char *architecture,
6616                                         union spoolss_DriverInfo **info_p,
6617                                         uint32_t *count)
6618 {
6619         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6620                                         info_p, count);
6621 }
6622
6623 /****************************************************************************
6624  Enumerates all printer drivers at level 3.
6625 ****************************************************************************/
6626
6627 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6628                                         const char *servername,
6629                                         const char *architecture,
6630                                         union spoolss_DriverInfo **info_p,
6631                                         uint32_t *count)
6632 {
6633         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6634                                         info_p, count);
6635 }
6636
6637 /****************************************************************************
6638  Enumerates all printer drivers at level 4.
6639 ****************************************************************************/
6640
6641 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6642                                         const char *servername,
6643                                         const char *architecture,
6644                                         union spoolss_DriverInfo **info_p,
6645                                         uint32_t *count)
6646 {
6647         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6648                                         info_p, count);
6649 }
6650
6651 /****************************************************************************
6652  Enumerates all printer drivers at level 5.
6653 ****************************************************************************/
6654
6655 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6656                                         const char *servername,
6657                                         const char *architecture,
6658                                         union spoolss_DriverInfo **info_p,
6659                                         uint32_t *count)
6660 {
6661         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6662                                         info_p, count);
6663 }
6664
6665 /****************************************************************************
6666  Enumerates all printer drivers at level 6.
6667 ****************************************************************************/
6668
6669 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6670                                         const char *servername,
6671                                         const char *architecture,
6672                                         union spoolss_DriverInfo **info_p,
6673                                         uint32_t *count)
6674 {
6675         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6676                                         info_p, count);
6677 }
6678
6679
6680 /****************************************************************
6681  _spoolss_EnumPrinterDrivers
6682 ****************************************************************/
6683
6684 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6685                                    struct spoolss_EnumPrinterDrivers *r)
6686 {
6687         const char *cservername;
6688         WERROR result;
6689
6690         /* that's an [in out] buffer */
6691
6692         if (!r->in.buffer && (r->in.offered != 0)) {
6693                 return WERR_INVALID_PARAM;
6694         }
6695
6696         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6697
6698         *r->out.needed = 0;
6699         *r->out.count = 0;
6700         *r->out.info = NULL;
6701
6702         cservername = canon_servername(r->in.server);
6703
6704         if (!is_myname_or_ipaddr(cservername)) {
6705                 return WERR_UNKNOWN_PRINTER_DRIVER;
6706         }
6707
6708         switch (r->in.level) {
6709         case 1:
6710                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6711                                                    r->in.environment,
6712                                                    r->out.info, r->out.count);
6713                 break;
6714         case 2:
6715                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6716                                                    r->in.environment,
6717                                                    r->out.info, r->out.count);
6718                 break;
6719         case 3:
6720                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6721                                                    r->in.environment,
6722                                                    r->out.info, r->out.count);
6723                 break;
6724         case 4:
6725                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6726                                                    r->in.environment,
6727                                                    r->out.info, r->out.count);
6728                 break;
6729         case 5:
6730                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6731                                                    r->in.environment,
6732                                                    r->out.info, r->out.count);
6733                 break;
6734         case 6:
6735                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6736                                                    r->in.environment,
6737                                                    r->out.info, r->out.count);
6738                 break;
6739         default:
6740                 return WERR_UNKNOWN_LEVEL;
6741         }
6742
6743         if (!W_ERROR_IS_OK(result)) {
6744                 return result;
6745         }
6746
6747         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6748                                                      spoolss_EnumPrinterDrivers, NULL,
6749                                                      *r->out.info, r->in.level,
6750                                                      *r->out.count);
6751         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6752         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6753
6754         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6755 }
6756
6757 /****************************************************************************
6758 ****************************************************************************/
6759
6760 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6761                                struct spoolss_FormInfo1 *r,
6762                                const nt_forms_struct *form)
6763 {
6764         r->form_name    = talloc_strdup(mem_ctx, form->name);
6765         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6766
6767         r->flags        = form->flag;
6768         r->size.width   = form->width;
6769         r->size.height  = form->length;
6770         r->area.left    = form->left;
6771         r->area.top     = form->top;
6772         r->area.right   = form->right;
6773         r->area.bottom  = form->bottom;
6774
6775         return WERR_OK;
6776 }
6777
6778 /****************************************************************
6779  spoolss_enumforms_level1
6780 ****************************************************************/
6781
6782 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6783                                        const nt_forms_struct *builtin_forms,
6784                                        uint32_t num_builtin_forms,
6785                                        const nt_forms_struct *user_forms,
6786                                        uint32_t num_user_forms,
6787                                        union spoolss_FormInfo **info_p,
6788                                        uint32_t *count)
6789 {
6790         union spoolss_FormInfo *info;
6791         WERROR result = WERR_OK;
6792         int i;
6793
6794         *count = num_builtin_forms + num_user_forms;
6795
6796         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6797         W_ERROR_HAVE_NO_MEMORY(info);
6798
6799         /* construct the list of form structures */
6800         for (i=0; i<num_builtin_forms; i++) {
6801                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6802                 result = fill_form_info_1(info, &info[i].info1,
6803                                           &builtin_forms[i]);
6804                 if (!W_ERROR_IS_OK(result)) {
6805                         goto out;
6806                 }
6807         }
6808
6809         for (i=0; i<num_user_forms; i++) {
6810                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6811                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6812                                           &user_forms[i]);
6813                 if (!W_ERROR_IS_OK(result)) {
6814                         goto out;
6815                 }
6816         }
6817
6818  out:
6819         if (!W_ERROR_IS_OK(result)) {
6820                 TALLOC_FREE(info);
6821                 *count = 0;
6822                 return result;
6823         }
6824
6825         *info_p = info;
6826
6827         return WERR_OK;
6828 }
6829
6830 /****************************************************************
6831  _spoolss_EnumForms
6832 ****************************************************************/
6833
6834 WERROR _spoolss_EnumForms(pipes_struct *p,
6835                           struct spoolss_EnumForms *r)
6836 {
6837         WERROR result;
6838         nt_forms_struct *user_forms = NULL;
6839         nt_forms_struct *builtin_forms = NULL;
6840         uint32_t num_user_forms;
6841         uint32_t num_builtin_forms;
6842
6843         *r->out.count = 0;
6844         *r->out.needed = 0;
6845         *r->out.info = NULL;
6846
6847         /* that's an [in out] buffer */
6848
6849         if (!r->in.buffer && (r->in.offered != 0) ) {
6850                 return WERR_INVALID_PARAM;
6851         }
6852
6853         DEBUG(4,("_spoolss_EnumForms\n"));
6854         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6855         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6856
6857         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6858         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6859         num_user_forms = get_ntforms(&user_forms);
6860         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6861
6862         if (num_user_forms + num_builtin_forms == 0) {
6863                 SAFE_FREE(builtin_forms);
6864                 SAFE_FREE(user_forms);
6865                 return WERR_NO_MORE_ITEMS;
6866         }
6867
6868         switch (r->in.level) {
6869         case 1:
6870                 result = spoolss_enumforms_level1(p->mem_ctx,
6871                                                   builtin_forms,
6872                                                   num_builtin_forms,
6873                                                   user_forms,
6874                                                   num_user_forms,
6875                                                   r->out.info,
6876                                                   r->out.count);
6877                 break;
6878         default:
6879                 result = WERR_UNKNOWN_LEVEL;
6880                 break;
6881         }
6882
6883         SAFE_FREE(user_forms);
6884         SAFE_FREE(builtin_forms);
6885
6886         if (!W_ERROR_IS_OK(result)) {
6887                 return result;
6888         }
6889
6890         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6891                                                      spoolss_EnumForms, NULL,
6892                                                      *r->out.info, r->in.level,
6893                                                      *r->out.count);
6894         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6895         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6896
6897         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6898 }
6899
6900 /****************************************************************
6901 ****************************************************************/
6902
6903 static WERROR find_form_byname(const char *name,
6904                                nt_forms_struct *form)
6905 {
6906         nt_forms_struct *list = NULL;
6907         int num_forms = 0, i = 0;
6908
6909         if (get_a_builtin_ntform_by_string(name, form)) {
6910                 return WERR_OK;
6911         }
6912
6913         num_forms = get_ntforms(&list);
6914         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6915
6916         if (num_forms == 0) {
6917                 return WERR_BADFID;
6918         }
6919
6920         /* Check if the requested name is in the list of form structures */
6921         for (i = 0; i < num_forms; i++) {
6922
6923                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6924
6925                 if (strequal(name, list[i].name)) {
6926                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6927                         *form = list[i];
6928                         SAFE_FREE(list);
6929                         return WERR_OK;
6930                 }
6931         }
6932
6933         SAFE_FREE(list);
6934
6935         return WERR_BADFID;
6936 }
6937
6938 /****************************************************************
6939  _spoolss_GetForm
6940 ****************************************************************/
6941
6942 WERROR _spoolss_GetForm(pipes_struct *p,
6943                         struct spoolss_GetForm *r)
6944 {
6945         WERROR result;
6946         nt_forms_struct form;
6947
6948         /* that's an [in out] buffer */
6949
6950         if (!r->in.buffer && (r->in.offered != 0)) {
6951                 return WERR_INVALID_PARAM;
6952         }
6953
6954         DEBUG(4,("_spoolss_GetForm\n"));
6955         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6956         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6957
6958         result = find_form_byname(r->in.form_name, &form);
6959         if (!W_ERROR_IS_OK(result)) {
6960                 TALLOC_FREE(r->out.info);
6961                 return result;
6962         }
6963
6964         switch (r->in.level) {
6965         case 1:
6966                 result = fill_form_info_1(p->mem_ctx,
6967                                           &r->out.info->info1,
6968                                           &form);
6969                 break;
6970
6971         default:
6972                 result = WERR_UNKNOWN_LEVEL;
6973                 break;
6974         }
6975
6976         if (!W_ERROR_IS_OK(result)) {
6977                 TALLOC_FREE(r->out.info);
6978                 return result;
6979         }
6980
6981         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6982                                                r->out.info, r->in.level);
6983         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6984
6985         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6986 }
6987
6988 /****************************************************************************
6989 ****************************************************************************/
6990
6991 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6992                           struct spoolss_PortInfo1 *r,
6993                           const char *name)
6994 {
6995         r->port_name = talloc_strdup(mem_ctx, name);
6996         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6997
6998         return WERR_OK;
6999 }
7000
7001 /****************************************************************************
7002  TODO: This probably needs distinguish between TCP/IP and Local ports
7003  somehow.
7004 ****************************************************************************/
7005
7006 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7007                           struct spoolss_PortInfo2 *r,
7008                           const char *name)
7009 {
7010         r->port_name = talloc_strdup(mem_ctx, name);
7011         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7012
7013         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7014         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7015
7016         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7017         W_ERROR_HAVE_NO_MEMORY(r->description);
7018
7019         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7020         r->reserved = 0;
7021
7022         return WERR_OK;
7023 }
7024
7025
7026 /****************************************************************************
7027  wrapper around the enumer ports command
7028 ****************************************************************************/
7029
7030 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7031 {
7032         char *cmd = lp_enumports_cmd();
7033         char **qlines = NULL;
7034         char *command = NULL;
7035         int numlines;
7036         int ret;
7037         int fd;
7038
7039         *count = 0;
7040         *lines = NULL;
7041
7042         /* if no hook then just fill in the default port */
7043
7044         if ( !*cmd ) {
7045                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7046                         return WERR_NOMEM;
7047                 }
7048                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7049                         TALLOC_FREE(qlines);
7050                         return WERR_NOMEM;
7051                 }
7052                 qlines[1] = NULL;
7053                 numlines = 1;
7054         }
7055         else {
7056                 /* we have a valid enumport command */
7057
7058                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7059                 if (!command) {
7060                         return WERR_NOMEM;
7061                 }
7062
7063                 DEBUG(10,("Running [%s]\n", command));
7064                 ret = smbrun(command, &fd);
7065                 DEBUG(10,("Returned [%d]\n", ret));
7066                 TALLOC_FREE(command);
7067                 if (ret != 0) {
7068                         if (fd != -1) {
7069                                 close(fd);
7070                         }
7071                         return WERR_ACCESS_DENIED;
7072                 }
7073
7074                 numlines = 0;
7075                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7076                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7077                 close(fd);
7078         }
7079
7080         *count = numlines;
7081         *lines = qlines;
7082
7083         return WERR_OK;
7084 }
7085
7086 /****************************************************************************
7087  enumports level 1.
7088 ****************************************************************************/
7089
7090 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7091                                 union spoolss_PortInfo **info_p,
7092                                 uint32_t *count)
7093 {
7094         union spoolss_PortInfo *info = NULL;
7095         int i=0;
7096         WERROR result = WERR_OK;
7097         char **qlines = NULL;
7098         int numlines = 0;
7099
7100         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7101         if (!W_ERROR_IS_OK(result)) {
7102                 goto out;
7103         }
7104
7105         if (numlines) {
7106                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7107                 if (!info) {
7108                         DEBUG(10,("Returning WERR_NOMEM\n"));
7109                         result = WERR_NOMEM;
7110                         goto out;
7111                 }
7112
7113                 for (i=0; i<numlines; i++) {
7114                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7115                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7116                         if (!W_ERROR_IS_OK(result)) {
7117                                 goto out;
7118                         }
7119                 }
7120         }
7121         TALLOC_FREE(qlines);
7122
7123 out:
7124         if (!W_ERROR_IS_OK(result)) {
7125                 TALLOC_FREE(info);
7126                 TALLOC_FREE(qlines);
7127                 *count = 0;
7128                 *info_p = NULL;
7129                 return result;
7130         }
7131
7132         *info_p = info;
7133         *count = numlines;
7134
7135         return WERR_OK;
7136 }
7137
7138 /****************************************************************************
7139  enumports level 2.
7140 ****************************************************************************/
7141
7142 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7143                                 union spoolss_PortInfo **info_p,
7144                                 uint32_t *count)
7145 {
7146         union spoolss_PortInfo *info = NULL;
7147         int i=0;
7148         WERROR result = WERR_OK;
7149         char **qlines = NULL;
7150         int numlines = 0;
7151
7152         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7153         if (!W_ERROR_IS_OK(result)) {
7154                 goto out;
7155         }
7156
7157         if (numlines) {
7158                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7159                 if (!info) {
7160                         DEBUG(10,("Returning WERR_NOMEM\n"));
7161                         result = WERR_NOMEM;
7162                         goto out;
7163                 }
7164
7165                 for (i=0; i<numlines; i++) {
7166                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7167                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7168                         if (!W_ERROR_IS_OK(result)) {
7169                                 goto out;
7170                         }
7171                 }
7172         }
7173         TALLOC_FREE(qlines);
7174
7175 out:
7176         if (!W_ERROR_IS_OK(result)) {
7177                 TALLOC_FREE(info);
7178                 TALLOC_FREE(qlines);
7179                 *count = 0;
7180                 *info_p = NULL;
7181                 return result;
7182         }
7183
7184         *info_p = info;
7185         *count = numlines;
7186
7187         return WERR_OK;
7188 }
7189
7190 /****************************************************************
7191  _spoolss_EnumPorts
7192 ****************************************************************/
7193
7194 WERROR _spoolss_EnumPorts(pipes_struct *p,
7195                           struct spoolss_EnumPorts *r)
7196 {
7197         WERROR result;
7198
7199         /* that's an [in out] buffer */
7200
7201         if (!r->in.buffer && (r->in.offered != 0)) {
7202                 return WERR_INVALID_PARAM;
7203         }
7204
7205         DEBUG(4,("_spoolss_EnumPorts\n"));
7206
7207         *r->out.count = 0;
7208         *r->out.needed = 0;
7209         *r->out.info = NULL;
7210
7211         switch (r->in.level) {
7212         case 1:
7213                 result = enumports_level_1(p->mem_ctx, r->out.info,
7214                                            r->out.count);
7215                 break;
7216         case 2:
7217                 result = enumports_level_2(p->mem_ctx, r->out.info,
7218                                            r->out.count);
7219                 break;
7220         default:
7221                 return WERR_UNKNOWN_LEVEL;
7222         }
7223
7224         if (!W_ERROR_IS_OK(result)) {
7225                 return result;
7226         }
7227
7228         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7229                                                      spoolss_EnumPorts, NULL,
7230                                                      *r->out.info, r->in.level,
7231                                                      *r->out.count);
7232         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7233         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7234
7235         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7236 }
7237
7238 /****************************************************************************
7239 ****************************************************************************/
7240
7241 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7242                                            const char *server,
7243                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7244                                            struct spoolss_DeviceMode *devmode,
7245                                            struct security_descriptor *sec_desc,
7246                                            struct spoolss_UserLevelCtr *user_ctr,
7247                                            struct policy_handle *handle)
7248 {
7249         NT_PRINTER_INFO_LEVEL *printer = NULL;
7250         fstring name;
7251         int     snum;
7252         WERROR err = WERR_OK;
7253
7254         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7255                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7256                 return WERR_NOMEM;
7257         }
7258
7259         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7260         if (!convert_printer_info(info_ctr, printer)) {
7261                 free_a_printer(&printer, 2);
7262                 return WERR_NOMEM;
7263         }
7264
7265         /* check to see if the printer already exists */
7266
7267         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7268                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7269                         printer->info_2->sharename));
7270                 free_a_printer(&printer, 2);
7271                 return WERR_PRINTER_ALREADY_EXISTS;
7272         }
7273
7274         /* FIXME!!!  smbd should check to see if the driver is installed before
7275            trying to add a printer like this  --jerry */
7276
7277         if (*lp_addprinter_cmd() ) {
7278                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7279                                        printer) ) {
7280                         free_a_printer(&printer,2);
7281                         return WERR_ACCESS_DENIED;
7282                 }
7283         } else {
7284                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7285                         "smb.conf parameter \"addprinter command\" is defined. This"
7286                         "parameter must exist for this call to succeed\n",
7287                         printer->info_2->sharename ));
7288         }
7289
7290         /* use our primary netbios name since get_a_printer() will convert
7291            it to what the client expects on a case by case basis */
7292
7293         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7294              printer->info_2->sharename);
7295
7296
7297         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7298                 free_a_printer(&printer,2);
7299                 return WERR_ACCESS_DENIED;
7300         }
7301
7302         /* you must be a printer admin to add a new printer */
7303         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7304                 free_a_printer(&printer,2);
7305                 return WERR_ACCESS_DENIED;
7306         }
7307
7308         /*
7309          * Do sanity check on the requested changes for Samba.
7310          */
7311
7312         if (!check_printer_ok(printer->info_2, snum)) {
7313                 free_a_printer(&printer,2);
7314                 return WERR_INVALID_PARAM;
7315         }
7316
7317         /*
7318          * When a printer is created, the drivername bound to the printer is used
7319          * to lookup previously saved driver initialization info, which is then
7320          * bound to the new printer, simulating what happens in the Windows arch.
7321          */
7322
7323         if (!devmode)
7324         {
7325                 set_driver_init(printer, 2);
7326         }
7327         else
7328         {
7329                 /* A valid devmode was included, convert and link it
7330                 */
7331                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7332
7333                 if (!convert_devicemode(printer->info_2->printername, devmode,
7334                                         &printer->info_2->devmode)) {
7335                         return  WERR_NOMEM;
7336                 }
7337         }
7338
7339         /* write the ASCII on disk */
7340         err = mod_a_printer(printer, 2);
7341         if (!W_ERROR_IS_OK(err)) {
7342                 free_a_printer(&printer,2);
7343                 return err;
7344         }
7345
7346         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7347                 /* Handle open failed - remove addition. */
7348                 del_a_printer(printer->info_2->sharename);
7349                 free_a_printer(&printer,2);
7350                 ZERO_STRUCTP(handle);
7351                 return WERR_ACCESS_DENIED;
7352         }
7353
7354         update_c_setprinter(false);
7355         free_a_printer(&printer,2);
7356
7357         return WERR_OK;
7358 }
7359
7360 /****************************************************************
7361  _spoolss_AddPrinterEx
7362 ****************************************************************/
7363
7364 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7365                              struct spoolss_AddPrinterEx *r)
7366 {
7367         switch (r->in.info_ctr->level) {
7368         case 1:
7369                 /* we don't handle yet */
7370                 /* but I know what to do ... */
7371                 return WERR_UNKNOWN_LEVEL;
7372         case 2:
7373                 return spoolss_addprinterex_level_2(p, r->in.server,
7374                                                     r->in.info_ctr,
7375                                                     r->in.devmode_ctr->devmode,
7376                                                     r->in.secdesc_ctr->sd,
7377                                                     r->in.userlevel_ctr,
7378                                                     r->out.handle);
7379         default:
7380                 return WERR_UNKNOWN_LEVEL;
7381         }
7382 }
7383
7384 /****************************************************************
7385  _spoolss_AddPrinter
7386 ****************************************************************/
7387
7388 WERROR _spoolss_AddPrinter(pipes_struct *p,
7389                            struct spoolss_AddPrinter *r)
7390 {
7391         struct spoolss_AddPrinterEx a;
7392         struct spoolss_UserLevelCtr userlevel_ctr;
7393
7394         ZERO_STRUCT(userlevel_ctr);
7395
7396         userlevel_ctr.level = 1;
7397
7398         a.in.server             = r->in.server;
7399         a.in.info_ctr           = r->in.info_ctr;
7400         a.in.devmode_ctr        = r->in.devmode_ctr;
7401         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7402         a.in.userlevel_ctr      = &userlevel_ctr;
7403         a.out.handle            = r->out.handle;
7404
7405         return _spoolss_AddPrinterEx(p, &a);
7406 }
7407
7408 /****************************************************************
7409  _spoolss_AddPrinterDriver
7410 ****************************************************************/
7411
7412 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7413                                  struct spoolss_AddPrinterDriver *r)
7414 {
7415         WERROR err = WERR_OK;
7416         char *driver_name = NULL;
7417         uint32_t version;
7418         const char *fn;
7419
7420         switch (p->hdr_req.opnum) {
7421                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7422                         fn = "_spoolss_AddPrinterDriver";
7423                         break;
7424                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7425                         fn = "_spoolss_AddPrinterDriverEx";
7426                         break;
7427                 default:
7428                         return WERR_INVALID_PARAM;
7429         }
7430
7431
7432         /* FIXME */
7433         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7434                 /* Clever hack from Martin Zielinski <mz@seh.de>
7435                  * to allow downgrade from level 8 (Vista).
7436                  */
7437                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7438                         r->in.info_ctr->level));
7439                 return WERR_UNKNOWN_LEVEL;
7440         }
7441
7442         DEBUG(5,("Cleaning driver's information\n"));
7443         err = clean_up_driver_struct(p, r->in.info_ctr);
7444         if (!W_ERROR_IS_OK(err))
7445                 goto done;
7446
7447         DEBUG(5,("Moving driver to final destination\n"));
7448         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7449                                                               &err)) ) {
7450                 goto done;
7451         }
7452
7453         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7454                 err = WERR_ACCESS_DENIED;
7455                 goto done;
7456         }
7457
7458         /*
7459          * I think this is where he DrvUpgradePrinter() hook would be
7460          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7461          * server.  Right now, we just need to send ourselves a message
7462          * to update each printer bound to this driver.   --jerry
7463          */
7464
7465         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7466                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7467                         fn, driver_name));
7468         }
7469
7470         /*
7471          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7472          * decide if the driver init data should be deleted. The rules are:
7473          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7474          *  2) delete init data only if there is no 2k/Xp driver
7475          *  3) always delete init data
7476          * The generalized rule is always use init data from the highest order driver.
7477          * It is necessary to follow the driver install by an initialization step to
7478          * finish off this process.
7479         */
7480
7481         switch (version) {
7482                 /*
7483                  * 9x printer driver - never delete init data
7484                 */
7485                 case 0:
7486                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7487                                 fn, driver_name));
7488                         break;
7489
7490                 /*
7491                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7492                  * there is no 2k/Xp driver init data for this driver name.
7493                 */
7494                 case 2:
7495                 {
7496                         union spoolss_DriverInfo *driver1;
7497
7498                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, 3, driver_name, "Windows NT x86", 3))) {
7499                                 /*
7500                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7501                                 */
7502                                 if (!del_driver_init(driver_name))
7503                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7504                                                 fn, driver_name));
7505                         } else {
7506                                 /*
7507                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7508                                 */
7509                                 free_a_printer_driver(driver1);
7510                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7511                                         fn, driver_name));
7512                         }
7513                 }
7514                 break;
7515
7516                 /*
7517                  * 2k or Xp printer driver - always delete init data
7518                 */
7519                 case 3:
7520                         if (!del_driver_init(driver_name))
7521                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7522                                         fn, driver_name));
7523                         break;
7524
7525                 default:
7526                         DEBUG(0,("%s: invalid level=%d\n", fn,
7527                                 r->in.info_ctr->level));
7528                         break;
7529         }
7530
7531
7532 done:
7533         return err;
7534 }
7535
7536 /****************************************************************
7537  _spoolss_AddPrinterDriverEx
7538 ****************************************************************/
7539
7540 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7541                                    struct spoolss_AddPrinterDriverEx *r)
7542 {
7543         struct spoolss_AddPrinterDriver a;
7544
7545         /*
7546          * we only support the semantics of AddPrinterDriver()
7547          * i.e. only copy files that are newer than existing ones
7548          */
7549
7550         if (r->in.flags != APD_COPY_NEW_FILES) {
7551                 return WERR_ACCESS_DENIED;
7552         }
7553
7554         a.in.servername         = r->in.servername;
7555         a.in.info_ctr           = r->in.info_ctr;
7556
7557         return _spoolss_AddPrinterDriver(p, &a);
7558 }
7559
7560 /****************************************************************************
7561 ****************************************************************************/
7562
7563 struct _spoolss_paths {
7564         int type;
7565         const char *share;
7566         const char *dir;
7567 };
7568
7569 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7570
7571 static const struct _spoolss_paths spoolss_paths[]= {
7572         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7573         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7574 };
7575
7576 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7577                                           const char *servername,
7578                                           const char *environment,
7579                                           int component,
7580                                           char **path)
7581 {
7582         const char *pservername = NULL;
7583         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7584         const char *short_archi;
7585
7586         *path = NULL;
7587
7588         /* environment may be empty */
7589         if (environment && strlen(environment)) {
7590                 long_archi = environment;
7591         }
7592
7593         /* servername may be empty */
7594         if (servername && strlen(servername)) {
7595                 pservername = canon_servername(servername);
7596
7597                 if (!is_myname_or_ipaddr(pservername)) {
7598                         return WERR_INVALID_PARAM;
7599                 }
7600         }
7601
7602         if (!(short_archi = get_short_archi(long_archi))) {
7603                 return WERR_INVALID_ENVIRONMENT;
7604         }
7605
7606         switch (component) {
7607         case SPOOLSS_PRTPROCS_PATH:
7608         case SPOOLSS_DRIVER_PATH:
7609                 if (pservername) {
7610                         *path = talloc_asprintf(mem_ctx,
7611                                         "\\\\%s\\%s\\%s",
7612                                         pservername,
7613                                         spoolss_paths[component].share,
7614                                         short_archi);
7615                 } else {
7616                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7617                                         SPOOLSS_DEFAULT_SERVER_PATH,
7618                                         spoolss_paths[component].dir,
7619                                         short_archi);
7620                 }
7621                 break;
7622         default:
7623                 return WERR_INVALID_PARAM;
7624         }
7625
7626         if (!*path) {
7627                 return WERR_NOMEM;
7628         }
7629
7630         return WERR_OK;
7631 }
7632
7633 /****************************************************************************
7634 ****************************************************************************/
7635
7636 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7637                                           const char *servername,
7638                                           const char *environment,
7639                                           struct spoolss_DriverDirectoryInfo1 *r)
7640 {
7641         WERROR werr;
7642         char *path = NULL;
7643
7644         werr = compose_spoolss_server_path(mem_ctx,
7645                                            servername,
7646                                            environment,
7647                                            SPOOLSS_DRIVER_PATH,
7648                                            &path);
7649         if (!W_ERROR_IS_OK(werr)) {
7650                 return werr;
7651         }
7652
7653         DEBUG(4,("printer driver directory: [%s]\n", path));
7654
7655         r->directory_name = path;
7656
7657         return WERR_OK;
7658 }
7659
7660 /****************************************************************
7661  _spoolss_GetPrinterDriverDirectory
7662 ****************************************************************/
7663
7664 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7665                                           struct spoolss_GetPrinterDriverDirectory *r)
7666 {
7667         WERROR werror;
7668
7669         /* that's an [in out] buffer */
7670
7671         if (!r->in.buffer && (r->in.offered != 0)) {
7672                 return WERR_INVALID_PARAM;
7673         }
7674
7675         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7676                 r->in.level));
7677
7678         *r->out.needed = 0;
7679
7680         /* r->in.level is ignored */
7681
7682         werror = getprinterdriverdir_level_1(p->mem_ctx,
7683                                              r->in.server,
7684                                              r->in.environment,
7685                                              &r->out.info->info1);
7686         if (!W_ERROR_IS_OK(werror)) {
7687                 TALLOC_FREE(r->out.info);
7688                 return werror;
7689         }
7690
7691         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7692                                                r->out.info, r->in.level);
7693         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7694
7695         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7696 }
7697
7698 /****************************************************************
7699  _spoolss_EnumPrinterData
7700 ****************************************************************/
7701
7702 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7703                                 struct spoolss_EnumPrinterData *r)
7704 {
7705         NT_PRINTER_INFO_LEVEL *printer = NULL;
7706         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7707         int             snum;
7708         WERROR          result;
7709         struct regval_blob      *val = NULL;
7710         NT_PRINTER_DATA *p_data;
7711         int             i, key_index, num_values;
7712         int             name_length;
7713
7714         *r->out.value_needed    = 0;
7715         *r->out.type            = REG_NONE;
7716         *r->out.data_needed     = 0;
7717
7718         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7719
7720         if (!Printer) {
7721                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7722                         OUR_HANDLE(r->in.handle)));
7723                 return WERR_BADFID;
7724         }
7725
7726         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7727                 return WERR_BADFID;
7728         }
7729
7730         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7731         if (!W_ERROR_IS_OK(result)) {
7732                 return result;
7733         }
7734
7735         p_data = printer->info_2->data;
7736         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7737
7738         result = WERR_OK;
7739
7740         /*
7741          * The NT machine wants to know the biggest size of value and data
7742          *
7743          * cf: MSDN EnumPrinterData remark section
7744          */
7745
7746         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7747
7748                 uint32_t biggest_valuesize = 0;
7749                 uint32_t biggest_datasize = 0;
7750
7751                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7752
7753                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7754
7755                 for ( i=0; i<num_values; i++ )
7756                 {
7757                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7758
7759                         name_length = strlen(val->valuename);
7760                         if ( strlen(val->valuename) > biggest_valuesize )
7761                                 biggest_valuesize = name_length;
7762
7763                         if ( val->size > biggest_datasize )
7764                                 biggest_datasize = val->size;
7765
7766                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7767                                 biggest_datasize));
7768                 }
7769
7770                 /* the value is an UNICODE string but real_value_size is the length
7771                    in bytes including the trailing 0 */
7772
7773                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7774                 *r->out.data_needed  = biggest_datasize;
7775
7776                 DEBUG(6,("final values: [%d], [%d]\n",
7777                         *r->out.value_needed, *r->out.data_needed));
7778
7779                 goto done;
7780         }
7781
7782         /*
7783          * the value len is wrong in NT sp3
7784          * that's the number of bytes not the number of unicode chars
7785          */
7786
7787         if (key_index != -1) {
7788                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7789                                                 r->in.enum_index);
7790         }
7791
7792         if (!val) {
7793
7794                 /* out_value should default to "" or else NT4 has
7795                    problems unmarshalling the response */
7796
7797                 if (r->in.value_offered) {
7798                         *r->out.value_needed = 1;
7799                         r->out.value_name = talloc_strdup(r, "");
7800                         if (!r->out.value_name) {
7801                                 result = WERR_NOMEM;
7802                                 goto done;
7803                         }
7804                 } else {
7805                         r->out.value_name = NULL;
7806                         *r->out.value_needed = 0;
7807                 }
7808
7809                 /* the data is counted in bytes */
7810
7811                 *r->out.data_needed = r->in.data_offered;
7812
7813                 result = WERR_NO_MORE_ITEMS;
7814         } else {
7815                 /*
7816                  * the value is:
7817                  * - counted in bytes in the request
7818                  * - counted in UNICODE chars in the max reply
7819                  * - counted in bytes in the real size
7820                  *
7821                  * take a pause *before* coding not *during* coding
7822                  */
7823
7824                 /* name */
7825                 if (r->in.value_offered) {
7826                         r->out.value_name = talloc_strdup(r, regval_name(val));
7827                         if (!r->out.value_name) {
7828                                 result = WERR_NOMEM;
7829                                 goto done;
7830                         }
7831                         *r->out.value_needed = strlen_m(regval_name(val));
7832                 } else {
7833                         r->out.value_name = NULL;
7834                         *r->out.value_needed = 0;
7835                 }
7836
7837                 /* type */
7838
7839                 *r->out.type = regval_type(val);
7840
7841                 /* data - counted in bytes */
7842
7843                 if (r->out.data && regval_size(val)) {
7844                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
7845                 }
7846
7847                 *r->out.data_needed = regval_size(val);
7848         }
7849
7850 done:
7851         free_a_printer(&printer, 2);
7852         return result;
7853 }
7854
7855 /****************************************************************
7856  _spoolss_SetPrinterData
7857 ****************************************************************/
7858
7859 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7860                                struct spoolss_SetPrinterData *r)
7861 {
7862         struct spoolss_SetPrinterDataEx r2;
7863
7864         r2.in.handle            = r->in.handle;
7865         r2.in.key_name          = "PrinterDriverData";
7866         r2.in.value_name        = r->in.value_name;
7867         r2.in.type              = r->in.type;
7868         r2.in.data              = r->in.data;
7869         r2.in._offered          = r->in._offered;
7870
7871         return _spoolss_SetPrinterDataEx(p, &r2);
7872 }
7873
7874 /****************************************************************
7875  _spoolss_ResetPrinter
7876 ****************************************************************/
7877
7878 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7879                              struct spoolss_ResetPrinter *r)
7880 {
7881         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7882         int             snum;
7883
7884         DEBUG(5,("_spoolss_ResetPrinter\n"));
7885
7886         /*
7887          * All we do is to check to see if the handle and queue is valid.
7888          * This call really doesn't mean anything to us because we only
7889          * support RAW printing.   --jerry
7890          */
7891
7892         if (!Printer) {
7893                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7894                         OUR_HANDLE(r->in.handle)));
7895                 return WERR_BADFID;
7896         }
7897
7898         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7899                 return WERR_BADFID;
7900
7901
7902         /* blindly return success */
7903         return WERR_OK;
7904 }
7905
7906 /****************************************************************
7907  _spoolss_DeletePrinterData
7908 ****************************************************************/
7909
7910 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7911                                   struct spoolss_DeletePrinterData *r)
7912 {
7913         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7914         int             snum=0;
7915         WERROR          status = WERR_OK;
7916         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7917
7918         DEBUG(5,("_spoolss_DeletePrinterData\n"));
7919
7920         if (!Printer) {
7921                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7922                         OUR_HANDLE(r->in.handle)));
7923                 return WERR_BADFID;
7924         }
7925
7926         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7927                 return WERR_BADFID;
7928
7929         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7930                 DEBUG(3, ("_spoolss_DeletePrinterData: "
7931                         "printer properties change denied by handle\n"));
7932                 return WERR_ACCESS_DENIED;
7933         }
7934
7935         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7936         if (!W_ERROR_IS_OK(status))
7937                 return status;
7938
7939         if (!r->in.value_name) {
7940                 free_a_printer(&printer, 2);
7941                 return WERR_NOMEM;
7942         }
7943
7944         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
7945                                         r->in.value_name );
7946
7947         if ( W_ERROR_IS_OK(status) )
7948                 mod_a_printer( printer, 2 );
7949
7950         free_a_printer(&printer, 2);
7951
7952         return status;
7953 }
7954
7955 /****************************************************************
7956  _spoolss_AddForm
7957 ****************************************************************/
7958
7959 WERROR _spoolss_AddForm(pipes_struct *p,
7960                         struct spoolss_AddForm *r)
7961 {
7962         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7963         nt_forms_struct tmpForm;
7964         int snum = -1;
7965         WERROR status = WERR_OK;
7966         NT_PRINTER_INFO_LEVEL *printer = NULL;
7967         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7968
7969         int count=0;
7970         nt_forms_struct *list=NULL;
7971         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7972
7973         DEBUG(5,("_spoolss_AddForm\n"));
7974
7975         if (!Printer) {
7976                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7977                         OUR_HANDLE(r->in.handle)));
7978                 return WERR_BADFID;
7979         }
7980
7981
7982         /* forms can be added on printer of on the print server handle */
7983
7984         if ( Printer->printer_type == SPLHND_PRINTER )
7985         {
7986                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7987                         return WERR_BADFID;
7988
7989                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7990                 if (!W_ERROR_IS_OK(status))
7991                         goto done;
7992         }
7993
7994         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7995            and not a printer admin, then fail */
7996
7997         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7998              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7999              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8000                                           NULL, NULL,
8001                                           p->server_info->ptok,
8002                                           lp_printer_admin(snum))) {
8003                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8004                 return WERR_ACCESS_DENIED;
8005         }
8006
8007         /* can't add if builtin */
8008
8009         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8010                 status = WERR_FILE_EXISTS;
8011                 goto done;
8012         }
8013
8014         count = get_ntforms(&list);
8015
8016         if(!add_a_form(&list, form, &count)) {
8017                 status =  WERR_NOMEM;
8018                 goto done;
8019         }
8020
8021         become_root();
8022         write_ntforms(&list, count);
8023         unbecome_root();
8024
8025         /*
8026          * ChangeID must always be set if this is a printer
8027          */
8028
8029         if ( Printer->printer_type == SPLHND_PRINTER )
8030                 status = mod_a_printer(printer, 2);
8031
8032 done:
8033         if ( printer )
8034                 free_a_printer(&printer, 2);
8035         SAFE_FREE(list);
8036
8037         return status;
8038 }
8039
8040 /****************************************************************
8041  _spoolss_DeleteForm
8042 ****************************************************************/
8043
8044 WERROR _spoolss_DeleteForm(pipes_struct *p,
8045                            struct spoolss_DeleteForm *r)
8046 {
8047         const char *form_name = r->in.form_name;
8048         nt_forms_struct tmpForm;
8049         int count=0;
8050         nt_forms_struct *list=NULL;
8051         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8052         int snum = -1;
8053         WERROR status = WERR_OK;
8054         NT_PRINTER_INFO_LEVEL *printer = NULL;
8055         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8056         bool ret = false;
8057
8058         DEBUG(5,("_spoolss_DeleteForm\n"));
8059
8060         if (!Printer) {
8061                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8062                         OUR_HANDLE(r->in.handle)));
8063                 return WERR_BADFID;
8064         }
8065
8066         /* forms can be deleted on printer of on the print server handle */
8067
8068         if ( Printer->printer_type == SPLHND_PRINTER )
8069         {
8070                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8071                         return WERR_BADFID;
8072
8073                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8074                 if (!W_ERROR_IS_OK(status))
8075                         goto done;
8076         }
8077
8078         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8079              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8080              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8081                                           NULL, NULL,
8082                                           p->server_info->ptok,
8083                                           lp_printer_admin(snum))) {
8084                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8085                 return WERR_ACCESS_DENIED;
8086         }
8087
8088
8089         /* can't delete if builtin */
8090
8091         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8092                 status = WERR_INVALID_PARAM;
8093                 goto done;
8094         }
8095
8096         count = get_ntforms(&list);
8097
8098         become_root();
8099         ret = delete_a_form(&list, form_name, &count, &status);
8100         unbecome_root();
8101         if (ret == false) {
8102                 goto done;
8103         }
8104
8105         /*
8106          * ChangeID must always be set if this is a printer
8107          */
8108
8109         if ( Printer->printer_type == SPLHND_PRINTER )
8110                 status = mod_a_printer(printer, 2);
8111
8112 done:
8113         if ( printer )
8114                 free_a_printer(&printer, 2);
8115         SAFE_FREE(list);
8116
8117         return status;
8118 }
8119
8120 /****************************************************************
8121  _spoolss_SetForm
8122 ****************************************************************/
8123
8124 WERROR _spoolss_SetForm(pipes_struct *p,
8125                         struct spoolss_SetForm *r)
8126 {
8127         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8128         nt_forms_struct tmpForm;
8129         int snum = -1;
8130         WERROR status = WERR_OK;
8131         NT_PRINTER_INFO_LEVEL *printer = NULL;
8132         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8133
8134         int count=0;
8135         nt_forms_struct *list=NULL;
8136         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8137
8138         DEBUG(5,("_spoolss_SetForm\n"));
8139
8140         if (!Printer) {
8141                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8142                         OUR_HANDLE(r->in.handle)));
8143                 return WERR_BADFID;
8144         }
8145
8146         /* forms can be modified on printer of on the print server handle */
8147
8148         if ( Printer->printer_type == SPLHND_PRINTER )
8149         {
8150                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8151                         return WERR_BADFID;
8152
8153                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8154                 if (!W_ERROR_IS_OK(status))
8155                         goto done;
8156         }
8157
8158         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8159            and not a printer admin, then fail */
8160
8161         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8162              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8163              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8164                                           NULL, NULL,
8165                                           p->server_info->ptok,
8166                                           lp_printer_admin(snum))) {
8167                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8168                 return WERR_ACCESS_DENIED;
8169         }
8170
8171         /* can't set if builtin */
8172         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8173                 status = WERR_INVALID_PARAM;
8174                 goto done;
8175         }
8176
8177         count = get_ntforms(&list);
8178         update_a_form(&list, form, count);
8179         become_root();
8180         write_ntforms(&list, count);
8181         unbecome_root();
8182
8183         /*
8184          * ChangeID must always be set if this is a printer
8185          */
8186
8187         if ( Printer->printer_type == SPLHND_PRINTER )
8188                 status = mod_a_printer(printer, 2);
8189
8190
8191 done:
8192         if ( printer )
8193                 free_a_printer(&printer, 2);
8194         SAFE_FREE(list);
8195
8196         return status;
8197 }
8198
8199 /****************************************************************************
8200  fill_print_processor1
8201 ****************************************************************************/
8202
8203 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8204                                     struct spoolss_PrintProcessorInfo1 *r,
8205                                     const char *print_processor_name)
8206 {
8207         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8208         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8209
8210         return WERR_OK;
8211 }
8212
8213 /****************************************************************************
8214  enumprintprocessors level 1.
8215 ****************************************************************************/
8216
8217 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8218                                           union spoolss_PrintProcessorInfo **info_p,
8219                                           uint32_t *count)
8220 {
8221         union spoolss_PrintProcessorInfo *info;
8222         WERROR result;
8223
8224         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8225         W_ERROR_HAVE_NO_MEMORY(info);
8226
8227         *count = 1;
8228
8229         result = fill_print_processor1(info, &info[0].info1, "winprint");
8230         if (!W_ERROR_IS_OK(result)) {
8231                 goto out;
8232         }
8233
8234  out:
8235         if (!W_ERROR_IS_OK(result)) {
8236                 TALLOC_FREE(info);
8237                 *count = 0;
8238                 return result;
8239         }
8240
8241         *info_p = info;
8242
8243         return WERR_OK;
8244 }
8245
8246 /****************************************************************
8247  _spoolss_EnumPrintProcessors
8248 ****************************************************************/
8249
8250 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8251                                     struct spoolss_EnumPrintProcessors *r)
8252 {
8253         WERROR result;
8254
8255         /* that's an [in out] buffer */
8256
8257         if (!r->in.buffer && (r->in.offered != 0)) {
8258                 return WERR_INVALID_PARAM;
8259         }
8260
8261         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8262
8263         /*
8264          * Enumerate the print processors ...
8265          *
8266          * Just reply with "winprint", to keep NT happy
8267          * and I can use my nice printer checker.
8268          */
8269
8270         *r->out.count = 0;
8271         *r->out.needed = 0;
8272         *r->out.info = NULL;
8273
8274         switch (r->in.level) {
8275         case 1:
8276                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8277                                                      r->out.count);
8278                 break;
8279         default:
8280                 return WERR_UNKNOWN_LEVEL;
8281         }
8282
8283         if (!W_ERROR_IS_OK(result)) {
8284                 return result;
8285         }
8286
8287         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8288                                                      spoolss_EnumPrintProcessors, NULL,
8289                                                      *r->out.info, r->in.level,
8290                                                      *r->out.count);
8291         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8292         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8293
8294         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8295 }
8296
8297 /****************************************************************************
8298  fill_printprocdatatype1
8299 ****************************************************************************/
8300
8301 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8302                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8303                                       const char *name_array)
8304 {
8305         r->name_array = talloc_strdup(mem_ctx, name_array);
8306         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8307
8308         return WERR_OK;
8309 }
8310
8311 /****************************************************************************
8312  enumprintprocdatatypes level 1.
8313 ****************************************************************************/
8314
8315 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8316                                              union spoolss_PrintProcDataTypesInfo **info_p,
8317                                              uint32_t *count)
8318 {
8319         WERROR result;
8320         union spoolss_PrintProcDataTypesInfo *info;
8321
8322         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8323         W_ERROR_HAVE_NO_MEMORY(info);
8324
8325         *count = 1;
8326
8327         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8328         if (!W_ERROR_IS_OK(result)) {
8329                 goto out;
8330         }
8331
8332  out:
8333         if (!W_ERROR_IS_OK(result)) {
8334                 TALLOC_FREE(info);
8335                 *count = 0;
8336                 return result;
8337         }
8338
8339         *info_p = info;
8340
8341         return WERR_OK;
8342 }
8343
8344 /****************************************************************
8345  _spoolss_EnumPrintProcDataTypes
8346 ****************************************************************/
8347
8348 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8349                                        struct spoolss_EnumPrintProcDataTypes *r)
8350 {
8351         WERROR result;
8352
8353         /* that's an [in out] buffer */
8354
8355         if (!r->in.buffer && (r->in.offered != 0)) {
8356                 return WERR_INVALID_PARAM;
8357         }
8358
8359         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8360
8361         *r->out.count = 0;
8362         *r->out.needed = 0;
8363         *r->out.info = NULL;
8364
8365         switch (r->in.level) {
8366         case 1:
8367                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8368                                                         r->out.count);
8369                 break;
8370         default:
8371                 return WERR_UNKNOWN_LEVEL;
8372         }
8373
8374         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8375                                                      spoolss_EnumPrintProcDataTypes, NULL,
8376                                                      *r->out.info, r->in.level,
8377                                                      *r->out.count);
8378         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8379         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8380
8381         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8382 }
8383
8384 /****************************************************************************
8385  fill_monitor_1
8386 ****************************************************************************/
8387
8388 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8389                              struct spoolss_MonitorInfo1 *r,
8390                              const char *monitor_name)
8391 {
8392         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8393         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8394
8395         return WERR_OK;
8396 }
8397
8398 /****************************************************************************
8399  fill_monitor_2
8400 ****************************************************************************/
8401
8402 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8403                              struct spoolss_MonitorInfo2 *r,
8404                              const char *monitor_name,
8405                              const char *environment,
8406                              const char *dll_name)
8407 {
8408         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8409         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8410         r->environment                  = talloc_strdup(mem_ctx, environment);
8411         W_ERROR_HAVE_NO_MEMORY(r->environment);
8412         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8413         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8414
8415         return WERR_OK;
8416 }
8417
8418 /****************************************************************************
8419  enumprintmonitors level 1.
8420 ****************************************************************************/
8421
8422 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8423                                         union spoolss_MonitorInfo **info_p,
8424                                         uint32_t *count)
8425 {
8426         union spoolss_MonitorInfo *info;
8427         WERROR result = WERR_OK;
8428
8429         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8430         W_ERROR_HAVE_NO_MEMORY(info);
8431
8432         *count = 2;
8433
8434         result = fill_monitor_1(info, &info[0].info1,
8435                                 SPL_LOCAL_PORT);
8436         if (!W_ERROR_IS_OK(result)) {
8437                 goto out;
8438         }
8439
8440         result = fill_monitor_1(info, &info[1].info1,
8441                                 SPL_TCPIP_PORT);
8442         if (!W_ERROR_IS_OK(result)) {
8443                 goto out;
8444         }
8445
8446 out:
8447         if (!W_ERROR_IS_OK(result)) {
8448                 TALLOC_FREE(info);
8449                 *count = 0;
8450                 return result;
8451         }
8452
8453         *info_p = info;
8454
8455         return WERR_OK;
8456 }
8457
8458 /****************************************************************************
8459  enumprintmonitors level 2.
8460 ****************************************************************************/
8461
8462 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8463                                         union spoolss_MonitorInfo **info_p,
8464                                         uint32_t *count)
8465 {
8466         union spoolss_MonitorInfo *info;
8467         WERROR result = WERR_OK;
8468
8469         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8470         W_ERROR_HAVE_NO_MEMORY(info);
8471
8472         *count = 2;
8473
8474         result = fill_monitor_2(info, &info[0].info2,
8475                                 SPL_LOCAL_PORT,
8476                                 "Windows NT X86", /* FIXME */
8477                                 "localmon.dll");
8478         if (!W_ERROR_IS_OK(result)) {
8479                 goto out;
8480         }
8481
8482         result = fill_monitor_2(info, &info[1].info2,
8483                                 SPL_TCPIP_PORT,
8484                                 "Windows NT X86", /* FIXME */
8485                                 "tcpmon.dll");
8486         if (!W_ERROR_IS_OK(result)) {
8487                 goto out;
8488         }
8489
8490 out:
8491         if (!W_ERROR_IS_OK(result)) {
8492                 TALLOC_FREE(info);
8493                 *count = 0;
8494                 return result;
8495         }
8496
8497         *info_p = info;
8498
8499         return WERR_OK;
8500 }
8501
8502 /****************************************************************
8503  _spoolss_EnumMonitors
8504 ****************************************************************/
8505
8506 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8507                              struct spoolss_EnumMonitors *r)
8508 {
8509         WERROR result;
8510
8511         /* that's an [in out] buffer */
8512
8513         if (!r->in.buffer && (r->in.offered != 0)) {
8514                 return WERR_INVALID_PARAM;
8515         }
8516
8517         DEBUG(5,("_spoolss_EnumMonitors\n"));
8518
8519         /*
8520          * Enumerate the print monitors ...
8521          *
8522          * Just reply with "Local Port", to keep NT happy
8523          * and I can use my nice printer checker.
8524          */
8525
8526         *r->out.count = 0;
8527         *r->out.needed = 0;
8528         *r->out.info = NULL;
8529
8530         switch (r->in.level) {
8531         case 1:
8532                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8533                                                    r->out.count);
8534                 break;
8535         case 2:
8536                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8537                                                    r->out.count);
8538                 break;
8539         default:
8540                 return WERR_UNKNOWN_LEVEL;
8541         }
8542
8543         if (!W_ERROR_IS_OK(result)) {
8544                 return result;
8545         }
8546
8547         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8548                                                      spoolss_EnumMonitors, NULL,
8549                                                      *r->out.info, r->in.level,
8550                                                      *r->out.count);
8551         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8552         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8553
8554         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8555 }
8556
8557 /****************************************************************************
8558 ****************************************************************************/
8559
8560 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8561                              const print_queue_struct *queue,
8562                              int count, int snum,
8563                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8564                              uint32_t jobid,
8565                              struct spoolss_JobInfo1 *r)
8566 {
8567         int i = 0;
8568         bool found = false;
8569
8570         for (i=0; i<count && found == false; i++) {
8571                 if (queue[i].job == (int)jobid) {
8572                         found = true;
8573                 }
8574         }
8575
8576         if (found == false) {
8577                 /* NT treats not found as bad param... yet another bad choice */
8578                 return WERR_INVALID_PARAM;
8579         }
8580
8581         return fill_job_info1(mem_ctx,
8582                               r,
8583                               &queue[i-1],
8584                               i,
8585                               snum,
8586                               ntprinter);
8587 }
8588
8589 /****************************************************************************
8590 ****************************************************************************/
8591
8592 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8593                              const print_queue_struct *queue,
8594                              int count, int snum,
8595                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8596                              uint32_t jobid,
8597                              struct spoolss_JobInfo2 *r)
8598 {
8599         int i = 0;
8600         bool found = false;
8601         struct spoolss_DeviceMode *devmode;
8602         NT_DEVICEMODE *nt_devmode;
8603         WERROR result;
8604
8605         for (i=0; i<count && found == false; i++) {
8606                 if (queue[i].job == (int)jobid) {
8607                         found = true;
8608                 }
8609         }
8610
8611         if (found == false) {
8612                 /* NT treats not found as bad param... yet another bad
8613                    choice */
8614                 return WERR_INVALID_PARAM;
8615         }
8616
8617         /*
8618          * if the print job does not have a DEVMODE associated with it,
8619          * just use the one for the printer. A NULL devicemode is not
8620          *  a failure condition
8621          */
8622
8623         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8624         if (nt_devmode) {
8625                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8626                 W_ERROR_HAVE_NO_MEMORY(devmode);
8627                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8628                 if (!W_ERROR_IS_OK(result)) {
8629                         return result;
8630                 }
8631         } else {
8632                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8633                 W_ERROR_HAVE_NO_MEMORY(devmode);
8634         }
8635
8636         return fill_job_info2(mem_ctx,
8637                               r,
8638                               &queue[i-1],
8639                               i,
8640                               snum,
8641                               ntprinter,
8642                               devmode);
8643 }
8644
8645 /****************************************************************
8646  _spoolss_GetJob
8647 ****************************************************************/
8648
8649 WERROR _spoolss_GetJob(pipes_struct *p,
8650                        struct spoolss_GetJob *r)
8651 {
8652         WERROR result = WERR_OK;
8653         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8654         int snum;
8655         int count;
8656         print_queue_struct      *queue = NULL;
8657         print_status_struct prt_status;
8658
8659         /* that's an [in out] buffer */
8660
8661         if (!r->in.buffer && (r->in.offered != 0)) {
8662                 return WERR_INVALID_PARAM;
8663         }
8664
8665         DEBUG(5,("_spoolss_GetJob\n"));
8666
8667         *r->out.needed = 0;
8668
8669         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8670                 return WERR_BADFID;
8671         }
8672
8673         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8674         if (!W_ERROR_IS_OK(result)) {
8675                 return result;
8676         }
8677
8678         count = print_queue_status(snum, &queue, &prt_status);
8679
8680         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8681                      count, prt_status.status, prt_status.message));
8682
8683         switch (r->in.level) {
8684         case 1:
8685                 result = getjob_level_1(p->mem_ctx,
8686                                         queue, count, snum, ntprinter,
8687                                         r->in.job_id, &r->out.info->info1);
8688                 break;
8689         case 2:
8690                 result = getjob_level_2(p->mem_ctx,
8691                                         queue, count, snum, ntprinter,
8692                                         r->in.job_id, &r->out.info->info2);
8693                 break;
8694         default:
8695                 result = WERR_UNKNOWN_LEVEL;
8696                 break;
8697         }
8698
8699         SAFE_FREE(queue);
8700         free_a_printer(&ntprinter, 2);
8701
8702         if (!W_ERROR_IS_OK(result)) {
8703                 TALLOC_FREE(r->out.info);
8704                 return result;
8705         }
8706
8707         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8708                                                r->out.info, r->in.level);
8709         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8710
8711         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8712 }
8713
8714 /****************************************************************
8715  _spoolss_GetPrinterDataEx
8716 ****************************************************************/
8717
8718 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8719                                  struct spoolss_GetPrinterDataEx *r)
8720 {
8721
8722         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8723         struct regval_blob              *val = NULL;
8724         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8725         int                     snum = 0;
8726         WERROR result = WERR_OK;
8727         DATA_BLOB blob;
8728
8729         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8730
8731         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8732                 r->in.key_name, r->in.value_name));
8733
8734         /* in case of problem, return some default values */
8735
8736         *r->out.needed  = 0;
8737         *r->out.type    = REG_NONE;
8738
8739         if (!Printer) {
8740                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8741                         OUR_HANDLE(r->in.handle)));
8742                 result = WERR_BADFID;
8743                 goto done;
8744         }
8745
8746         /* Is the handle to a printer or to the server? */
8747
8748         if (Printer->printer_type == SPLHND_SERVER) {
8749
8750                 result = getprinterdata_printer_server(p->mem_ctx,
8751                                                        r->in.value_name,
8752                                                        r->out.type,
8753                                                        r->out.data);
8754                 goto done;
8755         }
8756
8757         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8758                 result = WERR_BADFID;
8759                 goto done;
8760         }
8761
8762         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8763         if (!W_ERROR_IS_OK(result)) {
8764                 goto done;
8765         }
8766
8767         /* check to see if the keyname is valid */
8768         if (!strlen(r->in.key_name)) {
8769                 result = WERR_INVALID_PARAM;
8770                 goto done;
8771         }
8772
8773         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8774
8775         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8776             strequal(r->in.value_name, "ChangeId")) {
8777                 *r->out.type = REG_DWORD;
8778                 *r->out.needed = 4;
8779                 r->out.data->value = printer->info_2->changeid;
8780                 result = WERR_OK;
8781                 goto done;
8782         }
8783
8784         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8785                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8786                         "Invalid keyname [%s]\n", r->in.key_name ));
8787                 result = WERR_BADFILE;
8788                 goto done;
8789         }
8790
8791         val = get_printer_data(printer->info_2,
8792                                r->in.key_name, r->in.value_name);
8793         if (!val) {
8794                 result = WERR_BADFILE;
8795                 goto done;
8796         }
8797
8798         *r->out.needed = regval_size(val);
8799         *r->out.type = regval_type(val);
8800
8801         blob = data_blob_const(regval_data_p(val), regval_size(val));
8802
8803         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
8804                                           r->out.data,
8805                                           *r->out.type);
8806
8807  done:
8808         if (printer) {
8809                 free_a_printer(&printer, 2);
8810         }
8811
8812         if (!W_ERROR_IS_OK(result)) {
8813                 return result;
8814         }
8815
8816         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
8817         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8818         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8819
8820         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8821 }
8822
8823 /****************************************************************
8824  _spoolss_SetPrinterDataEx
8825 ****************************************************************/
8826
8827 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8828                                  struct spoolss_SetPrinterDataEx *r)
8829 {
8830         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8831         int                     snum = 0;
8832         WERROR                  result = WERR_OK;
8833         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8834         char                    *oid_string;
8835         DATA_BLOB blob;
8836
8837         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8838
8839         /* From MSDN documentation of SetPrinterDataEx: pass request to
8840            SetPrinterData if key is "PrinterDriverData" */
8841
8842         if (!Printer) {
8843                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8844                         OUR_HANDLE(r->in.handle)));
8845                 return WERR_BADFID;
8846         }
8847
8848         if (Printer->printer_type == SPLHND_SERVER) {
8849                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8850                         "Not implemented for server handles yet\n"));
8851                 return WERR_INVALID_PARAM;
8852         }
8853
8854         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8855                 return WERR_BADFID;
8856         }
8857
8858         /*
8859          * Access check : NT returns "access denied" if you make a
8860          * SetPrinterData call without the necessary privildge.
8861          * we were originally returning OK if nothing changed
8862          * which made Win2k issue **a lot** of SetPrinterData
8863          * when connecting to a printer  --jerry
8864          */
8865
8866         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8867                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8868                         "change denied by handle access permissions\n"));
8869                 return WERR_ACCESS_DENIED;
8870         }
8871
8872         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8873         if (!W_ERROR_IS_OK(result)) {
8874                 return result;
8875         }
8876
8877         /* check for OID in valuename */
8878
8879         oid_string = strchr(r->in.value_name, ',');
8880         if (oid_string) {
8881                 *oid_string = '\0';
8882                 oid_string++;
8883         }
8884
8885         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8886                                           r->in.type, &r->in.data);
8887         if (!W_ERROR_IS_OK(result)) {
8888                 goto done;
8889         }
8890
8891         /*
8892          * When client side code sets a magic printer data key, detect it and save
8893          * the current printer data and the magic key's data (its the DEVMODE) for
8894          * future printer/driver initializations.
8895          */
8896         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8897                 /* Set devmode and printer initialization info */
8898                 result = save_driver_init(printer, 2, blob.data, blob.length);
8899
8900                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8901
8902                 goto done;
8903         }
8904
8905         /* save the registry data */
8906
8907         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8908                                     r->in.type, blob.data, blob.length);
8909
8910         if (W_ERROR_IS_OK(result)) {
8911                 /* save the OID if one was specified */
8912                 if (oid_string) {
8913                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8914                                 r->in.key_name, SPOOL_OID_KEY);
8915                         if (!str) {
8916                                 result = WERR_NOMEM;
8917                                 goto done;
8918                         }
8919
8920                         /*
8921                          * I'm not checking the status here on purpose.  Don't know
8922                          * if this is right, but I'm returning the status from the
8923                          * previous set_printer_dataex() call.  I have no idea if
8924                          * this is right.    --jerry
8925                          */
8926
8927                         set_printer_dataex(printer, str, r->in.value_name,
8928                                            REG_SZ, (uint8_t *)oid_string,
8929                                            strlen(oid_string)+1);
8930                 }
8931
8932                 result = mod_a_printer(printer, 2);
8933         }
8934
8935  done:
8936         free_a_printer(&printer, 2);
8937
8938         return result;
8939 }
8940
8941 /****************************************************************
8942  _spoolss_DeletePrinterDataEx
8943 ****************************************************************/
8944
8945 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8946                                     struct spoolss_DeletePrinterDataEx *r)
8947 {
8948         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8949         int             snum=0;
8950         WERROR          status = WERR_OK;
8951         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8952
8953         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8954
8955         if (!Printer) {
8956                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8957                         "Invalid handle (%s:%u:%u).\n",
8958                         OUR_HANDLE(r->in.handle)));
8959                 return WERR_BADFID;
8960         }
8961
8962         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8963                 return WERR_BADFID;
8964
8965         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8966                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8967                         "printer properties change denied by handle\n"));
8968                 return WERR_ACCESS_DENIED;
8969         }
8970
8971         if (!r->in.value_name || !r->in.key_name) {
8972                 return WERR_NOMEM;
8973         }
8974
8975         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8976         if (!W_ERROR_IS_OK(status))
8977                 return status;
8978
8979         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8980
8981         if ( W_ERROR_IS_OK(status) )
8982                 mod_a_printer( printer, 2 );
8983
8984         free_a_printer(&printer, 2);
8985
8986         return status;
8987 }
8988
8989 /****************************************************************
8990  _spoolss_EnumPrinterKey
8991 ****************************************************************/
8992
8993 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8994                                struct spoolss_EnumPrinterKey *r)
8995 {
8996         fstring         *keynames = NULL;
8997         int             num_keys;
8998         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8999         NT_PRINTER_DATA *data;
9000         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9001         int             snum = 0;
9002         WERROR          result = WERR_BADFILE;
9003         int i;
9004         const char **array = NULL;
9005         DATA_BLOB blob;
9006
9007         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9008
9009         if (!Printer) {
9010                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9011                         OUR_HANDLE(r->in.handle)));
9012                 return WERR_BADFID;
9013         }
9014
9015         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9016                 return WERR_BADFID;
9017         }
9018
9019         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9020         if (!W_ERROR_IS_OK(result)) {
9021                 return result;
9022         }
9023
9024         /* get the list of subkey names */
9025
9026         data = printer->info_2->data;
9027
9028         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9029         if (num_keys == -1) {
9030                 result = WERR_BADFILE;
9031                 goto done;
9032         }
9033
9034         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9035         if (!array) {
9036                 result = WERR_NOMEM;
9037                 goto done;
9038         }
9039
9040         for (i=0; i < num_keys; i++) {
9041
9042                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9043                         keynames[i]));
9044
9045                 array[i] = talloc_strdup(array, keynames[i]);
9046                 if (!array[i]) {
9047                         result = WERR_NOMEM;
9048                         goto done;
9049                 }
9050         }
9051
9052         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9053                 result = WERR_NOMEM;
9054                 goto done;
9055         }
9056
9057         *r->out.needed = blob.length;
9058
9059         if (r->in.offered < *r->out.needed) {
9060                 result = WERR_MORE_DATA;
9061         } else {
9062                 result = WERR_OK;
9063                 r->out.key_buffer->string = array;
9064         }
9065
9066  done:
9067         if (!W_ERROR_IS_OK(result)) {
9068                 TALLOC_FREE(array);
9069                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9070                         *r->out.needed = 0;
9071                 }
9072         }
9073
9074         free_a_printer(&printer, 2);
9075         SAFE_FREE(keynames);
9076
9077         return result;
9078 }
9079
9080 /****************************************************************
9081  _spoolss_DeletePrinterKey
9082 ****************************************************************/
9083
9084 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9085                                  struct spoolss_DeletePrinterKey *r)
9086 {
9087         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9088         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9089         int                     snum=0;
9090         WERROR                  status;
9091
9092         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9093
9094         if (!Printer) {
9095                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9096                         OUR_HANDLE(r->in.handle)));
9097                 return WERR_BADFID;
9098         }
9099
9100         /* if keyname == NULL, return error */
9101
9102         if ( !r->in.key_name )
9103                 return WERR_INVALID_PARAM;
9104
9105         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9106                 return WERR_BADFID;
9107
9108         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9109                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9110                         "printer properties change denied by handle\n"));
9111                 return WERR_ACCESS_DENIED;
9112         }
9113
9114         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9115         if (!W_ERROR_IS_OK(status))
9116                 return status;
9117
9118         /* delete the key and all subneys */
9119
9120         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9121
9122         if ( W_ERROR_IS_OK(status) )
9123                 status = mod_a_printer(printer, 2);
9124
9125         free_a_printer( &printer, 2 );
9126
9127         return status;
9128 }
9129
9130 /****************************************************************
9131 ****************************************************************/
9132
9133 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9134                                                    struct regval_blob *v,
9135                                                    struct spoolss_PrinterEnumValues *r)
9136 {
9137         WERROR result;
9138
9139         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9140         W_ERROR_HAVE_NO_MEMORY(r->data);
9141
9142         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9143         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9144
9145         r->type         = regval_type(v);
9146         r->data_length  = regval_size(v);
9147
9148         if (r->data_length) {
9149                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9150                                                  regval_size(v));
9151                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9152                                                   r->data,
9153                                                   r->type);
9154                 if (!W_ERROR_IS_OK(result)) {
9155                         return result;
9156                 }
9157         }
9158
9159         return WERR_OK;
9160 }
9161
9162 /****************************************************************
9163  _spoolss_EnumPrinterDataEx
9164 ****************************************************************/
9165
9166 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9167                                   struct spoolss_EnumPrinterDataEx *r)
9168 {
9169         uint32_t        count = 0;
9170         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9171         struct spoolss_PrinterEnumValues *info = NULL;
9172         NT_PRINTER_DATA         *p_data;
9173         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9174         int             snum;
9175         WERROR          result;
9176         int             key_index;
9177         int             i;
9178
9179         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9180
9181         *r->out.count = 0;
9182         *r->out.needed = 0;
9183         *r->out.info = NULL;
9184
9185         if (!Printer) {
9186                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9187                         OUR_HANDLE(r->in.handle)));
9188                 return WERR_BADFID;
9189         }
9190
9191         /*
9192          * first check for a keyname of NULL or "".  Win2k seems to send
9193          * this a lot and we should send back WERR_INVALID_PARAM
9194          * no need to spend time looking up the printer in this case.
9195          * --jerry
9196          */
9197
9198         if (!strlen(r->in.key_name)) {
9199                 result = WERR_INVALID_PARAM;
9200                 goto done;
9201         }
9202
9203         /* get the printer off of disk */
9204
9205         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9206                 return WERR_BADFID;
9207         }
9208
9209         ZERO_STRUCT(printer);
9210         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9211         if (!W_ERROR_IS_OK(result)) {
9212                 return result;
9213         }
9214
9215         /* now look for a match on the key name */
9216
9217         p_data = printer->info_2->data;
9218
9219         key_index = lookup_printerkey(p_data, r->in.key_name);
9220         if (key_index == -1) {
9221                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9222                         r->in.key_name));
9223                 result = WERR_INVALID_PARAM;
9224                 goto done;
9225         }
9226
9227         /* allocate the memory for the array of pointers -- if necessary */
9228
9229         count = regval_ctr_numvals(p_data->keys[key_index].values);
9230         if (!count) {
9231                 result = WERR_OK; /* ??? */
9232                 goto done;
9233         }
9234
9235         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9236                                  struct spoolss_PrinterEnumValues,
9237                                  count);
9238         if (!info) {
9239                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9240                 result = WERR_NOMEM;
9241                 goto done;
9242         }
9243
9244         /*
9245          * loop through all params and build the array to pass
9246          * back to the  client
9247          */
9248
9249         for (i=0; i < count; i++) {
9250
9251                 struct regval_blob      *val;
9252
9253                 /* lookup the registry value */
9254
9255                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9256
9257                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9258
9259                 /* copy the data */
9260
9261                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9262                 if (!W_ERROR_IS_OK(result)) {
9263                         goto done;
9264                 }
9265         }
9266
9267 #if 0 /* FIXME - gd */
9268         /* housekeeping information in the reply */
9269
9270         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9271          * the hand marshalled container size is a multiple
9272          * of 4 bytes for RPC alignment.
9273          */
9274
9275         if (needed % 4) {
9276                 needed += 4-(needed % 4);
9277         }
9278 #endif
9279         *r->out.count   = count;
9280         *r->out.info    = info;
9281
9282  done:
9283
9284         if (printer) {
9285                 free_a_printer(&printer, 2);
9286         }
9287
9288         if (!W_ERROR_IS_OK(result)) {
9289                 return result;
9290         }
9291
9292         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9293                                                spoolss_EnumPrinterDataEx, NULL,
9294                                                *r->out.info,
9295                                                *r->out.count);
9296         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9297         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9298
9299         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9300 }
9301
9302 /****************************************************************************
9303 ****************************************************************************/
9304
9305 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9306                                                  const char *servername,
9307                                                  const char *environment,
9308                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9309 {
9310         WERROR werr;
9311         char *path = NULL;
9312
9313         werr = compose_spoolss_server_path(mem_ctx,
9314                                            servername,
9315                                            environment,
9316                                            SPOOLSS_PRTPROCS_PATH,
9317                                            &path);
9318         if (!W_ERROR_IS_OK(werr)) {
9319                 return werr;
9320         }
9321
9322         DEBUG(4,("print processor directory: [%s]\n", path));
9323
9324         r->directory_name = path;
9325
9326         return WERR_OK;
9327 }
9328
9329 /****************************************************************
9330  _spoolss_GetPrintProcessorDirectory
9331 ****************************************************************/
9332
9333 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9334                                            struct spoolss_GetPrintProcessorDirectory *r)
9335 {
9336         WERROR result;
9337
9338         /* that's an [in out] buffer */
9339
9340         if (!r->in.buffer && (r->in.offered != 0)) {
9341                 return WERR_INVALID_PARAM;
9342         }
9343
9344         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9345                 r->in.level));
9346
9347         *r->out.needed = 0;
9348
9349         /* r->in.level is ignored */
9350
9351         /* We always should reply with a local print processor directory so that
9352          * users are not forced to have a [prnproc$] share on the Samba spoolss
9353          * server - Guenther */
9354
9355         result = getprintprocessordirectory_level_1(p->mem_ctx,
9356                                                     NULL, /* r->in.server */
9357                                                     r->in.environment,
9358                                                     &r->out.info->info1);
9359         if (!W_ERROR_IS_OK(result)) {
9360                 TALLOC_FREE(r->out.info);
9361                 return result;
9362         }
9363
9364         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9365                                                r->out.info, r->in.level);
9366         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9367
9368         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9369 }
9370
9371 /*******************************************************************
9372  ********************************************************************/
9373
9374 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9375                                const char *dllname)
9376 {
9377         enum ndr_err_code ndr_err;
9378         struct spoolss_MonitorUi ui;
9379
9380         ui.dll_name = dllname;
9381
9382         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9383                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9384         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9385                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9386         }
9387         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9388 }
9389
9390 /*******************************************************************
9391  Streams the monitor UI DLL name in UNICODE
9392 *******************************************************************/
9393
9394 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9395                                NT_USER_TOKEN *token, DATA_BLOB *in,
9396                                DATA_BLOB *out, uint32_t *needed)
9397 {
9398         const char *dllname = "tcpmonui.dll";
9399
9400         *needed = (strlen(dllname)+1) * 2;
9401
9402         if (out->length < *needed) {
9403                 return WERR_INSUFFICIENT_BUFFER;
9404         }
9405
9406         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9407                 return WERR_NOMEM;
9408         }
9409
9410         return WERR_OK;
9411 }
9412
9413 /*******************************************************************
9414  ********************************************************************/
9415
9416 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9417                              struct spoolss_PortData1 *port1,
9418                              const DATA_BLOB *buf)
9419 {
9420         enum ndr_err_code ndr_err;
9421         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9422                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9423         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9424                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9425         }
9426         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9427 }
9428
9429 /*******************************************************************
9430  ********************************************************************/
9431
9432 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9433                              struct spoolss_PortData2 *port2,
9434                              const DATA_BLOB *buf)
9435 {
9436         enum ndr_err_code ndr_err;
9437         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9438                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9439         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9440                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9441         }
9442         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9443 }
9444
9445 /*******************************************************************
9446  Create a new TCP/IP port
9447 *******************************************************************/
9448
9449 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9450                              NT_USER_TOKEN *token, DATA_BLOB *in,
9451                              DATA_BLOB *out, uint32_t *needed)
9452 {
9453         struct spoolss_PortData1 port1;
9454         struct spoolss_PortData2 port2;
9455         char *device_uri = NULL;
9456         uint32_t version;
9457
9458         const char *portname;
9459         const char *hostaddress;
9460         const char *queue;
9461         uint32_t port_number;
9462         uint32_t protocol;
9463
9464         /* peek for spoolss_PortData version */
9465
9466         if (!in || (in->length < (128 + 4))) {
9467                 return WERR_GENERAL_FAILURE;
9468         }
9469
9470         version = IVAL(in->data, 128);
9471
9472         switch (version) {
9473                 case 1:
9474                         ZERO_STRUCT(port1);
9475
9476                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9477                                 return WERR_NOMEM;
9478                         }
9479
9480                         portname        = port1.portname;
9481                         hostaddress     = port1.hostaddress;
9482                         queue           = port1.queue;
9483                         protocol        = port1.protocol;
9484                         port_number     = port1.port_number;
9485
9486                         break;
9487                 case 2:
9488                         ZERO_STRUCT(port2);
9489
9490                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9491                                 return WERR_NOMEM;
9492                         }
9493
9494                         portname        = port2.portname;
9495                         hostaddress     = port2.hostaddress;
9496                         queue           = port2.queue;
9497                         protocol        = port2.protocol;
9498                         port_number     = port2.port_number;
9499
9500                         break;
9501                 default:
9502                         DEBUG(1,("xcvtcp_addport: "
9503                                 "unknown version of port_data: %d\n", version));
9504                         return WERR_UNKNOWN_PORT;
9505         }
9506
9507         /* create the device URI and call the add_port_hook() */
9508
9509         switch (protocol) {
9510         case PROTOCOL_RAWTCP_TYPE:
9511                 device_uri = talloc_asprintf(mem_ctx,
9512                                 "socket://%s:%d/", hostaddress,
9513                                 port_number);
9514                 break;
9515
9516         case PROTOCOL_LPR_TYPE:
9517                 device_uri = talloc_asprintf(mem_ctx,
9518                         "lpr://%s/%s", hostaddress, queue );
9519                 break;
9520
9521         default:
9522                 return WERR_UNKNOWN_PORT;
9523         }
9524
9525         if (!device_uri) {
9526                 return WERR_NOMEM;
9527         }
9528
9529         return add_port_hook(mem_ctx, token, portname, device_uri);
9530 }
9531
9532 /*******************************************************************
9533 *******************************************************************/
9534
9535 struct xcv_api_table xcvtcp_cmds[] = {
9536         { "MonitorUI",  xcvtcp_monitorui },
9537         { "AddPort",    xcvtcp_addport},
9538         { NULL,         NULL }
9539 };
9540
9541 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9542                                      NT_USER_TOKEN *token, const char *command,
9543                                      DATA_BLOB *inbuf,
9544                                      DATA_BLOB *outbuf,
9545                                      uint32_t *needed )
9546 {
9547         int i;
9548
9549         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9550
9551         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9552                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9553                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9554         }
9555
9556         return WERR_BADFUNC;
9557 }
9558
9559 /*******************************************************************
9560 *******************************************************************/
9561 #if 0   /* don't support management using the "Local Port" monitor */
9562
9563 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9564                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9565                                  DATA_BLOB *out, uint32_t *needed)
9566 {
9567         const char *dllname = "localui.dll";
9568
9569         *needed = (strlen(dllname)+1) * 2;
9570
9571         if (out->length < *needed) {
9572                 return WERR_INSUFFICIENT_BUFFER;
9573         }
9574
9575         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9576                 return WERR_NOMEM;
9577         }
9578
9579         return WERR_OK;
9580 }
9581
9582 /*******************************************************************
9583 *******************************************************************/
9584
9585 struct xcv_api_table xcvlocal_cmds[] = {
9586         { "MonitorUI",  xcvlocal_monitorui },
9587         { NULL,         NULL }
9588 };
9589 #else
9590 struct xcv_api_table xcvlocal_cmds[] = {
9591         { NULL,         NULL }
9592 };
9593 #endif
9594
9595
9596
9597 /*******************************************************************
9598 *******************************************************************/
9599
9600 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9601                                        NT_USER_TOKEN *token, const char *command,
9602                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9603                                        uint32_t *needed)
9604 {
9605         int i;
9606
9607         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9608
9609         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9610                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9611                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9612         }
9613         return WERR_BADFUNC;
9614 }
9615
9616 /****************************************************************
9617  _spoolss_XcvData
9618 ****************************************************************/
9619
9620 WERROR _spoolss_XcvData(pipes_struct *p,
9621                         struct spoolss_XcvData *r)
9622 {
9623         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9624         DATA_BLOB out_data = data_blob_null;
9625         WERROR werror;
9626
9627         if (!Printer) {
9628                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9629                         OUR_HANDLE(r->in.handle)));
9630                 return WERR_BADFID;
9631         }
9632
9633         /* Has to be a handle to the TCP/IP port monitor */
9634
9635         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9636                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9637                 return WERR_BADFID;
9638         }
9639
9640         /* requires administrative access to the server */
9641
9642         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9643                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9644                 return WERR_ACCESS_DENIED;
9645         }
9646
9647         /* Allocate the outgoing buffer */
9648
9649         if (r->in.out_data_size) {
9650                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9651                 if (out_data.data == NULL) {
9652                         return WERR_NOMEM;
9653                 }
9654         }
9655
9656         switch ( Printer->printer_type ) {
9657         case SPLHND_PORTMON_TCP:
9658                 werror = process_xcvtcp_command(p->mem_ctx,
9659                                                 p->server_info->ptok,
9660                                                 r->in.function_name,
9661                                                 &r->in.in_data, &out_data,
9662                                                 r->out.needed);
9663                 break;
9664         case SPLHND_PORTMON_LOCAL:
9665                 werror = process_xcvlocal_command(p->mem_ctx,
9666                                                   p->server_info->ptok,
9667                                                   r->in.function_name,
9668                                                   &r->in.in_data, &out_data,
9669                                                   r->out.needed);
9670                 break;
9671         default:
9672                 werror = WERR_INVALID_PRINT_MONITOR;
9673         }
9674
9675         if (!W_ERROR_IS_OK(werror)) {
9676                 return werror;
9677         }
9678
9679         *r->out.status_code = 0;
9680
9681         memcpy(r->out.out_data, out_data.data, out_data.length);
9682
9683         return WERR_OK;
9684 }
9685
9686 /****************************************************************
9687  _spoolss_AddPrintProcessor
9688 ****************************************************************/
9689
9690 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9691                                   struct spoolss_AddPrintProcessor *r)
9692 {
9693         /* for now, just indicate success and ignore the add.  We'll
9694            automatically set the winprint processor for printer
9695            entries later.  Used to debug the LexMark Optra S 1855 PCL
9696            driver --jerry */
9697
9698         return WERR_OK;
9699 }
9700
9701 /****************************************************************
9702  _spoolss_AddPort
9703 ****************************************************************/
9704
9705 WERROR _spoolss_AddPort(pipes_struct *p,
9706                         struct spoolss_AddPort *r)
9707 {
9708         /* do what w2k3 does */
9709
9710         return WERR_NOT_SUPPORTED;
9711 }
9712
9713 /****************************************************************
9714  _spoolss_GetPrinterDriver
9715 ****************************************************************/
9716
9717 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9718                                  struct spoolss_GetPrinterDriver *r)
9719 {
9720         p->rng_fault_state = true;
9721         return WERR_NOT_SUPPORTED;
9722 }
9723
9724 /****************************************************************
9725  _spoolss_ReadPrinter
9726 ****************************************************************/
9727
9728 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9729                             struct spoolss_ReadPrinter *r)
9730 {
9731         p->rng_fault_state = true;
9732         return WERR_NOT_SUPPORTED;
9733 }
9734
9735 /****************************************************************
9736  _spoolss_WaitForPrinterChange
9737 ****************************************************************/
9738
9739 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9740                                      struct spoolss_WaitForPrinterChange *r)
9741 {
9742         p->rng_fault_state = true;
9743         return WERR_NOT_SUPPORTED;
9744 }
9745
9746 /****************************************************************
9747  _spoolss_ConfigurePort
9748 ****************************************************************/
9749
9750 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9751                               struct spoolss_ConfigurePort *r)
9752 {
9753         p->rng_fault_state = true;
9754         return WERR_NOT_SUPPORTED;
9755 }
9756
9757 /****************************************************************
9758  _spoolss_DeletePort
9759 ****************************************************************/
9760
9761 WERROR _spoolss_DeletePort(pipes_struct *p,
9762                            struct spoolss_DeletePort *r)
9763 {
9764         p->rng_fault_state = true;
9765         return WERR_NOT_SUPPORTED;
9766 }
9767
9768 /****************************************************************
9769  _spoolss_CreatePrinterIC
9770 ****************************************************************/
9771
9772 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9773                                 struct spoolss_CreatePrinterIC *r)
9774 {
9775         p->rng_fault_state = true;
9776         return WERR_NOT_SUPPORTED;
9777 }
9778
9779 /****************************************************************
9780  _spoolss_PlayGDIScriptOnPrinterIC
9781 ****************************************************************/
9782
9783 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9784                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9785 {
9786         p->rng_fault_state = true;
9787         return WERR_NOT_SUPPORTED;
9788 }
9789
9790 /****************************************************************
9791  _spoolss_DeletePrinterIC
9792 ****************************************************************/
9793
9794 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9795                                 struct spoolss_DeletePrinterIC *r)
9796 {
9797         p->rng_fault_state = true;
9798         return WERR_NOT_SUPPORTED;
9799 }
9800
9801 /****************************************************************
9802  _spoolss_AddPrinterConnection
9803 ****************************************************************/
9804
9805 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9806                                      struct spoolss_AddPrinterConnection *r)
9807 {
9808         p->rng_fault_state = true;
9809         return WERR_NOT_SUPPORTED;
9810 }
9811
9812 /****************************************************************
9813  _spoolss_DeletePrinterConnection
9814 ****************************************************************/
9815
9816 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9817                                         struct spoolss_DeletePrinterConnection *r)
9818 {
9819         p->rng_fault_state = true;
9820         return WERR_NOT_SUPPORTED;
9821 }
9822
9823 /****************************************************************
9824  _spoolss_PrinterMessageBox
9825 ****************************************************************/
9826
9827 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9828                                   struct spoolss_PrinterMessageBox *r)
9829 {
9830         p->rng_fault_state = true;
9831         return WERR_NOT_SUPPORTED;
9832 }
9833
9834 /****************************************************************
9835  _spoolss_AddMonitor
9836 ****************************************************************/
9837
9838 WERROR _spoolss_AddMonitor(pipes_struct *p,
9839                            struct spoolss_AddMonitor *r)
9840 {
9841         p->rng_fault_state = true;
9842         return WERR_NOT_SUPPORTED;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_DeleteMonitor
9847 ****************************************************************/
9848
9849 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9850                               struct spoolss_DeleteMonitor *r)
9851 {
9852         p->rng_fault_state = true;
9853         return WERR_NOT_SUPPORTED;
9854 }
9855
9856 /****************************************************************
9857  _spoolss_DeletePrintProcessor
9858 ****************************************************************/
9859
9860 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9861                                      struct spoolss_DeletePrintProcessor *r)
9862 {
9863         p->rng_fault_state = true;
9864         return WERR_NOT_SUPPORTED;
9865 }
9866
9867 /****************************************************************
9868  _spoolss_AddPrintProvidor
9869 ****************************************************************/
9870
9871 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9872                                  struct spoolss_AddPrintProvidor *r)
9873 {
9874         p->rng_fault_state = true;
9875         return WERR_NOT_SUPPORTED;
9876 }
9877
9878 /****************************************************************
9879  _spoolss_DeletePrintProvidor
9880 ****************************************************************/
9881
9882 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9883                                     struct spoolss_DeletePrintProvidor *r)
9884 {
9885         p->rng_fault_state = true;
9886         return WERR_NOT_SUPPORTED;
9887 }
9888
9889 /****************************************************************
9890  _spoolss_FindFirstPrinterChangeNotification
9891 ****************************************************************/
9892
9893 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9894                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9895 {
9896         p->rng_fault_state = true;
9897         return WERR_NOT_SUPPORTED;
9898 }
9899
9900 /****************************************************************
9901  _spoolss_FindNextPrinterChangeNotification
9902 ****************************************************************/
9903
9904 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9905                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9906 {
9907         p->rng_fault_state = true;
9908         return WERR_NOT_SUPPORTED;
9909 }
9910
9911 /****************************************************************
9912  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9913 ****************************************************************/
9914
9915 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9916                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9917 {
9918         p->rng_fault_state = true;
9919         return WERR_NOT_SUPPORTED;
9920 }
9921
9922 /****************************************************************
9923  _spoolss_ReplyOpenPrinter
9924 ****************************************************************/
9925
9926 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9927                                  struct spoolss_ReplyOpenPrinter *r)
9928 {
9929         p->rng_fault_state = true;
9930         return WERR_NOT_SUPPORTED;
9931 }
9932
9933 /****************************************************************
9934  _spoolss_RouterReplyPrinter
9935 ****************************************************************/
9936
9937 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9938                                    struct spoolss_RouterReplyPrinter *r)
9939 {
9940         p->rng_fault_state = true;
9941         return WERR_NOT_SUPPORTED;
9942 }
9943
9944 /****************************************************************
9945  _spoolss_ReplyClosePrinter
9946 ****************************************************************/
9947
9948 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9949                                   struct spoolss_ReplyClosePrinter *r)
9950 {
9951         p->rng_fault_state = true;
9952         return WERR_NOT_SUPPORTED;
9953 }
9954
9955 /****************************************************************
9956  _spoolss_AddPortEx
9957 ****************************************************************/
9958
9959 WERROR _spoolss_AddPortEx(pipes_struct *p,
9960                           struct spoolss_AddPortEx *r)
9961 {
9962         p->rng_fault_state = true;
9963         return WERR_NOT_SUPPORTED;
9964 }
9965
9966 /****************************************************************
9967  _spoolss_RouterFindFirstPrinterChangeNotification
9968 ****************************************************************/
9969
9970 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9971                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9972 {
9973         p->rng_fault_state = true;
9974         return WERR_NOT_SUPPORTED;
9975 }
9976
9977 /****************************************************************
9978  _spoolss_SpoolerInit
9979 ****************************************************************/
9980
9981 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9982                             struct spoolss_SpoolerInit *r)
9983 {
9984         p->rng_fault_state = true;
9985         return WERR_NOT_SUPPORTED;
9986 }
9987
9988 /****************************************************************
9989  _spoolss_ResetPrinterEx
9990 ****************************************************************/
9991
9992 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9993                                struct spoolss_ResetPrinterEx *r)
9994 {
9995         p->rng_fault_state = true;
9996         return WERR_NOT_SUPPORTED;
9997 }
9998
9999 /****************************************************************
10000  _spoolss_RouterReplyPrinterEx
10001 ****************************************************************/
10002
10003 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10004                                      struct spoolss_RouterReplyPrinterEx *r)
10005 {
10006         p->rng_fault_state = true;
10007         return WERR_NOT_SUPPORTED;
10008 }
10009
10010 /****************************************************************
10011  _spoolss_44
10012 ****************************************************************/
10013
10014 WERROR _spoolss_44(pipes_struct *p,
10015                    struct spoolss_44 *r)
10016 {
10017         p->rng_fault_state = true;
10018         return WERR_NOT_SUPPORTED;
10019 }
10020
10021 /****************************************************************
10022  _spoolss_47
10023 ****************************************************************/
10024
10025 WERROR _spoolss_47(pipes_struct *p,
10026                    struct spoolss_47 *r)
10027 {
10028         p->rng_fault_state = true;
10029         return WERR_NOT_SUPPORTED;
10030 }
10031
10032 /****************************************************************
10033  _spoolss_4a
10034 ****************************************************************/
10035
10036 WERROR _spoolss_4a(pipes_struct *p,
10037                    struct spoolss_4a *r)
10038 {
10039         p->rng_fault_state = true;
10040         return WERR_NOT_SUPPORTED;
10041 }
10042
10043 /****************************************************************
10044  _spoolss_4b
10045 ****************************************************************/
10046
10047 WERROR _spoolss_4b(pipes_struct *p,
10048                    struct spoolss_4b *r)
10049 {
10050         p->rng_fault_state = true;
10051         return WERR_NOT_SUPPORTED;
10052 }
10053
10054 /****************************************************************
10055  _spoolss_4c
10056 ****************************************************************/
10057
10058 WERROR _spoolss_4c(pipes_struct *p,
10059                    struct spoolss_4c *r)
10060 {
10061         p->rng_fault_state = true;
10062         return WERR_NOT_SUPPORTED;
10063 }
10064
10065 /****************************************************************
10066  _spoolss_53
10067 ****************************************************************/
10068
10069 WERROR _spoolss_53(pipes_struct *p,
10070                    struct spoolss_53 *r)
10071 {
10072         p->rng_fault_state = true;
10073         return WERR_NOT_SUPPORTED;
10074 }
10075
10076 /****************************************************************
10077  _spoolss_55
10078 ****************************************************************/
10079
10080 WERROR _spoolss_55(pipes_struct *p,
10081                    struct spoolss_55 *r)
10082 {
10083         p->rng_fault_state = true;
10084         return WERR_NOT_SUPPORTED;
10085 }
10086
10087 /****************************************************************
10088  _spoolss_56
10089 ****************************************************************/
10090
10091 WERROR _spoolss_56(pipes_struct *p,
10092                    struct spoolss_56 *r)
10093 {
10094         p->rng_fault_state = true;
10095         return WERR_NOT_SUPPORTED;
10096 }
10097
10098 /****************************************************************
10099  _spoolss_57
10100 ****************************************************************/
10101
10102 WERROR _spoolss_57(pipes_struct *p,
10103                    struct spoolss_57 *r)
10104 {
10105         p->rng_fault_state = true;
10106         return WERR_NOT_SUPPORTED;
10107 }
10108
10109 /****************************************************************
10110  _spoolss_5a
10111 ****************************************************************/
10112
10113 WERROR _spoolss_5a(pipes_struct *p,
10114                    struct spoolss_5a *r)
10115 {
10116         p->rng_fault_state = true;
10117         return WERR_NOT_SUPPORTED;
10118 }
10119
10120 /****************************************************************
10121  _spoolss_5b
10122 ****************************************************************/
10123
10124 WERROR _spoolss_5b(pipes_struct *p,
10125                    struct spoolss_5b *r)
10126 {
10127         p->rng_fault_state = true;
10128         return WERR_NOT_SUPPORTED;
10129 }
10130
10131 /****************************************************************
10132  _spoolss_5c
10133 ****************************************************************/
10134
10135 WERROR _spoolss_5c(pipes_struct *p,
10136                    struct spoolss_5c *r)
10137 {
10138         p->rng_fault_state = true;
10139         return WERR_NOT_SUPPORTED;
10140 }
10141
10142 /****************************************************************
10143  _spoolss_5d
10144 ****************************************************************/
10145
10146 WERROR _spoolss_5d(pipes_struct *p,
10147                    struct spoolss_5d *r)
10148 {
10149         p->rng_fault_state = true;
10150         return WERR_NOT_SUPPORTED;
10151 }
10152
10153 /****************************************************************
10154  _spoolss_5e
10155 ****************************************************************/
10156
10157 WERROR _spoolss_5e(pipes_struct *p,
10158                    struct spoolss_5e *r)
10159 {
10160         p->rng_fault_state = true;
10161         return WERR_NOT_SUPPORTED;
10162 }
10163
10164 /****************************************************************
10165  _spoolss_5f
10166 ****************************************************************/
10167
10168 WERROR _spoolss_5f(pipes_struct *p,
10169                    struct spoolss_5f *r)
10170 {
10171         p->rng_fault_state = true;
10172         return WERR_NOT_SUPPORTED;
10173 }
10174
10175 /****************************************************************
10176  _spoolss_60
10177 ****************************************************************/
10178
10179 WERROR _spoolss_60(pipes_struct *p,
10180                    struct spoolss_60 *r)
10181 {
10182         p->rng_fault_state = true;
10183         return WERR_NOT_SUPPORTED;
10184 }
10185
10186 /****************************************************************
10187  _spoolss_61
10188 ****************************************************************/
10189
10190 WERROR _spoolss_61(pipes_struct *p,
10191                    struct spoolss_61 *r)
10192 {
10193         p->rng_fault_state = true;
10194         return WERR_NOT_SUPPORTED;
10195 }
10196
10197 /****************************************************************
10198  _spoolss_62
10199 ****************************************************************/
10200
10201 WERROR _spoolss_62(pipes_struct *p,
10202                    struct spoolss_62 *r)
10203 {
10204         p->rng_fault_state = true;
10205         return WERR_NOT_SUPPORTED;
10206 }
10207
10208 /****************************************************************
10209  _spoolss_63
10210 ****************************************************************/
10211
10212 WERROR _spoolss_63(pipes_struct *p,
10213                    struct spoolss_63 *r)
10214 {
10215         p->rng_fault_state = true;
10216         return WERR_NOT_SUPPORTED;
10217 }
10218
10219 /****************************************************************
10220  _spoolss_64
10221 ****************************************************************/
10222
10223 WERROR _spoolss_64(pipes_struct *p,
10224                    struct spoolss_64 *r)
10225 {
10226         p->rng_fault_state = true;
10227         return WERR_NOT_SUPPORTED;
10228 }
10229
10230 /****************************************************************
10231  _spoolss_65
10232 ****************************************************************/
10233
10234 WERROR _spoolss_65(pipes_struct *p,
10235                    struct spoolss_65 *r)
10236 {
10237         p->rng_fault_state = true;
10238         return WERR_NOT_SUPPORTED;
10239 }
10240
10241 /****************************************************************
10242  _spoolss_GetCorePrinterDrivers
10243 ****************************************************************/
10244
10245 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10246                                       struct spoolss_GetCorePrinterDrivers *r)
10247 {
10248         p->rng_fault_state = true;
10249         return WERR_NOT_SUPPORTED;
10250 }
10251
10252 /****************************************************************
10253  _spoolss_67
10254 ****************************************************************/
10255
10256 WERROR _spoolss_67(pipes_struct *p,
10257                    struct spoolss_67 *r)
10258 {
10259         p->rng_fault_state = true;
10260         return WERR_NOT_SUPPORTED;
10261 }
10262
10263 /****************************************************************
10264  _spoolss_GetPrinterDriverPackagePath
10265 ****************************************************************/
10266
10267 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10268                                             struct spoolss_GetPrinterDriverPackagePath *r)
10269 {
10270         p->rng_fault_state = true;
10271         return WERR_NOT_SUPPORTED;
10272 }
10273
10274 /****************************************************************
10275  _spoolss_69
10276 ****************************************************************/
10277
10278 WERROR _spoolss_69(pipes_struct *p,
10279                    struct spoolss_69 *r)
10280 {
10281         p->rng_fault_state = true;
10282         return WERR_NOT_SUPPORTED;
10283 }
10284
10285 /****************************************************************
10286  _spoolss_6a
10287 ****************************************************************/
10288
10289 WERROR _spoolss_6a(pipes_struct *p,
10290                    struct spoolss_6a *r)
10291 {
10292         p->rng_fault_state = true;
10293         return WERR_NOT_SUPPORTED;
10294 }
10295
10296 /****************************************************************
10297  _spoolss_6b
10298 ****************************************************************/
10299
10300 WERROR _spoolss_6b(pipes_struct *p,
10301                    struct spoolss_6b *r)
10302 {
10303         p->rng_fault_state = true;
10304         return WERR_NOT_SUPPORTED;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_6c
10309 ****************************************************************/
10310
10311 WERROR _spoolss_6c(pipes_struct *p,
10312                    struct spoolss_6c *r)
10313 {
10314         p->rng_fault_state = true;
10315         return WERR_NOT_SUPPORTED;
10316 }
10317
10318 /****************************************************************
10319  _spoolss_6d
10320 ****************************************************************/
10321
10322 WERROR _spoolss_6d(pipes_struct *p,
10323                    struct spoolss_6d *r)
10324 {
10325         p->rng_fault_state = true;
10326         return WERR_NOT_SUPPORTED;
10327 }