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