8cf2c4159b46fa35aa7bde3e455033a5f017045d
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35         ((info)?ndr_size_##fn(info, level, ic, 0):0)
36
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
39
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
42
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44
45
46 extern userdom_struct current_user_info;
47
48 #undef DBGC_CLASS
49 #define DBGC_CLASS DBGC_RPC_SRV
50
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
53 #endif
54
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
57
58 static Printer_entry *printers_list;
59
60 typedef struct _counter_printer_0 {
61         struct _counter_printer_0 *next;
62         struct _counter_printer_0 *prev;
63
64         int snum;
65         uint32_t counter;
66 } counter_printer_0;
67
68 static counter_printer_0 *counter_list;
69
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
72
73
74 /* in printing/nt_printing.c */
75
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
77
78 /* API table for Xcv Monitor functions */
79
80 struct xcv_api_table {
81         const char *name;
82         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 };
84
85 /********************************************************************
86  * Canonicalize servername.
87  ********************************************************************/
88
89 static const char *canon_servername(const char *servername)
90 {
91         const char *pservername = servername;
92         while (*pservername == '\\') {
93                 pservername++;
94         }
95         return pservername;
96 }
97
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
100 {
101         switch (v) {
102         case LPQ_QUEUED:
103                 return 0;
104         case LPQ_PAUSED:
105                 return JOB_STATUS_PAUSED;
106         case LPQ_SPOOLING:
107                 return JOB_STATUS_SPOOLING;
108         case LPQ_PRINTING:
109                 return JOB_STATUS_PRINTING;
110         case LPQ_ERROR:
111                 return JOB_STATUS_ERROR;
112         case LPQ_DELETING:
113                 return JOB_STATUS_DELETING;
114         case LPQ_OFFLINE:
115                 return JOB_STATUS_OFFLINE;
116         case LPQ_PAPEROUT:
117                 return JOB_STATUS_PAPEROUT;
118         case LPQ_PRINTED:
119                 return JOB_STATUS_PRINTED;
120         case LPQ_DELETED:
121                 return JOB_STATUS_DELETED;
122         case LPQ_BLOCKED:
123                 return JOB_STATUS_BLOCKED_DEVQ;
124         case LPQ_USER_INTERVENTION:
125                 return JOB_STATUS_USER_INTERVENTION;
126         }
127         return 0;
128 }
129
130 static int nt_printq_status(int v)
131 {
132         switch (v) {
133         case LPQ_PAUSED:
134                 return PRINTER_STATUS_PAUSED;
135         case LPQ_QUEUED:
136         case LPQ_SPOOLING:
137         case LPQ_PRINTING:
138                 return 0;
139         }
140         return 0;
141 }
142
143 /***************************************************************************
144  Disconnect from the client
145 ****************************************************************************/
146
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
148 {
149         WERROR result;
150         NTSTATUS status;
151
152         /*
153          * Tell the specific printing tdb we no longer want messages for this printer
154          * by deregistering our PID.
155          */
156
157         if (!print_notify_deregister_pid(snum))
158                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
159
160         /* weird if the test succeds !!! */
161         if (smb_connections==0) {
162                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
163                 return;
164         }
165
166         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167                                                   handle,
168                                                   &result);
169         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171                         win_errstr(result)));
172
173         /* if it's the last connection, deconnect the IPC$ share */
174         if (smb_connections==1) {
175
176                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
178
179                 messaging_deregister(smbd_messaging_context(),
180                                      MSG_PRINTER_NOTIFY2, NULL);
181
182                 /* Tell the connections db we're no longer interested in
183                  * printer notify messages. */
184
185                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
186         }
187
188         smb_connections--;
189 }
190
191 /****************************************************************************
192  Functions to free a printer entry datastruct.
193 ****************************************************************************/
194
195 static int printer_entry_destructor(Printer_entry *Printer)
196 {
197         if (Printer->notify.client_connected == true) {
198                 int snum = -1;
199
200                 if ( Printer->printer_type == SPLHND_SERVER) {
201                         snum = -1;
202                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203                 } else if (Printer->printer_type == SPLHND_PRINTER) {
204                         snum = print_queue_snum(Printer->sharename);
205                         if (snum != -1)
206                                 srv_spoolss_replycloseprinter(snum,
207                                                 &Printer->notify.client_hnd);
208                 }
209         }
210
211         Printer->notify.flags=0;
212         Printer->notify.options=0;
213         Printer->notify.localmachine[0]='\0';
214         Printer->notify.printerlocal=0;
215         TALLOC_FREE(Printer->notify.option);
216         Printer->notify.client_connected = false;
217
218         free_nt_devicemode( &Printer->nt_devmode );
219         free_a_printer( &Printer->printer_info, 2 );
220
221         /* Remove from the internal list. */
222         DLIST_REMOVE(printers_list, Printer);
223         return 0;
224 }
225
226 /****************************************************************************
227   find printer index by handle
228 ****************************************************************************/
229
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231                                                 struct policy_handle *hnd)
232 {
233         Printer_entry *find_printer = NULL;
234
235         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
237                 return NULL;
238         }
239
240         return find_printer;
241 }
242
243 /****************************************************************************
244  Close printer index by handle.
245 ****************************************************************************/
246
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
248 {
249         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250
251         if (!Printer) {
252                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
253                         OUR_HANDLE(hnd)));
254                 return false;
255         }
256
257         close_policy_hnd(p, hnd);
258
259         return true;
260 }
261
262 /****************************************************************************
263  Delete a printer given a handle.
264 ****************************************************************************/
265
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
267 {
268         char *cmd = lp_deleteprinter_cmd();
269         char *command = NULL;
270         int ret;
271         SE_PRIV se_printop = SE_PRINT_OPERATOR;
272         bool is_print_op = false;
273
274         /* can't fail if we don't try */
275
276         if ( !*cmd )
277                 return WERR_OK;
278
279         command = talloc_asprintf(ctx,
280                         "%s \"%s\"",
281                         cmd, sharename);
282         if (!command) {
283                 return WERR_NOMEM;
284         }
285         if ( token )
286                 is_print_op = user_has_privileges( token, &se_printop );
287
288         DEBUG(10,("Running [%s]\n", command));
289
290         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
291
292         if ( is_print_op )
293                 become_root();
294
295         if ( (ret = smbrun(command, NULL)) == 0 ) {
296                 /* Tell everyone we updated smb.conf. */
297                 message_send_all(smbd_messaging_context(),
298                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
299         }
300
301         if ( is_print_op )
302                 unbecome_root();
303
304         /********** END SePrintOperatorPrivlege BLOCK **********/
305
306         DEBUGADD(10,("returned [%d]\n", ret));
307
308         TALLOC_FREE(command);
309
310         if (ret != 0)
311                 return WERR_BADFID; /* What to return here? */
312
313         /* go ahead and re-read the services immediately */
314         become_root();
315         reload_services(false);
316         unbecome_root();
317
318         if ( lp_servicenumber( sharename )  < 0 )
319                 return WERR_ACCESS_DENIED;
320
321         return WERR_OK;
322 }
323
324 /****************************************************************************
325  Delete a printer given a handle.
326 ****************************************************************************/
327
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
329 {
330         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331
332         if (!Printer) {
333                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
334                         OUR_HANDLE(hnd)));
335                 return WERR_BADFID;
336         }
337
338         /*
339          * It turns out that Windows allows delete printer on a handle
340          * opened by an admin user, then used on a pipe handle created
341          * by an anonymous user..... but they're working on security.... riiight !
342          * JRA.
343          */
344
345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347                 return WERR_ACCESS_DENIED;
348         }
349
350         /* this does not need a become root since the access check has been
351            done on the handle already */
352
353         if (del_a_printer( Printer->sharename ) != 0) {
354                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
355                 return WERR_BADFID;
356         }
357
358         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359                                    Printer->sharename );
360 }
361
362 /****************************************************************************
363  Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
365
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367                              int *number, struct share_params **params)
368 {
369         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370
371         if (!Printer) {
372                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
373                         OUR_HANDLE(hnd)));
374                 return false;
375         }
376
377         switch (Printer->printer_type) {
378                 case SPLHND_PRINTER:
379                         DEBUG(4,("short name:%s\n", Printer->sharename));
380                         *number = print_queue_snum(Printer->sharename);
381                         return (*number != -1);
382                 case SPLHND_SERVER:
383                         return false;
384                 default:
385                         return false;
386         }
387 }
388
389 /****************************************************************************
390  Set printer handle type.
391  Check if it's \\server or \\server\printer
392 ****************************************************************************/
393
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
395 {
396         DEBUG(3,("Setting printer type=%s\n", handlename));
397
398         if ( strlen(handlename) < 3 ) {
399                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
400                 return false;
401         }
402
403         /* it's a print server */
404         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405                 DEBUGADD(4,("Printer is a print server\n"));
406                 Printer->printer_type = SPLHND_SERVER;
407         }
408         /* it's a printer (set_printer_hnd_name() will handle port monitors */
409         else {
410                 DEBUGADD(4,("Printer is a printer\n"));
411                 Printer->printer_type = SPLHND_PRINTER;
412         }
413
414         return true;
415 }
416
417 /****************************************************************************
418  Set printer handle name..  Accept names like \\server, \\server\printer,
419  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
420  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421  XcvDataPort() interface.
422 ****************************************************************************/
423
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 {
426         int snum;
427         int n_services=lp_numservices();
428         char *aprinter, *printername;
429         const char *servername;
430         fstring sname;
431         bool found = false;
432         NT_PRINTER_INFO_LEVEL *printer = NULL;
433         WERROR result;
434
435         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436                 (unsigned long)strlen(handlename)));
437
438         aprinter = CONST_DISCARD(char *, handlename);
439         if ( *handlename == '\\' ) {
440                 servername = canon_servername(handlename);
441                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
442                         *aprinter = '\0';
443                         aprinter++;
444                 }
445         } else {
446                 servername = global_myname();
447         }
448
449         /* save the servername to fill in replies on this handle */
450
451         if ( !is_myname_or_ipaddr( servername ) )
452                 return false;
453
454         fstrcpy( Printer->servername, servername );
455
456         if ( Printer->printer_type == SPLHND_SERVER )
457                 return true;
458
459         if ( Printer->printer_type != SPLHND_PRINTER )
460                 return false;
461
462         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
463
464         /* check for the Port Monitor Interface */
465
466         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467                 Printer->printer_type = SPLHND_PORTMON_TCP;
468                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469                 found = true;
470         }
471         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
474                 found = true;
475         }
476
477         /* Search all sharenames first as this is easier than pulling
478            the printer_info_2 off of disk. Don't use find_service() since
479            that calls out to map_username() */
480
481         /* do another loop to look for printernames */
482
483         for (snum=0; !found && snum<n_services; snum++) {
484
485                 /* no point going on if this is not a printer */
486
487                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488                         continue;
489
490                 fstrcpy(sname, lp_servicename(snum));
491                 if ( strequal( aprinter, sname ) ) {
492                         found = true;
493                         break;
494                 }
495
496                 /* no point looking up the printer object if
497                    we aren't allowing printername != sharename */
498
499                 if ( lp_force_printername(snum) )
500                         continue;
501
502                 fstrcpy(sname, lp_servicename(snum));
503
504                 printer = NULL;
505
506                 /* This call doesn't fill in the location or comment from
507                  * a CUPS server for efficiency with large numbers of printers.
508                  * JRA.
509                  */
510
511                 result = get_a_printer_search( NULL, &printer, 2, sname );
512                 if ( !W_ERROR_IS_OK(result) ) {
513                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514                                 sname, win_errstr(result)));
515                         continue;
516                 }
517
518                 /* printername is always returned as \\server\printername */
519                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521                                 printer->info_2->printername));
522                         free_a_printer( &printer, 2);
523                         continue;
524                 }
525
526                 printername++;
527
528                 if ( strequal(printername, aprinter) ) {
529                         free_a_printer( &printer, 2);
530                         found = true;
531                         break;
532                 }
533
534                 DEBUGADD(10, ("printername: %s\n", printername));
535
536                 free_a_printer( &printer, 2);
537         }
538
539         free_a_printer( &printer, 2);
540
541         if ( !found ) {
542                 DEBUGADD(4,("Printer not found\n"));
543                 return false;
544         }
545
546         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
547
548         fstrcpy(Printer->sharename, sname);
549
550         return true;
551 }
552
553 /****************************************************************************
554  Find first available printer slot. creates a printer handle for you.
555  ****************************************************************************/
556
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558                              const char *name, uint32_t access_granted)
559 {
560         Printer_entry *new_printer;
561
562         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
563
564         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565         if (new_printer == NULL) {
566                 return false;
567         }
568         talloc_set_destructor(new_printer, printer_entry_destructor);
569
570         if (!create_policy_hnd(p, hnd, new_printer)) {
571                 TALLOC_FREE(new_printer);
572                 return false;
573         }
574
575         /* Add to the internal list. */
576         DLIST_ADD(printers_list, new_printer);
577
578         new_printer->notify.option=NULL;
579
580         if (!set_printer_hnd_printertype(new_printer, name)) {
581                 close_printer_handle(p, hnd);
582                 return false;
583         }
584
585         if (!set_printer_hnd_name(new_printer, name)) {
586                 close_printer_handle(p, hnd);
587                 return false;
588         }
589
590         new_printer->access_granted = access_granted;
591
592         DEBUG(5, ("%d printer handles active\n",
593                   (int)num_pipe_handles(p->pipe_handles)));
594
595         return true;
596 }
597
598 /***************************************************************************
599  check to see if the client motify handle is monitoring the notification
600  given by (notify_type, notify_field).
601  **************************************************************************/
602
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604                                       uint16_t notify_field)
605 {
606         return true;
607 }
608
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610                                 uint16_t notify_field)
611 {
612         struct spoolss_NotifyOption *option = p->notify.option;
613         uint32_t i, j;
614
615         /*
616          * Flags should always be zero when the change notify
617          * is registered by the client's spooler.  A user Win32 app
618          * might use the flags though instead of the NOTIFY_OPTION_INFO
619          * --jerry
620          */
621
622         if (!option) {
623                 return false;
624         }
625
626         if (p->notify.flags)
627                 return is_monitoring_event_flags(
628                         p->notify.flags, notify_type, notify_field);
629
630         for (i = 0; i < option->count; i++) {
631
632                 /* Check match for notify_type */
633
634                 if (option->types[i].type != notify_type)
635                         continue;
636
637                 /* Check match for field */
638
639                 for (j = 0; j < option->types[i].count; j++) {
640                         if (option->types[i].fields[j].field == notify_field) {
641                                 return true;
642                         }
643                 }
644         }
645
646         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647                    p->servername, p->sharename, notify_type, notify_field));
648
649         return false;
650 }
651
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653         _data->data.integer[0] = _integer; \
654         _data->data.integer[1] = 0;
655
656
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659         if (!_data->data.string.string) {\
660                 _data->data.string.size = 0; \
661         } \
662         _data->data.string.size = strlen_m_term(_p) * 2;
663
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665         _data->data.devmode.devmode = _devmode;
666
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669         if (!_data->data.sd.sd) { \
670                 _data->data.sd.sd_size = 0; \
671         } \
672         _data->data.sd.sd_size = _size;
673
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
675                                    struct tm *t,
676                                    const char **pp,
677                                    uint32_t *plen)
678 {
679         struct spoolss_Time st;
680         uint32_t len = 16;
681         char *p;
682
683         if (!init_systemtime(&st, t)) {
684                 return;
685         }
686
687         p = talloc_array(mem_ctx, char, len);
688         if (!p) {
689                 return;
690         }
691
692         /*
693          * Systemtime must be linearized as a set of UINT16's.
694          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695          */
696
697         SSVAL(p, 0, st.year);
698         SSVAL(p, 2, st.month);
699         SSVAL(p, 4, st.day_of_week);
700         SSVAL(p, 6, st.day);
701         SSVAL(p, 8, st.hour);
702         SSVAL(p, 10, st.minute);
703         SSVAL(p, 12, st.second);
704         SSVAL(p, 14, st.millisecond);
705
706         *pp = p;
707         *plen = len;
708 }
709
710 /* Convert a notification message to a struct spoolss_Notify */
711
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713                              struct spoolss_Notify *data,
714                              TALLOC_CTX *mem_ctx)
715 {
716         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 }
718
719 static void notify_string(struct spoolss_notify_msg *msg,
720                           struct spoolss_Notify *data,
721                           TALLOC_CTX *mem_ctx)
722 {
723         /* The length of the message includes the trailing \0 */
724
725         data->data.string.size = msg->len * 2;
726         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727         if (!data->data.string.string) {
728                 data->data.string.size = 0;
729                 return;
730         }
731 }
732
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734                                struct spoolss_Notify *data,
735                                TALLOC_CTX *mem_ctx)
736 {
737         data->data.string.string = NULL;
738         data->data.string.size = 0;
739
740         if (msg->len != sizeof(time_t)) {
741                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
742                           msg->len));
743                 return;
744         }
745
746         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747                                &data->data.string.string,
748                                &data->data.string.size);
749 }
750
751 struct notify2_message_table {
752         const char *name;
753         void (*fn)(struct spoolss_notify_msg *msg,
754                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 };
756
757 static struct notify2_message_table printer_notify_table[] = {
758         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 };
778
779 static struct notify2_message_table job_notify_table[] = {
780         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
804 };
805
806
807 /***********************************************************************
808  Allocate talloc context for container object
809  **********************************************************************/
810
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 {
813         if ( !ctr )
814                 return;
815
816         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817
818         return;
819 }
820
821 /***********************************************************************
822  release all allocated memory and zero out structure
823  **********************************************************************/
824
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 {
827         if ( !ctr )
828                 return;
829
830         if ( ctr->ctx )
831                 talloc_destroy(ctr->ctx);
832
833         ZERO_STRUCTP(ctr);
834
835         return;
836 }
837
838 /***********************************************************************
839  **********************************************************************/
840
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 {
843         if ( !ctr )
844                 return NULL;
845
846         return ctr->ctx;
847 }
848
849 /***********************************************************************
850  **********************************************************************/
851
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
853 {
854         if ( !ctr || !ctr->msg_groups )
855                 return NULL;
856
857         if ( idx >= ctr->num_groups )
858                 return NULL;
859
860         return &ctr->msg_groups[idx];
861
862 }
863
864 /***********************************************************************
865  How many groups of change messages do we have ?
866  **********************************************************************/
867
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 {
870         if ( !ctr )
871                 return 0;
872
873         return ctr->num_groups;
874 }
875
876 /***********************************************************************
877  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878  **********************************************************************/
879
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 {
882         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
883         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
884         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
885         int                             i, new_slot;
886
887         if ( !ctr || !msg )
888                 return 0;
889
890         /* loop over all groups looking for a matching printer name */
891
892         for ( i=0; i<ctr->num_groups; i++ ) {
893                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
894                         break;
895         }
896
897         /* add a new group? */
898
899         if ( i == ctr->num_groups ) {
900                 ctr->num_groups++;
901
902                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904                         return 0;
905                 }
906                 ctr->msg_groups = groups;
907
908                 /* clear the new entry and set the printer name */
909
910                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912         }
913
914         /* add the change messages; 'i' is the correct index now regardless */
915
916         msg_grp = &ctr->msg_groups[i];
917
918         msg_grp->num_msgs++;
919
920         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922                 return 0;
923         }
924         msg_grp->msgs = msg_list;
925
926         new_slot = msg_grp->num_msgs-1;
927         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928
929         /* need to allocate own copy of data */
930
931         if ( msg->len != 0 )
932                 msg_grp->msgs[new_slot].notify.data = (char *)
933                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934
935         return ctr->num_groups;
936 }
937
938 /***********************************************************************
939  Send a change notication message on all handles which have a call
940  back registered
941  **********************************************************************/
942
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 {
945         Printer_entry            *p;
946         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
947         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948         SPOOLSS_NOTIFY_MSG       *messages;
949         int                      sending_msg_count;
950
951         if ( !msg_group ) {
952                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
953                 return;
954         }
955
956         messages = msg_group->msgs;
957
958         if ( !messages ) {
959                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
960                 return;
961         }
962
963         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964
965         /* loop over all printers */
966
967         for (p = printers_list; p; p = p->next) {
968                 struct spoolss_Notify *notifies;
969                 uint32_t count = 0;
970                 uint32_t id;
971                 int     i;
972
973                 /* Is there notification on this handle? */
974
975                 if ( !p->notify.client_connected )
976                         continue;
977
978                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979
980                 /* For this printer?  Print servers always receive
981                    notifications. */
982
983                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
984                     ( !strequal(msg_group->printername, p->sharename) ) )
985                         continue;
986
987                 DEBUG(10,("Our printer\n"));
988
989                 /* allocate the max entries possible */
990
991                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
992                 if (!notifies) {
993                         return;
994                 }
995
996                 /* build the array of change notifications */
997
998                 sending_msg_count = 0;
999
1000                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1002
1003                         /* Are we monitoring this event? */
1004
1005                         if (!is_monitoring_event(p, msg->type, msg->field))
1006                                 continue;
1007
1008                         sending_msg_count++;
1009
1010
1011                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012                                 msg->type, msg->field, p->sharename));
1013
1014                         /*
1015                          * if the is a printer notification handle and not a job notification
1016                          * type, then set the id to 0.  Other wise just use what was specified
1017                          * in the message.
1018                          *
1019                          * When registering change notification on a print server handle
1020                          * we always need to send back the id (snum) matching the printer
1021                          * for which the change took place.  For change notify registered
1022                          * on a printer handle, this does not matter and the id should be 0.
1023                          *
1024                          * --jerry
1025                          */
1026
1027                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1028                                 id = 0;
1029                         else
1030                                 id = msg->id;
1031
1032
1033                         /* Convert unix jobid to smb jobid */
1034
1035                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036                                 id = sysjob_to_jobid(msg->id);
1037
1038                                 if (id == -1) {
1039                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1040                                         goto done;
1041                                 }
1042                         }
1043
1044                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1045
1046                         switch(msg->type) {
1047                         case PRINTER_NOTIFY_TYPE:
1048                                 if ( printer_notify_table[msg->field].fn )
1049                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1050                                 break;
1051
1052                         case JOB_NOTIFY_TYPE:
1053                                 if ( job_notify_table[msg->field].fn )
1054                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1055                                 break;
1056
1057                         default:
1058                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1059                                 goto done;
1060                         }
1061
1062                         count++;
1063                 }
1064
1065                 if ( sending_msg_count ) {
1066                         NTSTATUS status;
1067                         WERROR werr;
1068                         union spoolss_ReplyPrinterInfo info;
1069                         struct spoolss_NotifyInfo info0;
1070                         uint32_t reply_result;
1071
1072                         info0.version   = 0x2;
1073                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074                         info0.count     = count;
1075                         info0.notifies  = notifies;
1076
1077                         info.info0 = &info0;
1078
1079                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080                                                                      &p->notify.client_hnd,
1081                                                                      p->notify.change, /* color */
1082                                                                      p->notify.flags,
1083                                                                      &reply_result,
1084                                                                      0, /* reply_type, must be 0 */
1085                                                                      info,
1086                                                                      &werr);
1087                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089                                         notify_cli_pipe->srv_name_slash,
1090                                         win_errstr(werr)));
1091                         }
1092                         switch (reply_result) {
1093                                 case 0:
1094                                         break;
1095                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1096                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1098                                         break;
1099                                 default:
1100                                         break;
1101                         }
1102                 }
1103         }
1104
1105 done:
1106         DEBUG(8,("send_notify2_changes: Exit...\n"));
1107         return;
1108 }
1109
1110 /***********************************************************************
1111  **********************************************************************/
1112
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 {
1115
1116         uint32_t tv_sec, tv_usec;
1117         size_t offset = 0;
1118
1119         /* Unpack message */
1120
1121         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122                              msg->printer);
1123
1124         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1125                                 &tv_sec, &tv_usec,
1126                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127
1128         if (msg->len == 0)
1129                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130                            &msg->notify.value[0], &msg->notify.value[1]);
1131         else
1132                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133                            &msg->len, &msg->notify.data);
1134
1135         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1137
1138         tv->tv_sec = tv_sec;
1139         tv->tv_usec = tv_usec;
1140
1141         if (msg->len == 0)
1142                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143                           msg->notify.value[1]));
1144         else
1145                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1146
1147         return true;
1148 }
1149
1150 /********************************************************************
1151  Receive a notify2 message list
1152  ********************************************************************/
1153
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1155                                          void *private_data,
1156                                          uint32_t msg_type,
1157                                          struct server_id server_id,
1158                                          DATA_BLOB *data)
1159 {
1160         size_t                  msg_count, i;
1161         char                    *buf = (char *)data->data;
1162         char                    *msg_ptr;
1163         size_t                  msg_len;
1164         SPOOLSS_NOTIFY_MSG      notify;
1165         SPOOLSS_NOTIFY_MSG_CTR  messages;
1166         int                     num_groups;
1167
1168         if (data->length < 4) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1170                 return;
1171         }
1172
1173         msg_count = IVAL(buf, 0);
1174         msg_ptr = buf + 4;
1175
1176         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1177
1178         if (msg_count == 0) {
1179                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1180                 return;
1181         }
1182
1183         /* initialize the container */
1184
1185         ZERO_STRUCT( messages );
1186         notify_msg_ctr_init( &messages );
1187
1188         /*
1189          * build message groups for each printer identified
1190          * in a change_notify msg.  Remember that a PCN message
1191          * includes the handle returned for the srv_spoolss_replyopenprinter()
1192          * call.  Therefore messages are grouped according to printer handle.
1193          */
1194
1195         for ( i=0; i<msg_count; i++ ) {
1196                 struct timeval msg_tv;
1197
1198                 if (msg_ptr + 4 - buf > data->length) {
1199                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1200                         return;
1201                 }
1202
1203                 msg_len = IVAL(msg_ptr,0);
1204                 msg_ptr += 4;
1205
1206                 if (msg_ptr + msg_len - buf > data->length) {
1207                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1208                         return;
1209                 }
1210
1211                 /* unpack messages */
1212
1213                 ZERO_STRUCT( notify );
1214                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1215                 msg_ptr += msg_len;
1216
1217                 /* add to correct list in container */
1218
1219                 notify_msg_ctr_addmsg( &messages, &notify );
1220
1221                 /* free memory that might have been allocated by notify2_unpack_msg() */
1222
1223                 if ( notify.len != 0 )
1224                         SAFE_FREE( notify.notify.data );
1225         }
1226
1227         /* process each group of messages */
1228
1229         num_groups = notify_msg_ctr_numgroups( &messages );
1230         for ( i=0; i<num_groups; i++ )
1231                 send_notify2_changes( &messages, i );
1232
1233
1234         /* cleanup */
1235
1236         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237                 (uint32_t)msg_count ));
1238
1239         notify_msg_ctr_destroy( &messages );
1240
1241         return;
1242 }
1243
1244 /********************************************************************
1245  Send a message to ourself about new driver being installed
1246  so we can upgrade the information for each printer bound to this
1247  driver
1248  ********************************************************************/
1249
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1251 {
1252         int len = strlen(drivername);
1253
1254         if (!len)
1255                 return false;
1256
1257         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258                 drivername));
1259
1260         messaging_send_buf(smbd_messaging_context(), procid_self(),
1261                            MSG_PRINTER_DRVUPGRADE,
1262                            (uint8_t *)drivername, len+1);
1263
1264         return true;
1265 }
1266
1267 /**********************************************************************
1268  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269  over all printers, upgrading ones as necessary
1270  **********************************************************************/
1271
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1273                             void *private_data,
1274                             uint32_t msg_type,
1275                             struct server_id server_id,
1276                             DATA_BLOB *data)
1277 {
1278         fstring drivername;
1279         int snum;
1280         int n_services = lp_numservices();
1281         size_t len;
1282
1283         len = MIN(data->length,sizeof(drivername)-1);
1284         strncpy(drivername, (const char *)data->data, len);
1285
1286         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1287
1288         /* Iterate the printer list */
1289
1290         for (snum=0; snum<n_services; snum++)
1291         {
1292                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293                 {
1294                         WERROR result;
1295                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1296
1297                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298                         if (!W_ERROR_IS_OK(result))
1299                                 continue;
1300
1301                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1302                         {
1303                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1304
1305                                 /* all we care about currently is the change_id */
1306
1307                                 result = mod_a_printer(printer, 2);
1308                                 if (!W_ERROR_IS_OK(result)) {
1309                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310                                                 win_errstr(result)));
1311                                 }
1312                         }
1313
1314                         free_a_printer(&printer, 2);
1315                 }
1316         }
1317
1318         /* all done */
1319 }
1320
1321 /********************************************************************
1322  Update the cache for all printq's with a registered client
1323  connection
1324  ********************************************************************/
1325
1326 void update_monitored_printq_cache( void )
1327 {
1328         Printer_entry *printer = printers_list;
1329         int snum;
1330
1331         /* loop through all printers and update the cache where
1332            client_connected == true */
1333         while ( printer )
1334         {
1335                 if ( (printer->printer_type == SPLHND_PRINTER)
1336                         && printer->notify.client_connected )
1337                 {
1338                         snum = print_queue_snum(printer->sharename);
1339                         print_queue_status( snum, NULL, NULL );
1340                 }
1341
1342                 printer = printer->next;
1343         }
1344
1345         return;
1346 }
1347 /********************************************************************
1348  Send a message to ourself about new driver being installed
1349  so we can upgrade the information for each printer bound to this
1350  driver
1351  ********************************************************************/
1352
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1354 {
1355         int len = strlen(drivername);
1356
1357         if (!len)
1358                 return false;
1359
1360         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361                 drivername));
1362
1363         messaging_send_buf(smbd_messaging_context(), procid_self(),
1364                            MSG_PRINTERDATA_INIT_RESET,
1365                            (uint8_t *)drivername, len+1);
1366
1367         return true;
1368 }
1369
1370 /**********************************************************************
1371  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372  over all printers, resetting printer data as neessary
1373  **********************************************************************/
1374
1375 void reset_all_printerdata(struct messaging_context *msg,
1376                            void *private_data,
1377                            uint32_t msg_type,
1378                            struct server_id server_id,
1379                            DATA_BLOB *data)
1380 {
1381         fstring drivername;
1382         int snum;
1383         int n_services = lp_numservices();
1384         size_t len;
1385
1386         len = MIN( data->length, sizeof(drivername)-1 );
1387         strncpy( drivername, (const char *)data->data, len );
1388
1389         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1390
1391         /* Iterate the printer list */
1392
1393         for ( snum=0; snum<n_services; snum++ )
1394         {
1395                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396                 {
1397                         WERROR result;
1398                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1399
1400                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401                         if ( !W_ERROR_IS_OK(result) )
1402                                 continue;
1403
1404                         /*
1405                          * if the printer is bound to the driver,
1406                          * then reset to the new driver initdata
1407                          */
1408
1409                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1410                         {
1411                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1412
1413                                 if ( !set_driver_init(printer, 2) ) {
1414                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415                                                 printer->info_2->printername, printer->info_2->drivername));
1416                                 }
1417
1418                                 result = mod_a_printer( printer, 2 );
1419                                 if ( !W_ERROR_IS_OK(result) ) {
1420                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1421                                                 get_dos_error_msg(result)));
1422                                 }
1423                         }
1424
1425                         free_a_printer( &printer, 2 );
1426                 }
1427         }
1428
1429         /* all done */
1430
1431         return;
1432 }
1433
1434 /****************************************************************
1435  _spoolss_OpenPrinter
1436 ****************************************************************/
1437
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439                             struct spoolss_OpenPrinter *r)
1440 {
1441         struct spoolss_OpenPrinterEx e;
1442         WERROR werr;
1443
1444         ZERO_STRUCT(e.in.userlevel);
1445
1446         e.in.printername        = r->in.printername;
1447         e.in.datatype           = r->in.datatype;
1448         e.in.devmode_ctr        = r->in.devmode_ctr;
1449         e.in.access_mask        = r->in.access_mask;
1450         e.in.level              = 0;
1451
1452         e.out.handle            = r->out.handle;
1453
1454         werr = _spoolss_OpenPrinterEx(p, &e);
1455
1456         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457                 /* OpenPrinterEx returns this for a bad
1458                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1459                  * instead.
1460                  */
1461                 werr = WERR_INVALID_PRINTER_NAME;
1462         }
1463
1464         return werr;
1465 }
1466
1467 /********************************************************************
1468  ********************************************************************/
1469
1470 bool convert_devicemode(const char *printername,
1471                         const struct spoolss_DeviceMode *devmode,
1472                         NT_DEVICEMODE **pp_nt_devmode)
1473 {
1474         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475
1476         /*
1477          * Ensure nt_devmode is a valid pointer
1478          * as we will be overwriting it.
1479          */
1480
1481         if (nt_devmode == NULL) {
1482                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1484                         return false;
1485         }
1486
1487         fstrcpy(nt_devmode->devicename, devmode->devicename);
1488         fstrcpy(nt_devmode->formname, devmode->formname);
1489
1490         nt_devmode->devicename[31] = '\0';
1491         nt_devmode->formname[31] = '\0';
1492
1493         nt_devmode->specversion         = devmode->specversion;
1494         nt_devmode->driverversion       = devmode->driverversion;
1495         nt_devmode->size                = devmode->size;
1496         nt_devmode->fields              = devmode->fields;
1497         nt_devmode->orientation         = devmode->orientation;
1498         nt_devmode->papersize           = devmode->papersize;
1499         nt_devmode->paperlength         = devmode->paperlength;
1500         nt_devmode->paperwidth          = devmode->paperwidth;
1501         nt_devmode->scale               = devmode->scale;
1502         nt_devmode->copies              = devmode->copies;
1503         nt_devmode->defaultsource       = devmode->defaultsource;
1504         nt_devmode->printquality        = devmode->printquality;
1505         nt_devmode->color               = devmode->color;
1506         nt_devmode->duplex              = devmode->duplex;
1507         nt_devmode->yresolution         = devmode->yresolution;
1508         nt_devmode->ttoption            = devmode->ttoption;
1509         nt_devmode->collate             = devmode->collate;
1510
1511         nt_devmode->logpixels           = devmode->logpixels;
1512         nt_devmode->bitsperpel          = devmode->bitsperpel;
1513         nt_devmode->pelswidth           = devmode->pelswidth;
1514         nt_devmode->pelsheight          = devmode->pelsheight;
1515         nt_devmode->displayflags        = devmode->displayflags;
1516         nt_devmode->displayfrequency    = devmode->displayfrequency;
1517         nt_devmode->icmmethod           = devmode->icmmethod;
1518         nt_devmode->icmintent           = devmode->icmintent;
1519         nt_devmode->mediatype           = devmode->mediatype;
1520         nt_devmode->dithertype          = devmode->dithertype;
1521         nt_devmode->reserved1           = devmode->reserved1;
1522         nt_devmode->reserved2           = devmode->reserved2;
1523         nt_devmode->panningwidth        = devmode->panningwidth;
1524         nt_devmode->panningheight       = devmode->panningheight;
1525
1526         /*
1527          * Only change private and driverextra if the incoming devmode
1528          * has a new one. JRA.
1529          */
1530
1531         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532                 SAFE_FREE(nt_devmode->nt_dev_private);
1533                 nt_devmode->driverextra = devmode->__driverextra_length;
1534                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1535                         return false;
1536                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1537         }
1538
1539         *pp_nt_devmode = nt_devmode;
1540
1541         return true;
1542 }
1543
1544 /****************************************************************
1545  _spoolss_OpenPrinterEx
1546 ****************************************************************/
1547
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549                               struct spoolss_OpenPrinterEx *r)
1550 {
1551         int snum;
1552         Printer_entry *Printer=NULL;
1553
1554         if (!r->in.printername) {
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         /* some sanity check because you can open a printer or a print server */
1559         /* aka: \\server\printer or \\server */
1560
1561         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1562
1563         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564                 ZERO_STRUCTP(r->out.handle);
1565                 return WERR_INVALID_PARAM;
1566         }
1567
1568         Printer = find_printer_index_by_hnd(p, r->out.handle);
1569         if ( !Printer ) {
1570                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1571                         "handle we created for printer %s\n", r->in.printername));
1572                 close_printer_handle(p, r->out.handle);
1573                 ZERO_STRUCTP(r->out.handle);
1574                 return WERR_INVALID_PARAM;
1575         }
1576
1577         /*
1578          * First case: the user is opening the print server:
1579          *
1580          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1582          *
1583          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585          * or if the user is listed in the smb.conf printer admin parameter.
1586          *
1587          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588          * client view printer folder, but does not show the MSAPW.
1589          *
1590          * Note: this test needs code to check access rights here too. Jeremy
1591          * could you look at this?
1592          *
1593          * Second case: the user is opening a printer:
1594          * NT doesn't let us connect to a printer if the connecting user
1595          * doesn't have print permission.
1596          *
1597          * Third case: user is opening a Port Monitor
1598          * access checks same as opening a handle to the print server.
1599          */
1600
1601         switch (Printer->printer_type )
1602         {
1603         case SPLHND_SERVER:
1604         case SPLHND_PORTMON_TCP:
1605         case SPLHND_PORTMON_LOCAL:
1606                 /* Printserver handles use global struct... */
1607
1608                 snum = -1;
1609
1610                 /* Map standard access rights to object specific access rights */
1611
1612                 se_map_standard(&r->in.access_mask,
1613                                 &printserver_std_mapping);
1614
1615                 /* Deny any object specific bits that don't apply to print
1616                    servers (i.e printer and job specific bits) */
1617
1618                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1619
1620                 if (r->in.access_mask &
1621                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623                         close_printer_handle(p, r->out.handle);
1624                         ZERO_STRUCTP(r->out.handle);
1625                         return WERR_ACCESS_DENIED;
1626                 }
1627
1628                 /* Allow admin access */
1629
1630                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1631                 {
1632                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1633
1634                         if (!lp_ms_add_printer_wizard()) {
1635                                 close_printer_handle(p, r->out.handle);
1636                                 ZERO_STRUCTP(r->out.handle);
1637                                 return WERR_ACCESS_DENIED;
1638                         }
1639
1640                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641                            and not a printer admin, then fail */
1642
1643                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644                             !user_has_privileges(p->server_info->ptok,
1645                                                  &se_printop ) &&
1646                             !token_contains_name_in_list(
1647                                     uidtoname(p->server_info->utok.uid),
1648                                     NULL, NULL,
1649                                     p->server_info->ptok,
1650                                     lp_printer_admin(snum))) {
1651                                 close_printer_handle(p, r->out.handle);
1652                                 ZERO_STRUCTP(r->out.handle);
1653                                 return WERR_ACCESS_DENIED;
1654                         }
1655
1656                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1657                 }
1658                 else
1659                 {
1660                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1661                 }
1662
1663                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1665
1666                 /* We fall through to return WERR_OK */
1667                 break;
1668
1669         case SPLHND_PRINTER:
1670                 /* NT doesn't let us connect to a printer if the connecting user
1671                    doesn't have print permission.  */
1672
1673                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674                         close_printer_handle(p, r->out.handle);
1675                         ZERO_STRUCTP(r->out.handle);
1676                         return WERR_BADFID;
1677                 }
1678
1679                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1681                 }
1682
1683                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1684
1685                 /* map an empty access mask to the minimum access mask */
1686                 if (r->in.access_mask == 0x0)
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688
1689                 /*
1690                  * If we are not serving the printer driver for this printer,
1691                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1692                  * will keep NT clients happy  --jerry
1693                  */
1694
1695                 if (lp_use_client_driver(snum)
1696                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1697                 {
1698                         r->in.access_mask = PRINTER_ACCESS_USE;
1699                 }
1700
1701                 /* check smb.conf parameters and the the sec_desc */
1702
1703                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705                         ZERO_STRUCTP(r->out.handle);
1706                         return WERR_ACCESS_DENIED;
1707                 }
1708
1709                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710                                    p->server_info->ptok, snum) ||
1711                     !print_access_check(p->server_info, snum,
1712                                         r->in.access_mask)) {
1713                         DEBUG(3, ("access DENIED for printer open\n"));
1714                         close_printer_handle(p, r->out.handle);
1715                         ZERO_STRUCTP(r->out.handle);
1716                         return WERR_ACCESS_DENIED;
1717                 }
1718
1719                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721                         close_printer_handle(p, r->out.handle);
1722                         ZERO_STRUCTP(r->out.handle);
1723                         return WERR_ACCESS_DENIED;
1724                 }
1725
1726                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1728                 else
1729                         r->in.access_mask = PRINTER_ACCESS_USE;
1730
1731                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1733
1734                 break;
1735
1736         default:
1737                 /* sanity check to prevent programmer error */
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return WERR_BADFID;
1740         }
1741
1742         Printer->access_granted = r->in.access_mask;
1743
1744         /*
1745          * If the client sent a devmode in the OpenPrinter() call, then
1746          * save it here in case we get a job submission on this handle
1747          */
1748
1749          if ((Printer->printer_type != SPLHND_SERVER) &&
1750              r->in.devmode_ctr.devmode) {
1751                 convert_devicemode(Printer->sharename,
1752                                    r->in.devmode_ctr.devmode,
1753                                    &Printer->nt_devmode);
1754          }
1755
1756 #if 0   /* JERRY -- I'm doubtful this is really effective */
1757         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758            optimization in Windows 2000 clients  --jerry */
1759
1760         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761                 && (RA_WIN2K == get_remote_arch()) )
1762         {
1763                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764                 sys_usleep( 500000 );
1765         }
1766 #endif
1767
1768         return WERR_OK;
1769 }
1770
1771 /****************************************************************************
1772 ****************************************************************************/
1773
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775                                               NT_PRINTER_INFO_LEVEL_2 *d)
1776 {
1777         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1778
1779         if (!r || !d) {
1780                 return false;
1781         }
1782
1783         d->attributes           = r->attributes;
1784         d->priority             = r->priority;
1785         d->default_priority     = r->defaultpriority;
1786         d->starttime            = r->starttime;
1787         d->untiltime            = r->untiltime;
1788         d->status               = r->status;
1789         d->cjobs                = r->cjobs;
1790
1791         fstrcpy(d->servername,  r->servername);
1792         fstrcpy(d->printername, r->printername);
1793         fstrcpy(d->sharename,   r->sharename);
1794         fstrcpy(d->portname,    r->portname);
1795         fstrcpy(d->drivername,  r->drivername);
1796         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797         fstrcpy(d->location,    r->location);
1798         fstrcpy(d->sepfile,     r->sepfile);
1799         fstrcpy(d->printprocessor, r->printprocessor);
1800         fstrcpy(d->datatype,    r->datatype);
1801         fstrcpy(d->parameters,  r->parameters);
1802
1803         return true;
1804 }
1805
1806 /****************************************************************************
1807 ****************************************************************************/
1808
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810                                  NT_PRINTER_INFO_LEVEL *printer)
1811 {
1812         bool ret;
1813
1814         switch (info_ctr->level) {
1815         case 2:
1816                 /* allocate memory if needed.  Messy because
1817                    convert_printer_info is used to update an existing
1818                    printer or build a new one */
1819
1820                 if (!printer->info_2) {
1821                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822                         if (!printer->info_2) {
1823                                 DEBUG(0,("convert_printer_info: "
1824                                         "talloc() failed!\n"));
1825                                 return false;
1826                         }
1827                 }
1828
1829                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1830                                                         printer->info_2);
1831                 printer->info_2->setuptime = time(NULL);
1832                 return ret;
1833         }
1834
1835         return false;
1836 }
1837
1838 /****************************************************************
1839  _spoolss_ClosePrinter
1840 ****************************************************************/
1841
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843                              struct spoolss_ClosePrinter *r)
1844 {
1845         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1846
1847         if (Printer && Printer->document_started) {
1848                 struct spoolss_EndDocPrinter e;
1849
1850                 e.in.handle = r->in.handle;
1851
1852                 _spoolss_EndDocPrinter(p, &e);
1853         }
1854
1855         if (!close_printer_handle(p, r->in.handle))
1856                 return WERR_BADFID;
1857
1858         /* clear the returned printer handle.  Observed behavior
1859            from Win2k server.  Don't think this really matters.
1860            Previous code just copied the value of the closed
1861            handle.    --jerry */
1862
1863         ZERO_STRUCTP(r->out.handle);
1864
1865         return WERR_OK;
1866 }
1867
1868 /****************************************************************
1869  _spoolss_DeletePrinter
1870 ****************************************************************/
1871
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873                               struct spoolss_DeletePrinter *r)
1874 {
1875         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1876         WERROR result;
1877
1878         if (Printer && Printer->document_started) {
1879                 struct spoolss_EndDocPrinter e;
1880
1881                 e.in.handle = r->in.handle;
1882
1883                 _spoolss_EndDocPrinter(p, &e);
1884         }
1885
1886         result = delete_printer_handle(p, r->in.handle);
1887
1888         update_c_setprinter(false);
1889
1890         return result;
1891 }
1892
1893 /*******************************************************************
1894  * static function to lookup the version id corresponding to an
1895  * long architecture string
1896  ******************************************************************/
1897
1898 static const struct print_architecture_table_node archi_table[]= {
1899
1900         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1901         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1902         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1903         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1904         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1905         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1906         {"Windows x64",          SPL_ARCH_X64,          3 },
1907         {NULL,                   "",            -1 }
1908 };
1909
1910 static int get_version_id(const char *arch)
1911 {
1912         int i;
1913
1914         for (i=0; archi_table[i].long_archi != NULL; i++)
1915         {
1916                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917                         return (archi_table[i].version);
1918         }
1919
1920         return -1;
1921 }
1922
1923 /****************************************************************
1924  _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1926
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928                                     struct spoolss_DeletePrinterDriver *r)
1929 {
1930
1931         union spoolss_DriverInfo *info = NULL;
1932         union spoolss_DriverInfo *info_win2k = NULL;
1933         int                             version;
1934         WERROR                          status;
1935         WERROR                          status_win2k = WERR_ACCESS_DENIED;
1936         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1937
1938         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1939            and not a printer admin, then fail */
1940
1941         if ( (p->server_info->utok.uid != sec_initial_uid())
1942                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1943                 && !token_contains_name_in_list(
1944                         uidtoname(p->server_info->utok.uid), NULL,
1945                         NULL, p->server_info->ptok,
1946                         lp_printer_admin(-1)) )
1947         {
1948                 return WERR_ACCESS_DENIED;
1949         }
1950
1951         /* check that we have a valid driver name first */
1952
1953         if ((version = get_version_id(r->in.architecture)) == -1)
1954                 return WERR_INVALID_ENVIRONMENT;
1955
1956         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
1957                                                 r->in.architecture,
1958                                                 version)))
1959         {
1960                 /* try for Win2k driver if "Windows NT x86" */
1961
1962                 if ( version == 2 ) {
1963                         version = 3;
1964                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1965                                                                 &info, 3,
1966                                                                 r->in.driver,
1967                                                                 r->in.architecture,
1968                                                                 version))) {
1969                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970                                 goto done;
1971                         }
1972                 }
1973                 /* otherwise it was a failure */
1974                 else {
1975                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1976                         goto done;
1977                 }
1978
1979         }
1980
1981         if (printer_driver_in_use(&info->info3)) {
1982                 status = WERR_PRINTER_DRIVER_IN_USE;
1983                 goto done;
1984         }
1985
1986         if ( version == 2 )
1987         {
1988                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1989                                                        &info_win2k, 3,
1990                                                        r->in.driver,
1991                                                        r->in.architecture, 3)))
1992                 {
1993                         /* if we get to here, we now have 2 driver info structures to remove */
1994                         /* remove the Win2k driver first*/
1995
1996                         status_win2k = delete_printer_driver(
1997                                 p, &info_win2k->info3, 3, false);
1998                         free_a_printer_driver(info_win2k);
1999
2000                         /* this should not have failed---if it did, report to client */
2001                         if ( !W_ERROR_IS_OK(status_win2k) )
2002                         {
2003                                 status = status_win2k;
2004                                 goto done;
2005                         }
2006                 }
2007         }
2008
2009         status = delete_printer_driver(p, &info->info3, version, false);
2010
2011         /* if at least one of the deletes succeeded return OK */
2012
2013         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2014                 status = WERR_OK;
2015
2016 done:
2017         free_a_printer_driver(info);
2018
2019         return status;
2020 }
2021
2022 /****************************************************************
2023  _spoolss_DeletePrinterDriverEx
2024 ****************************************************************/
2025
2026 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2027                                       struct spoolss_DeletePrinterDriverEx *r)
2028 {
2029         union spoolss_DriverInfo        *info = NULL;
2030         union spoolss_DriverInfo        *info_win2k = NULL;
2031         int                             version;
2032         bool                            delete_files;
2033         WERROR                          status;
2034         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2035         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2036
2037         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038            and not a printer admin, then fail */
2039
2040         if ( (p->server_info->utok.uid != sec_initial_uid())
2041                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2042                 && !token_contains_name_in_list(
2043                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2044                         p->server_info->ptok, lp_printer_admin(-1)) )
2045         {
2046                 return WERR_ACCESS_DENIED;
2047         }
2048
2049         /* check that we have a valid driver name first */
2050         if ((version = get_version_id(r->in.architecture)) == -1) {
2051                 /* this is what NT returns */
2052                 return WERR_INVALID_ENVIRONMENT;
2053         }
2054
2055         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2056                 version = r->in.version;
2057
2058         status = get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
2059                                       r->in.architecture, version);
2060
2061         if ( !W_ERROR_IS_OK(status) )
2062         {
2063                 /*
2064                  * if the client asked for a specific version,
2065                  * or this is something other than Windows NT x86,
2066                  * then we've failed
2067                  */
2068
2069                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2070                         goto done;
2071
2072                 /* try for Win2k driver if "Windows NT x86" */
2073
2074                 version = 3;
2075                 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, 3, r->in.driver,
2076                                                         r->in.architecture,
2077                                                         version))) {
2078                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2079                         goto done;
2080                 }
2081         }
2082
2083         if ( printer_driver_in_use(&info->info3) ) {
2084                 status = WERR_PRINTER_DRIVER_IN_USE;
2085                 goto done;
2086         }
2087
2088         /*
2089          * we have a couple of cases to consider.
2090          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2091          *     then the delete should fail if **any** files overlap with
2092          *     other drivers
2093          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094          *     non-overlapping files
2095          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096          *     is set, the do not delete any files
2097          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2098          */
2099
2100         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2101
2102         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2103
2104         if ( delete_files && printer_driver_files_in_use(info, &info->info3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2105                 /* no idea of the correct error here */
2106                 status = WERR_ACCESS_DENIED;
2107                 goto done;
2108         }
2109
2110
2111         /* also check for W32X86/3 if necessary; maybe we already have? */
2112
2113         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2114                 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k, 3,
2115                                                        r->in.driver,
2116                                                        r->in.architecture, 3)))
2117                 {
2118
2119                         if ( delete_files && printer_driver_files_in_use(info, &info_win2k->info3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2120                                 /* no idea of the correct error here */
2121                                 free_a_printer_driver(info_win2k);
2122                                 status = WERR_ACCESS_DENIED;
2123                                 goto done;
2124                         }
2125
2126                         /* if we get to here, we now have 2 driver info structures to remove */
2127                         /* remove the Win2k driver first*/
2128
2129                         status_win2k = delete_printer_driver(
2130                                 p, &info_win2k->info3, 3, delete_files);
2131                         free_a_printer_driver(info_win2k);
2132
2133                         /* this should not have failed---if it did, report to client */
2134
2135                         if ( !W_ERROR_IS_OK(status_win2k) )
2136                                 goto done;
2137                 }
2138         }
2139
2140         status = delete_printer_driver(p, &info->info3, version, delete_files);
2141
2142         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2143                 status = WERR_OK;
2144 done:
2145         free_a_printer_driver(info);
2146
2147         return status;
2148 }
2149
2150
2151 /****************************************************************************
2152  Internal routine for removing printerdata
2153  ***************************************************************************/
2154
2155 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2156 {
2157         return delete_printer_data( printer->info_2, key, value );
2158 }
2159
2160 /****************************************************************************
2161  Internal routine for storing printerdata
2162  ***************************************************************************/
2163
2164 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2165                           const char *key, const char *value,
2166                           uint32_t type, uint8_t *data, int real_len)
2167 {
2168         /* the registry objects enforce uniqueness based on value name */
2169
2170         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2171 }
2172
2173 /********************************************************************
2174  GetPrinterData on a printer server Handle.
2175 ********************************************************************/
2176
2177 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2178                                             const char *value,
2179                                             enum winreg_Type *type,
2180                                             union spoolss_PrinterData *data)
2181 {
2182         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2183
2184         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2185                 *type = REG_DWORD;
2186                 data->value = 0x00;
2187                 return WERR_OK;
2188         }
2189
2190         if (!StrCaseCmp(value, "BeepEnabled")) {
2191                 *type = REG_DWORD;
2192                 data->value = 0x00;
2193                 return WERR_OK;
2194         }
2195
2196         if (!StrCaseCmp(value, "EventLog")) {
2197                 *type = REG_DWORD;
2198                 /* formally was 0x1b */
2199                 data->value = 0x00;
2200                 return WERR_OK;
2201         }
2202
2203         if (!StrCaseCmp(value, "NetPopup")) {
2204                 *type = REG_DWORD;
2205                 data->value = 0x00;
2206                 return WERR_OK;
2207         }
2208
2209         if (!StrCaseCmp(value, "MajorVersion")) {
2210                 *type = REG_DWORD;
2211
2212                 /* Windows NT 4.0 seems to not allow uploading of drivers
2213                    to a server that reports 0x3 as the MajorVersion.
2214                    need to investigate more how Win2k gets around this .
2215                    -- jerry */
2216
2217                 if (RA_WINNT == get_remote_arch()) {
2218                         data->value = 0x02;
2219                 } else {
2220                         data->value = 0x03;
2221                 }
2222
2223                 return WERR_OK;
2224         }
2225
2226         if (!StrCaseCmp(value, "MinorVersion")) {
2227                 *type = REG_DWORD;
2228                 data->value = 0x00;
2229                 return WERR_OK;
2230         }
2231
2232         /* REG_BINARY
2233          *  uint32_t size        = 0x114
2234          *  uint32_t major       = 5
2235          *  uint32_t minor       = [0|1]
2236          *  uint32_t build       = [2195|2600]
2237          *  extra unicode string = e.g. "Service Pack 3"
2238          */
2239         if (!StrCaseCmp(value, "OSVersion")) {
2240                 DATA_BLOB blob;
2241                 enum ndr_err_code ndr_err;
2242                 struct spoolss_OSVersion os;
2243
2244                 os.major                = 5;    /* Windows 2000 == 5.0 */
2245                 os.minor                = 0;
2246                 os.build                = 2195; /* build */
2247                 os.extra_string         = "";   /* leave extra string empty */
2248
2249                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2250                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2251                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2252                         return WERR_GENERAL_FAILURE;
2253                 }
2254
2255                 *type = REG_BINARY;
2256                 data->binary = blob;
2257
2258                 return WERR_OK;
2259         }
2260
2261
2262         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2263                 *type = REG_SZ;
2264
2265                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2266                 W_ERROR_HAVE_NO_MEMORY(data->string);
2267
2268                 return WERR_OK;
2269         }
2270
2271         if (!StrCaseCmp(value, "Architecture")) {
2272                 *type = REG_SZ;
2273
2274                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2275                 W_ERROR_HAVE_NO_MEMORY(data->string);
2276
2277                 return WERR_OK;
2278         }
2279
2280         if (!StrCaseCmp(value, "DsPresent")) {
2281                 *type = REG_DWORD;
2282
2283                 /* only show the publish check box if we are a
2284                    member of a AD domain */
2285
2286                 if (lp_security() == SEC_ADS) {
2287                         data->value = 0x01;
2288                 } else {
2289                         data->value = 0x00;
2290                 }
2291                 return WERR_OK;
2292         }
2293
2294         if (!StrCaseCmp(value, "DNSMachineName")) {
2295                 const char *hostname = get_mydnsfullname();
2296
2297                 if (!hostname) {
2298                         return WERR_BADFILE;
2299                 }
2300
2301                 *type = REG_SZ;
2302                 data->string = talloc_strdup(mem_ctx, hostname);
2303                 W_ERROR_HAVE_NO_MEMORY(data->string);
2304
2305                 return WERR_OK;
2306         }
2307
2308         *type = REG_NONE;
2309
2310         return WERR_INVALID_PARAM;
2311 }
2312
2313 /****************************************************************
2314  _spoolss_GetPrinterData
2315 ****************************************************************/
2316
2317 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2318                                struct spoolss_GetPrinterData *r)
2319 {
2320         struct spoolss_GetPrinterDataEx r2;
2321
2322         r2.in.handle            = r->in.handle;
2323         r2.in.key_name          = "PrinterDriverData";
2324         r2.in.value_name        = r->in.value_name;
2325         r2.in.offered           = r->in.offered;
2326         r2.out.type             = r->out.type;
2327         r2.out.data             = r->out.data;
2328         r2.out.needed           = r->out.needed;
2329
2330         return _spoolss_GetPrinterDataEx(p, &r2);
2331 }
2332
2333 /*********************************************************
2334  Connect to the client machine.
2335 **********************************************************/
2336
2337 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2338                         struct sockaddr_storage *client_ss, const char *remote_machine)
2339 {
2340         NTSTATUS ret;
2341         struct cli_state *the_cli;
2342         struct sockaddr_storage rm_addr;
2343
2344         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2345                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2346                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2347                         return false;
2348                 }
2349
2350                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2351                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2352                         return false;
2353                 }
2354         } else {
2355                 char addr[INET6_ADDRSTRLEN];
2356                 rm_addr = *client_ss;
2357                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2358                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2359                         addr));
2360         }
2361
2362         /* setup the connection */
2363
2364         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2365                 &rm_addr, 0, "IPC$", "IPC",
2366                 "", /* username */
2367                 "", /* domain */
2368                 "", /* password */
2369                 0, lp_client_signing(), NULL );
2370
2371         if ( !NT_STATUS_IS_OK( ret ) ) {
2372                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2373                         remote_machine ));
2374                 return false;
2375         }
2376
2377         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2378                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2379                 cli_shutdown(the_cli);
2380                 return false;
2381         }
2382
2383         /*
2384          * Ok - we have an anonymous connection to the IPC$ share.
2385          * Now start the NT Domain stuff :-).
2386          */
2387
2388         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2389         if (!NT_STATUS_IS_OK(ret)) {
2390                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2391                         remote_machine, nt_errstr(ret)));
2392                 cli_shutdown(the_cli);
2393                 return false;
2394         }
2395
2396         return true;
2397 }
2398
2399 /***************************************************************************
2400  Connect to the client.
2401 ****************************************************************************/
2402
2403 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2404                                         uint32_t localprinter, uint32_t type,
2405                                         struct policy_handle *handle,
2406                                         struct sockaddr_storage *client_ss)
2407 {
2408         WERROR result;
2409         NTSTATUS status;
2410
2411         /*
2412          * If it's the first connection, contact the client
2413          * and connect to the IPC$ share anonymously
2414          */
2415         if (smb_connections==0) {
2416                 fstring unix_printer;
2417
2418                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2419
2420                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2421                         return false;
2422
2423                 messaging_register(smbd_messaging_context(), NULL,
2424                                    MSG_PRINTER_NOTIFY2,
2425                                    receive_notify2_message_list);
2426                 /* Tell the connections db we're now interested in printer
2427                  * notify messages. */
2428                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2429         }
2430
2431         /*
2432          * Tell the specific printing tdb we want messages for this printer
2433          * by registering our PID.
2434          */
2435
2436         if (!print_notify_register_pid(snum))
2437                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2438
2439         smb_connections++;
2440
2441         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2442                                                  printer,
2443                                                  localprinter,
2444                                                  type,
2445                                                  0,
2446                                                  NULL,
2447                                                  handle,
2448                                                  &result);
2449         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2450                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2451                         win_errstr(result)));
2452
2453         return (W_ERROR_IS_OK(result));
2454 }
2455
2456 /****************************************************************
2457  ****************************************************************/
2458
2459 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2460                                                              const struct spoolss_NotifyOption *r)
2461 {
2462         struct spoolss_NotifyOption *option;
2463         uint32_t i,k;
2464
2465         if (!r) {
2466                 return NULL;
2467         }
2468
2469         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2470         if (!option) {
2471                 return NULL;
2472         }
2473
2474         *option = *r;
2475
2476         if (!option->count) {
2477                 return option;
2478         }
2479
2480         option->types = talloc_zero_array(option,
2481                 struct spoolss_NotifyOptionType, option->count);
2482         if (!option->types) {
2483                 talloc_free(option);
2484                 return NULL;
2485         }
2486
2487         for (i=0; i < option->count; i++) {
2488                 option->types[i] = r->types[i];
2489
2490                 if (option->types[i].count) {
2491                         option->types[i].fields = talloc_zero_array(option,
2492                                 union spoolss_Field, option->types[i].count);
2493                         if (!option->types[i].fields) {
2494                                 talloc_free(option);
2495                                 return NULL;
2496                         }
2497                         for (k=0; k<option->types[i].count; k++) {
2498                                 option->types[i].fields[k] =
2499                                         r->types[i].fields[k];
2500                         }
2501                 }
2502         }
2503
2504         return option;
2505 }
2506
2507 /****************************************************************
2508  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2509  *
2510  * before replying OK: status=0 a rpc call is made to the workstation
2511  * asking ReplyOpenPrinter
2512  *
2513  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2514  * called from api_spoolss_rffpcnex
2515 ****************************************************************/
2516
2517 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2518                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2519 {
2520         int snum = -1;
2521         struct spoolss_NotifyOption *option = r->in.notify_options;
2522         struct sockaddr_storage client_ss;
2523
2524         /* store the notify value in the printer struct */
2525
2526         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2527
2528         if (!Printer) {
2529                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2530                         "Invalid handle (%s:%u:%u).\n",
2531                         OUR_HANDLE(r->in.handle)));
2532                 return WERR_BADFID;
2533         }
2534
2535         Printer->notify.flags           = r->in.flags;
2536         Printer->notify.options         = r->in.options;
2537         Printer->notify.printerlocal    = r->in.printer_local;
2538
2539         TALLOC_FREE(Printer->notify.option);
2540         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2541
2542         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2543
2544         /* Connect to the client machine and send a ReplyOpenPrinter */
2545
2546         if ( Printer->printer_type == SPLHND_SERVER)
2547                 snum = -1;
2548         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2549                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2550                 return WERR_BADFID;
2551
2552         if (!interpret_string_addr(&client_ss, p->client_address,
2553                                    AI_NUMERICHOST)) {
2554                 return WERR_SERVER_UNAVAILABLE;
2555         }
2556
2557         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2558                                         Printer->notify.printerlocal, 1,
2559                                         &Printer->notify.client_hnd, &client_ss))
2560                 return WERR_SERVER_UNAVAILABLE;
2561
2562         Printer->notify.client_connected = true;
2563
2564         return WERR_OK;
2565 }
2566
2567 /*******************************************************************
2568  * fill a notify_info_data with the servername
2569  ********************************************************************/
2570
2571 void spoolss_notify_server_name(int snum,
2572                                        struct spoolss_Notify *data,
2573                                        print_queue_struct *queue,
2574                                        NT_PRINTER_INFO_LEVEL *printer,
2575                                        TALLOC_CTX *mem_ctx)
2576 {
2577         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2578 }
2579
2580 /*******************************************************************
2581  * fill a notify_info_data with the printername (not including the servername).
2582  ********************************************************************/
2583
2584 void spoolss_notify_printer_name(int snum,
2585                                         struct spoolss_Notify *data,
2586                                         print_queue_struct *queue,
2587                                         NT_PRINTER_INFO_LEVEL *printer,
2588                                         TALLOC_CTX *mem_ctx)
2589 {
2590         /* the notify name should not contain the \\server\ part */
2591         char *p = strrchr(printer->info_2->printername, '\\');
2592
2593         if (!p) {
2594                 p = printer->info_2->printername;
2595         } else {
2596                 p++;
2597         }
2598
2599         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2600 }
2601
2602 /*******************************************************************
2603  * fill a notify_info_data with the servicename
2604  ********************************************************************/
2605
2606 void spoolss_notify_share_name(int snum,
2607                                       struct spoolss_Notify *data,
2608                                       print_queue_struct *queue,
2609                                       NT_PRINTER_INFO_LEVEL *printer,
2610                                       TALLOC_CTX *mem_ctx)
2611 {
2612         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2613 }
2614
2615 /*******************************************************************
2616  * fill a notify_info_data with the port name
2617  ********************************************************************/
2618
2619 void spoolss_notify_port_name(int snum,
2620                                      struct spoolss_Notify *data,
2621                                      print_queue_struct *queue,
2622                                      NT_PRINTER_INFO_LEVEL *printer,
2623                                      TALLOC_CTX *mem_ctx)
2624 {
2625         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2626 }
2627
2628 /*******************************************************************
2629  * fill a notify_info_data with the printername
2630  * but it doesn't exist, have to see what to do
2631  ********************************************************************/
2632
2633 void spoolss_notify_driver_name(int snum,
2634                                        struct spoolss_Notify *data,
2635                                        print_queue_struct *queue,
2636                                        NT_PRINTER_INFO_LEVEL *printer,
2637                                        TALLOC_CTX *mem_ctx)
2638 {
2639         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2640 }
2641
2642 /*******************************************************************
2643  * fill a notify_info_data with the comment
2644  ********************************************************************/
2645
2646 void spoolss_notify_comment(int snum,
2647                                    struct spoolss_Notify *data,
2648                                    print_queue_struct *queue,
2649                                    NT_PRINTER_INFO_LEVEL *printer,
2650                                    TALLOC_CTX *mem_ctx)
2651 {
2652         char *p;
2653
2654         if (*printer->info_2->comment == '\0') {
2655                 p = lp_comment(snum);
2656         } else {
2657                 p = printer->info_2->comment;
2658         }
2659
2660         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2661 }
2662
2663 /*******************************************************************
2664  * fill a notify_info_data with the comment
2665  * location = "Room 1, floor 2, building 3"
2666  ********************************************************************/
2667
2668 void spoolss_notify_location(int snum,
2669                                     struct spoolss_Notify *data,
2670                                     print_queue_struct *queue,
2671                                     NT_PRINTER_INFO_LEVEL *printer,
2672                                     TALLOC_CTX *mem_ctx)
2673 {
2674         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2675 }
2676
2677 /*******************************************************************
2678  * fill a notify_info_data with the device mode
2679  * jfm:xxxx don't to it for know but that's a real problem !!!
2680  ********************************************************************/
2681
2682 static void spoolss_notify_devmode(int snum,
2683                                    struct spoolss_Notify *data,
2684                                    print_queue_struct *queue,
2685                                    NT_PRINTER_INFO_LEVEL *printer,
2686                                    TALLOC_CTX *mem_ctx)
2687 {
2688         /* for a dummy implementation we have to zero the fields */
2689         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2690 }
2691
2692 /*******************************************************************
2693  * fill a notify_info_data with the separator file name
2694  ********************************************************************/
2695
2696 void spoolss_notify_sepfile(int snum,
2697                                    struct spoolss_Notify *data,
2698                                    print_queue_struct *queue,
2699                                    NT_PRINTER_INFO_LEVEL *printer,
2700                                    TALLOC_CTX *mem_ctx)
2701 {
2702         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2703 }
2704
2705 /*******************************************************************
2706  * fill a notify_info_data with the print processor
2707  * jfm:xxxx return always winprint to indicate we don't do anything to it
2708  ********************************************************************/
2709
2710 void spoolss_notify_print_processor(int snum,
2711                                            struct spoolss_Notify *data,
2712                                            print_queue_struct *queue,
2713                                            NT_PRINTER_INFO_LEVEL *printer,
2714                                            TALLOC_CTX *mem_ctx)
2715 {
2716         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2717 }
2718
2719 /*******************************************************************
2720  * fill a notify_info_data with the print processor options
2721  * jfm:xxxx send an empty string
2722  ********************************************************************/
2723
2724 void spoolss_notify_parameters(int snum,
2725                                       struct spoolss_Notify *data,
2726                                       print_queue_struct *queue,
2727                                       NT_PRINTER_INFO_LEVEL *printer,
2728                                       TALLOC_CTX *mem_ctx)
2729 {
2730         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2731 }
2732
2733 /*******************************************************************
2734  * fill a notify_info_data with the data type
2735  * jfm:xxxx always send RAW as data type
2736  ********************************************************************/
2737
2738 void spoolss_notify_datatype(int snum,
2739                                     struct spoolss_Notify *data,
2740                                     print_queue_struct *queue,
2741                                     NT_PRINTER_INFO_LEVEL *printer,
2742                                     TALLOC_CTX *mem_ctx)
2743 {
2744         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2745 }
2746
2747 /*******************************************************************
2748  * fill a notify_info_data with the security descriptor
2749  * jfm:xxxx send an null pointer to say no security desc
2750  * have to implement security before !
2751  ********************************************************************/
2752
2753 static void spoolss_notify_security_desc(int snum,
2754                                          struct spoolss_Notify *data,
2755                                          print_queue_struct *queue,
2756                                          NT_PRINTER_INFO_LEVEL *printer,
2757                                          TALLOC_CTX *mem_ctx)
2758 {
2759         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2760                                           printer->info_2->secdesc_buf->sd_size,
2761                                           printer->info_2->secdesc_buf->sd);
2762 }
2763
2764 /*******************************************************************
2765  * fill a notify_info_data with the attributes
2766  * jfm:xxxx a samba printer is always shared
2767  ********************************************************************/
2768
2769 void spoolss_notify_attributes(int snum,
2770                                       struct spoolss_Notify *data,
2771                                       print_queue_struct *queue,
2772                                       NT_PRINTER_INFO_LEVEL *printer,
2773                                       TALLOC_CTX *mem_ctx)
2774 {
2775         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2776 }
2777
2778 /*******************************************************************
2779  * fill a notify_info_data with the priority
2780  ********************************************************************/
2781
2782 static void spoolss_notify_priority(int snum,
2783                                     struct spoolss_Notify *data,
2784                                     print_queue_struct *queue,
2785                                     NT_PRINTER_INFO_LEVEL *printer,
2786                                     TALLOC_CTX *mem_ctx)
2787 {
2788         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the default priority
2793  ********************************************************************/
2794
2795 static void spoolss_notify_default_priority(int snum,
2796                                             struct spoolss_Notify *data,
2797                                             print_queue_struct *queue,
2798                                             NT_PRINTER_INFO_LEVEL *printer,
2799                                             TALLOC_CTX *mem_ctx)
2800 {
2801         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2802 }
2803
2804 /*******************************************************************
2805  * fill a notify_info_data with the start time
2806  ********************************************************************/
2807
2808 static void spoolss_notify_start_time(int snum,
2809                                       struct spoolss_Notify *data,
2810                                       print_queue_struct *queue,
2811                                       NT_PRINTER_INFO_LEVEL *printer,
2812                                       TALLOC_CTX *mem_ctx)
2813 {
2814         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the until time
2819  ********************************************************************/
2820
2821 static void spoolss_notify_until_time(int snum,
2822                                       struct spoolss_Notify *data,
2823                                       print_queue_struct *queue,
2824                                       NT_PRINTER_INFO_LEVEL *printer,
2825                                       TALLOC_CTX *mem_ctx)
2826 {
2827         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2828 }
2829
2830 /*******************************************************************
2831  * fill a notify_info_data with the status
2832  ********************************************************************/
2833
2834 static void spoolss_notify_status(int snum,
2835                                   struct spoolss_Notify *data,
2836                                   print_queue_struct *queue,
2837                                   NT_PRINTER_INFO_LEVEL *printer,
2838                                   TALLOC_CTX *mem_ctx)
2839 {
2840         print_status_struct status;
2841
2842         print_queue_length(snum, &status);
2843         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the number of jobs queued
2848  ********************************************************************/
2849
2850 void spoolss_notify_cjobs(int snum,
2851                                  struct spoolss_Notify *data,
2852                                  print_queue_struct *queue,
2853                                  NT_PRINTER_INFO_LEVEL *printer,
2854                                  TALLOC_CTX *mem_ctx)
2855 {
2856         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2857 }
2858
2859 /*******************************************************************
2860  * fill a notify_info_data with the average ppm
2861  ********************************************************************/
2862
2863 static void spoolss_notify_average_ppm(int snum,
2864                                        struct spoolss_Notify *data,
2865                                        print_queue_struct *queue,
2866                                        NT_PRINTER_INFO_LEVEL *printer,
2867                                        TALLOC_CTX *mem_ctx)
2868 {
2869         /* always respond 8 pages per minutes */
2870         /* a little hard ! */
2871         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2872 }
2873
2874 /*******************************************************************
2875  * fill a notify_info_data with username
2876  ********************************************************************/
2877
2878 static void spoolss_notify_username(int snum,
2879                                     struct spoolss_Notify *data,
2880                                     print_queue_struct *queue,
2881                                     NT_PRINTER_INFO_LEVEL *printer,
2882                                     TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with job status
2889  ********************************************************************/
2890
2891 static void spoolss_notify_job_status(int snum,
2892                                       struct spoolss_Notify *data,
2893                                       print_queue_struct *queue,
2894                                       NT_PRINTER_INFO_LEVEL *printer,
2895                                       TALLOC_CTX *mem_ctx)
2896 {
2897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2898 }
2899
2900 /*******************************************************************
2901  * fill a notify_info_data with job name
2902  ********************************************************************/
2903
2904 static void spoolss_notify_job_name(int snum,
2905                                     struct spoolss_Notify *data,
2906                                     print_queue_struct *queue,
2907                                     NT_PRINTER_INFO_LEVEL *printer,
2908                                     TALLOC_CTX *mem_ctx)
2909 {
2910         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2911 }
2912
2913 /*******************************************************************
2914  * fill a notify_info_data with job status
2915  ********************************************************************/
2916
2917 static void spoolss_notify_job_status_string(int snum,
2918                                              struct spoolss_Notify *data,
2919                                              print_queue_struct *queue,
2920                                              NT_PRINTER_INFO_LEVEL *printer,
2921                                              TALLOC_CTX *mem_ctx)
2922 {
2923         /*
2924          * Now we're returning job status codes we just return a "" here. JRA.
2925          */
2926
2927         const char *p = "";
2928
2929 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2930         p = "unknown";
2931
2932         switch (queue->status) {
2933         case LPQ_QUEUED:
2934                 p = "Queued";
2935                 break;
2936         case LPQ_PAUSED:
2937                 p = "";    /* NT provides the paused string */
2938                 break;
2939         case LPQ_SPOOLING:
2940                 p = "Spooling";
2941                 break;
2942         case LPQ_PRINTING:
2943                 p = "Printing";
2944                 break;
2945         }
2946 #endif /* NO LONGER NEEDED. */
2947
2948         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2949 }
2950
2951 /*******************************************************************
2952  * fill a notify_info_data with job time
2953  ********************************************************************/
2954
2955 static void spoolss_notify_job_time(int snum,
2956                                     struct spoolss_Notify *data,
2957                                     print_queue_struct *queue,
2958                                     NT_PRINTER_INFO_LEVEL *printer,
2959                                     TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with job size
2966  ********************************************************************/
2967
2968 static void spoolss_notify_job_size(int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     NT_PRINTER_INFO_LEVEL *printer,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with page info
2979  ********************************************************************/
2980 static void spoolss_notify_total_pages(int snum,
2981                                 struct spoolss_Notify *data,
2982                                 print_queue_struct *queue,
2983                                 NT_PRINTER_INFO_LEVEL *printer,
2984                                 TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with pages printed info.
2991  ********************************************************************/
2992 static void spoolss_notify_pages_printed(int snum,
2993                                 struct spoolss_Notify *data,
2994                                 print_queue_struct *queue,
2995                                 NT_PRINTER_INFO_LEVEL *printer,
2996                                 TALLOC_CTX *mem_ctx)
2997 {
2998         /* Add code when back-end tracks this */
2999         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3000 }
3001
3002 /*******************************************************************
3003  Fill a notify_info_data with job position.
3004  ********************************************************************/
3005
3006 static void spoolss_notify_job_position(int snum,
3007                                         struct spoolss_Notify *data,
3008                                         print_queue_struct *queue,
3009                                         NT_PRINTER_INFO_LEVEL *printer,
3010                                         TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3013 }
3014
3015 /*******************************************************************
3016  Fill a notify_info_data with submitted time.
3017  ********************************************************************/
3018
3019 static void spoolss_notify_submitted_time(int snum,
3020                                           struct spoolss_Notify *data,
3021                                           print_queue_struct *queue,
3022                                           NT_PRINTER_INFO_LEVEL *printer,
3023                                           TALLOC_CTX *mem_ctx)
3024 {
3025         data->data.string.string = NULL;
3026         data->data.string.size = 0;
3027
3028         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3029                                &data->data.string.string,
3030                                &data->data.string.size);
3031
3032 }
3033
3034 struct s_notify_info_data_table
3035 {
3036         enum spoolss_NotifyType type;
3037         uint16_t field;
3038         const char *name;
3039         enum spoolss_NotifyTable variable_type;
3040         void (*fn) (int snum, struct spoolss_Notify *data,
3041                     print_queue_struct *queue,
3042                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3043 };
3044
3045 /* A table describing the various print notification constants and
3046    whether the notification data is a pointer to a variable sized
3047    buffer, a one value uint32_t or a two value uint32_t. */
3048
3049 static const struct s_notify_info_data_table notify_info_data_table[] =
3050 {
3051 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3052 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3053 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3054 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3055 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3056 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3077 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3078 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3079 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3080 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3081 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3082 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3083 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3084 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3085 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3086 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3087 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3088 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3089 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3090 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3091 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3092 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3093 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3094 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3095 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3096 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3097 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3098 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3099 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3100 };
3101
3102 /*******************************************************************
3103  Return the variable_type of info_data structure.
3104 ********************************************************************/
3105
3106 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3107                                                   uint16_t field)
3108 {
3109         int i=0;
3110
3111         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3112                 if ( (notify_info_data_table[i].type == type) &&
3113                      (notify_info_data_table[i].field == field) ) {
3114                         return notify_info_data_table[i].variable_type;
3115                 }
3116         }
3117
3118         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3119
3120         return 0;
3121 }
3122
3123 /****************************************************************************
3124 ****************************************************************************/
3125
3126 static bool search_notify(enum spoolss_NotifyType type,
3127                           uint16_t field,
3128                           int *value)
3129 {
3130         int i;
3131
3132         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3133                 if (notify_info_data_table[i].type == type &&
3134                     notify_info_data_table[i].field == field &&
3135                     notify_info_data_table[i].fn != NULL) {
3136                         *value = i;
3137                         return true;
3138                 }
3139         }
3140
3141         return false;
3142 }
3143
3144 /****************************************************************************
3145 ****************************************************************************/
3146
3147 void construct_info_data(struct spoolss_Notify *info_data,
3148                          enum spoolss_NotifyType type,
3149                          uint16_t field,
3150                          int id)
3151 {
3152         info_data->type                 = type;
3153         info_data->field.field          = field;
3154         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3155         info_data->job_id               = id;
3156 }
3157
3158 /*******************************************************************
3159  *
3160  * fill a notify_info struct with info asked
3161  *
3162  ********************************************************************/
3163
3164 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3165                                           struct spoolss_NotifyInfo *info,
3166                                           int snum,
3167                                           const struct spoolss_NotifyOptionType *option_type,
3168                                           uint32_t id,
3169                                           TALLOC_CTX *mem_ctx)
3170 {
3171         int field_num,j;
3172         enum spoolss_NotifyType type;
3173         uint16_t field;
3174
3175         struct spoolss_Notify *current_data;
3176         NT_PRINTER_INFO_LEVEL *printer = NULL;
3177         print_queue_struct *queue=NULL;
3178
3179         type = option_type->type;
3180
3181         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3182                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3183                 option_type->count, lp_servicename(snum)));
3184
3185         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3186                 return false;
3187
3188         for(field_num=0; field_num < option_type->count; field_num++) {
3189                 field = option_type->fields[field_num].field;
3190
3191                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3192
3193                 if (!search_notify(type, field, &j) )
3194                         continue;
3195
3196                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3197                                                       struct spoolss_Notify,
3198                                                       info->count + 1);
3199                 if (info->notifies == NULL) {
3200                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3201                         free_a_printer(&printer, 2);
3202                         return false;
3203                 }
3204
3205                 current_data = &info->notifies[info->count];
3206
3207                 construct_info_data(current_data, type, field, id);
3208
3209                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3210                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3211
3212                 notify_info_data_table[j].fn(snum, current_data, queue,
3213                                              printer, mem_ctx);
3214
3215                 info->count++;
3216         }
3217
3218         free_a_printer(&printer, 2);
3219         return true;
3220 }
3221
3222 /*******************************************************************
3223  *
3224  * fill a notify_info struct with info asked
3225  *
3226  ********************************************************************/
3227
3228 static bool construct_notify_jobs_info(print_queue_struct *queue,
3229                                        struct spoolss_NotifyInfo *info,
3230                                        NT_PRINTER_INFO_LEVEL *printer,
3231                                        int snum,
3232                                        const struct spoolss_NotifyOptionType *option_type,
3233                                        uint32_t id,
3234                                        TALLOC_CTX *mem_ctx)
3235 {
3236         int field_num,j;
3237         enum spoolss_NotifyType type;
3238         uint16_t field;
3239         struct spoolss_Notify *current_data;
3240
3241         DEBUG(4,("construct_notify_jobs_info\n"));
3242
3243         type = option_type->type;
3244
3245         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3246                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3247                 option_type->count));
3248
3249         for(field_num=0; field_num<option_type->count; field_num++) {
3250                 field = option_type->fields[field_num].field;
3251
3252                 if (!search_notify(type, field, &j) )
3253                         continue;
3254
3255                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3256                                                       struct spoolss_Notify,
3257                                                       info->count + 1);
3258                 if (info->notifies == NULL) {
3259                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3260                         return false;
3261                 }
3262
3263                 current_data=&(info->notifies[info->count]);
3264
3265                 construct_info_data(current_data, type, field, id);
3266                 notify_info_data_table[j].fn(snum, current_data, queue,
3267                                              printer, mem_ctx);
3268                 info->count++;
3269         }
3270
3271         return true;
3272 }
3273
3274 /*
3275  * JFM: The enumeration is not that simple, it's even non obvious.
3276  *
3277  * let's take an example: I want to monitor the PRINTER SERVER for
3278  * the printer's name and the number of jobs currently queued.
3279  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3280  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3281  *
3282  * I have 3 printers on the back of my server.
3283  *
3284  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3285  * structures.
3286  *   Number     Data                    Id
3287  *      1       printer 1 name          1
3288  *      2       printer 1 cjob          1
3289  *      3       printer 2 name          2
3290  *      4       printer 2 cjob          2
3291  *      5       printer 3 name          3
3292  *      6       printer 3 name          3
3293  *
3294  * that's the print server case, the printer case is even worse.
3295  */
3296
3297 /*******************************************************************
3298  *
3299  * enumerate all printers on the printserver
3300  * fill a notify_info struct with info asked
3301  *
3302  ********************************************************************/
3303
3304 static WERROR printserver_notify_info(pipes_struct *p,
3305                                       struct policy_handle *hnd,
3306                                       struct spoolss_NotifyInfo *info,
3307                                       TALLOC_CTX *mem_ctx)
3308 {
3309         int snum;
3310         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3311         int n_services=lp_numservices();
3312         int i;
3313         struct spoolss_NotifyOption *option;
3314         struct spoolss_NotifyOptionType option_type;
3315
3316         DEBUG(4,("printserver_notify_info\n"));
3317
3318         if (!Printer)
3319                 return WERR_BADFID;
3320
3321         option = Printer->notify.option;
3322
3323         info->version   = 2;
3324         info->notifies  = NULL;
3325         info->count     = 0;
3326
3327         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3328            sending a ffpcn() request first */
3329
3330         if ( !option )
3331                 return WERR_BADFID;
3332
3333         for (i=0; i<option->count; i++) {
3334                 option_type = option->types[i];
3335
3336                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3337                         continue;
3338
3339                 for (snum=0; snum<n_services; snum++)
3340                 {
3341                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3342                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3343                 }
3344         }
3345
3346 #if 0
3347         /*
3348          * Debugging information, don't delete.
3349          */
3350
3351         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3352         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3353         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3354
3355         for (i=0; i<info->count; i++) {
3356                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3357                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3358                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3359         }
3360 #endif
3361
3362         return WERR_OK;
3363 }
3364
3365 /*******************************************************************
3366  *
3367  * fill a notify_info struct with info asked
3368  *
3369  ********************************************************************/
3370
3371 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3372                                   struct spoolss_NotifyInfo *info,
3373                                   TALLOC_CTX *mem_ctx)
3374 {
3375         int snum;
3376         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3377         int i;
3378         uint32_t id;
3379         struct spoolss_NotifyOption *option;
3380         struct spoolss_NotifyOptionType option_type;
3381         int count,j;
3382         print_queue_struct *queue=NULL;
3383         print_status_struct status;
3384
3385         DEBUG(4,("printer_notify_info\n"));
3386
3387         if (!Printer)
3388                 return WERR_BADFID;
3389
3390         option = Printer->notify.option;
3391         id = 0x0;
3392
3393         info->version   = 2;
3394         info->notifies  = NULL;
3395         info->count     = 0;
3396
3397         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3398            sending a ffpcn() request first */
3399
3400         if ( !option )
3401                 return WERR_BADFID;
3402
3403         get_printer_snum(p, hnd, &snum, NULL);
3404
3405         for (i=0; i<option->count; i++) {
3406                 option_type = option->types[i];
3407
3408                 switch (option_type.type) {
3409                 case PRINTER_NOTIFY_TYPE:
3410                         if(construct_notify_printer_info(Printer, info, snum,
3411                                                          &option_type, id,
3412                                                          mem_ctx))
3413                                 id--;
3414                         break;
3415
3416                 case JOB_NOTIFY_TYPE: {
3417                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3418
3419                         count = print_queue_status(snum, &queue, &status);
3420
3421                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3422                                 goto done;
3423
3424                         for (j=0; j<count; j++) {
3425                                 construct_notify_jobs_info(&queue[j], info,
3426                                                            printer, snum,
3427                                                            &option_type,
3428                                                            queue[j].job,
3429                                                            mem_ctx);
3430                         }
3431
3432                         free_a_printer(&printer, 2);
3433
3434                 done:
3435                         SAFE_FREE(queue);
3436                         break;
3437                 }
3438                 }
3439         }
3440
3441         /*
3442          * Debugging information, don't delete.
3443          */
3444         /*
3445         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3446         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3447         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3448
3449         for (i=0; i<info->count; i++) {
3450                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3451                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3452                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3453         }
3454         */
3455         return WERR_OK;
3456 }
3457
3458 /****************************************************************
3459  _spoolss_RouterRefreshPrinterChangeNotify
3460 ****************************************************************/
3461
3462 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3463                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3464 {
3465         struct spoolss_NotifyInfo *info;
3466
3467         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3468         WERROR result = WERR_BADFID;
3469
3470         /* we always have a spoolss_NotifyInfo struct */
3471         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3472         if (!info) {
3473                 result = WERR_NOMEM;
3474                 goto done;
3475         }
3476
3477         *r->out.info = info;
3478
3479         if (!Printer) {
3480                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3481                         "Invalid handle (%s:%u:%u).\n",
3482                         OUR_HANDLE(r->in.handle)));
3483                 goto done;
3484         }
3485
3486         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3487
3488         /*
3489          *      We are now using the change value, and
3490          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3491          *      I don't have a global notification system, I'm sending back all the
3492          *      informations even when _NOTHING_ has changed.
3493          */
3494
3495         /* We need to keep track of the change value to send back in
3496            RRPCN replies otherwise our updates are ignored. */
3497
3498         Printer->notify.fnpcn = true;
3499
3500         if (Printer->notify.client_connected) {
3501                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3502                         "Saving change value in request [%x]\n",
3503                         r->in.change_low));
3504                 Printer->notify.change = r->in.change_low;
3505         }
3506
3507         /* just ignore the spoolss_NotifyOption */
3508
3509         switch (Printer->printer_type) {
3510                 case SPLHND_SERVER:
3511                         result = printserver_notify_info(p, r->in.handle,
3512                                                          info, p->mem_ctx);
3513                         break;
3514
3515                 case SPLHND_PRINTER:
3516                         result = printer_notify_info(p, r->in.handle,
3517                                                      info, p->mem_ctx);
3518                         break;
3519         }
3520
3521         Printer->notify.fnpcn = false;
3522
3523 done:
3524         return result;
3525 }
3526
3527 /********************************************************************
3528  * construct_printer_info_0
3529  * fill a printer_info_0 struct
3530  ********************************************************************/
3531
3532 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3533                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3534                                       struct spoolss_PrinterInfo0 *r,
3535                                       int snum)
3536 {
3537         int count;
3538         counter_printer_0 *session_counter;
3539         time_t setuptime;
3540         print_status_struct status;
3541
3542         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3543         W_ERROR_HAVE_NO_MEMORY(r->printername);
3544
3545         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3546         W_ERROR_HAVE_NO_MEMORY(r->servername);
3547
3548         count = print_queue_length(snum, &status);
3549
3550         /* check if we already have a counter for this printer */
3551         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3552                 if (session_counter->snum == snum)
3553                         break;
3554         }
3555
3556         /* it's the first time, add it to the list */
3557         if (session_counter == NULL) {
3558                 session_counter = SMB_MALLOC_P(counter_printer_0);
3559                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3560                 ZERO_STRUCTP(session_counter);
3561                 session_counter->snum           = snum;
3562                 session_counter->counter        = 0;
3563                 DLIST_ADD(counter_list, session_counter);
3564         }
3565
3566         /* increment it */
3567         session_counter->counter++;
3568
3569         r->cjobs                        = count;
3570         r->total_jobs                   = 0;
3571         r->total_bytes                  = 0;
3572
3573         setuptime = (time_t)ntprinter->info_2->setuptime;
3574
3575         init_systemtime(&r->time, gmtime(&setuptime));
3576
3577         /* JFM:
3578          * the global_counter should be stored in a TDB as it's common to all the clients
3579          * and should be zeroed on samba startup
3580          */
3581         r->global_counter               = session_counter->counter;
3582         r->total_pages                  = 0;
3583         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3584         r->version                      = 0x0005;       /* NT 5 */
3585         r->free_build                   = 0x0893;       /* build 2195 */
3586         r->spooling                     = 0;
3587         r->max_spooling                 = 0;
3588         r->session_counter              = session_counter->counter;
3589         r->num_error_out_of_paper       = 0x0;
3590         r->num_error_not_ready          = 0x0;          /* number of print failure */
3591         r->job_error                    = 0x0;
3592         r->number_of_processors         = 0x1;
3593         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3594         r->high_part_total_bytes        = 0x0;
3595         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3596         r->last_error                   = WERR_OK;
3597         r->status                       = nt_printq_status(status.status);
3598         r->enumerate_network_printers   = 0x0;
3599         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3600         r->processor_architecture       = 0x0;
3601         r->processor_level              = 0x6;          /* 6  ???*/
3602         r->ref_ic                       = 0;
3603         r->reserved2                    = 0;
3604         r->reserved3                    = 0;
3605
3606         return WERR_OK;
3607 }
3608
3609 /****************************************************************************
3610  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3611  should be valid upon entry
3612 ****************************************************************************/
3613
3614 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3615                                     struct spoolss_DeviceMode *r,
3616                                     const NT_DEVICEMODE *ntdevmode)
3617 {
3618         if (!r || !ntdevmode) {
3619                 return WERR_INVALID_PARAM;
3620         }
3621
3622         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3623         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3624
3625         r->specversion          = ntdevmode->specversion;
3626         r->driverversion        = ntdevmode->driverversion;
3627         r->size                 = ntdevmode->size;
3628         r->__driverextra_length = ntdevmode->driverextra;
3629         r->fields               = ntdevmode->fields;
3630
3631         r->orientation          = ntdevmode->orientation;
3632         r->papersize            = ntdevmode->papersize;
3633         r->paperlength          = ntdevmode->paperlength;
3634         r->paperwidth           = ntdevmode->paperwidth;
3635         r->scale                = ntdevmode->scale;
3636         r->copies               = ntdevmode->copies;
3637         r->defaultsource        = ntdevmode->defaultsource;
3638         r->printquality         = ntdevmode->printquality;
3639         r->color                = ntdevmode->color;
3640         r->duplex               = ntdevmode->duplex;
3641         r->yresolution          = ntdevmode->yresolution;
3642         r->ttoption             = ntdevmode->ttoption;
3643         r->collate              = ntdevmode->collate;
3644
3645         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3646         W_ERROR_HAVE_NO_MEMORY(r->formname);
3647
3648         /* all 0 below are values that have not been set in the old parsing/copy
3649          * function, maybe they should... - gd */
3650
3651         r->logpixels            = 0;
3652         r->bitsperpel           = 0;
3653         r->pelswidth            = 0;
3654         r->pelsheight           = 0;
3655         r->displayflags         = 0;
3656         r->displayfrequency     = 0;
3657         r->icmmethod            = ntdevmode->icmmethod;
3658         r->icmintent            = ntdevmode->icmintent;
3659         r->mediatype            = ntdevmode->mediatype;
3660         r->dithertype           = ntdevmode->dithertype;
3661         r->reserved1            = 0;
3662         r->reserved2            = 0;
3663         r->panningwidth         = 0;
3664         r->panningheight        = 0;
3665
3666         if (ntdevmode->nt_dev_private != NULL) {
3667                 r->driverextra_data = data_blob_talloc(mem_ctx,
3668                         ntdevmode->nt_dev_private,
3669                         ntdevmode->driverextra);
3670                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3671         }
3672
3673         return WERR_OK;
3674 }
3675
3676
3677 /****************************************************************************
3678  Create a spoolss_DeviceMode struct. Returns talloced memory.
3679 ****************************************************************************/
3680
3681 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3682                                               const char *servicename)
3683 {
3684         WERROR result;
3685         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3686         struct spoolss_DeviceMode *devmode = NULL;
3687
3688         DEBUG(7,("construct_dev_mode\n"));
3689
3690         DEBUGADD(8,("getting printer characteristics\n"));
3691
3692         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3693                 return NULL;
3694
3695         if (!printer->info_2->devmode) {
3696                 DEBUG(5, ("BONG! There was no device mode!\n"));
3697                 goto done;
3698         }
3699
3700         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3701         if (!devmode) {
3702                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3703                 goto done;
3704         }
3705
3706         DEBUGADD(8,("loading DEVICEMODE\n"));
3707
3708         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3709         if (!W_ERROR_IS_OK(result)) {
3710                 TALLOC_FREE(devmode);
3711         }
3712
3713 done:
3714         free_a_printer(&printer,2);
3715
3716         return devmode;
3717 }
3718
3719 /********************************************************************
3720  * construct_printer_info1
3721  * fill a spoolss_PrinterInfo1 struct
3722 ********************************************************************/
3723
3724 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3725                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3726                                       uint32_t flags,
3727                                       struct spoolss_PrinterInfo1 *r,
3728                                       int snum)
3729 {
3730         r->flags                = flags;
3731
3732         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3733                                                   ntprinter->info_2->printername,
3734                                                   ntprinter->info_2->drivername,
3735                                                   ntprinter->info_2->location);
3736         W_ERROR_HAVE_NO_MEMORY(r->description);
3737
3738         if (*ntprinter->info_2->comment == '\0') {
3739                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3740         } else {
3741                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3742         }
3743         W_ERROR_HAVE_NO_MEMORY(r->comment);
3744
3745         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3746         W_ERROR_HAVE_NO_MEMORY(r->name);
3747
3748         return WERR_OK;
3749 }
3750
3751 /********************************************************************
3752  * construct_printer_info2
3753  * fill a spoolss_PrinterInfo2 struct
3754 ********************************************************************/
3755
3756 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3757                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3758                                       struct spoolss_PrinterInfo2 *r,
3759                                       int snum)
3760 {
3761         int count;
3762
3763         print_status_struct status;
3764
3765         count = print_queue_length(snum, &status);
3766
3767         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3768         W_ERROR_HAVE_NO_MEMORY(r->servername);
3769         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3770         W_ERROR_HAVE_NO_MEMORY(r->printername);
3771         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3772         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3773         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3774         W_ERROR_HAVE_NO_MEMORY(r->portname);
3775         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3776         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3777
3778         if (*ntprinter->info_2->comment == '\0') {
3779                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3780         } else {
3781                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3782         }
3783         W_ERROR_HAVE_NO_MEMORY(r->comment);
3784
3785         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3786         W_ERROR_HAVE_NO_MEMORY(r->location);
3787         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3788         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3789         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3790         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3791         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3792         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3793         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3794         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3795
3796         r->attributes           = ntprinter->info_2->attributes;
3797
3798         r->priority             = ntprinter->info_2->priority;
3799         r->defaultpriority      = ntprinter->info_2->default_priority;
3800         r->starttime            = ntprinter->info_2->starttime;
3801         r->untiltime            = ntprinter->info_2->untiltime;
3802         r->status               = nt_printq_status(status.status);
3803         r->cjobs                = count;
3804         r->averageppm           = ntprinter->info_2->averageppm;
3805
3806         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3807         if (!r->devmode) {
3808                 DEBUG(8,("Returning NULL Devicemode!\n"));
3809         }
3810
3811         r->secdesc              = NULL;
3812
3813         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3814                 /* don't use talloc_steal() here unless you do a deep steal of all
3815                    the SEC_DESC members */
3816
3817                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3818         }
3819
3820         return WERR_OK;
3821 }
3822
3823 /********************************************************************
3824  * construct_printer_info3
3825  * fill a spoolss_PrinterInfo3 struct
3826  ********************************************************************/
3827
3828 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3829                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3830                                       struct spoolss_PrinterInfo3 *r,
3831                                       int snum)
3832 {
3833         /* These are the components of the SD we are returning. */
3834
3835         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3836                 /* don't use talloc_steal() here unless you do a deep steal of all
3837                    the SEC_DESC members */
3838
3839                 r->secdesc = dup_sec_desc(mem_ctx,
3840                                           ntprinter->info_2->secdesc_buf->sd);
3841                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3842         }
3843
3844         return WERR_OK;
3845 }
3846
3847 /********************************************************************
3848  * construct_printer_info4
3849  * fill a spoolss_PrinterInfo4 struct
3850  ********************************************************************/
3851
3852 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3853                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3854                                       struct spoolss_PrinterInfo4 *r,
3855                                       int snum)
3856 {
3857         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3858         W_ERROR_HAVE_NO_MEMORY(r->printername);
3859         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3860         W_ERROR_HAVE_NO_MEMORY(r->servername);
3861
3862         r->attributes   = ntprinter->info_2->attributes;
3863
3864         return WERR_OK;
3865 }
3866
3867 /********************************************************************
3868  * construct_printer_info5
3869  * fill a spoolss_PrinterInfo5 struct
3870  ********************************************************************/
3871
3872 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3873                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3874                                       struct spoolss_PrinterInfo5 *r,
3875                                       int snum)
3876 {
3877         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3878         W_ERROR_HAVE_NO_MEMORY(r->printername);
3879         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3880         W_ERROR_HAVE_NO_MEMORY(r->portname);
3881
3882         r->attributes   = ntprinter->info_2->attributes;
3883
3884         /* these two are not used by NT+ according to MSDN */
3885
3886         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3887         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3888
3889         return WERR_OK;
3890 }
3891
3892 /********************************************************************
3893  * construct_printer_info_6
3894  * fill a spoolss_PrinterInfo6 struct
3895  ********************************************************************/
3896
3897 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3898                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3899                                       struct spoolss_PrinterInfo6 *r,
3900                                       int snum)
3901 {
3902         int count;
3903         print_status_struct status;
3904
3905         count = print_queue_length(snum, &status);
3906
3907         r->status = nt_printq_status(status.status);
3908
3909         return WERR_OK;
3910 }
3911
3912 /********************************************************************
3913  * construct_printer_info7
3914  * fill a spoolss_PrinterInfo7 struct
3915  ********************************************************************/
3916
3917 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3918                                       Printer_entry *print_hnd,
3919                                       struct spoolss_PrinterInfo7 *r,
3920                                       int snum)
3921 {
3922         struct GUID guid;
3923
3924         if (is_printer_published(print_hnd, snum, &guid)) {
3925                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3926                 r->action = DSPRINT_PUBLISH;
3927         } else {
3928                 r->guid = talloc_strdup(mem_ctx, "");
3929                 r->action = DSPRINT_UNPUBLISH;
3930         }
3931         W_ERROR_HAVE_NO_MEMORY(r->guid);
3932
3933         return WERR_OK;
3934 }
3935
3936 /********************************************************************
3937  * construct_printer_info8
3938  * fill a spoolss_PrinterInfo8 struct
3939  ********************************************************************/
3940
3941 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3942                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3943                                       struct spoolss_DeviceModeInfo *r,
3944                                       int snum)
3945 {
3946         struct spoolss_DeviceMode *devmode;
3947         WERROR result;
3948
3949         if (!ntprinter->info_2->devmode) {
3950                 r->devmode = NULL;
3951                 return WERR_OK;
3952         }
3953
3954         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3955         W_ERROR_HAVE_NO_MEMORY(devmode);
3956
3957         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
3958         if (!W_ERROR_IS_OK(result)) {
3959                 TALLOC_FREE(devmode);
3960                 return result;
3961         }
3962
3963         r->devmode      = devmode;
3964
3965         return WERR_OK;
3966 }
3967
3968
3969 /********************************************************************
3970 ********************************************************************/
3971
3972 static bool snum_is_shared_printer(int snum)
3973 {
3974         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3975 }
3976
3977 /********************************************************************
3978  Spoolss_enumprinters.
3979 ********************************************************************/
3980
3981 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3982                                            uint32_t level,
3983                                            uint32_t flags,
3984                                            union spoolss_PrinterInfo **info_p,
3985                                            uint32_t *count_p)
3986 {
3987         int snum;
3988         int n_services = lp_numservices();
3989         union spoolss_PrinterInfo *info = NULL;
3990         uint32_t count = 0;
3991         WERROR result = WERR_OK;
3992
3993         *count_p = 0;
3994         *info_p = NULL;
3995
3996         for (snum = 0; snum < n_services; snum++) {
3997
3998                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3999
4000                 if (!snum_is_shared_printer(snum)) {
4001                         continue;
4002                 }
4003
4004                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4005                         lp_servicename(snum), snum));
4006
4007                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4008                                             union spoolss_PrinterInfo,
4009                                             count + 1);
4010                 if (!info) {
4011                         result = WERR_NOMEM;
4012                         goto out;
4013                 }
4014
4015                 result = get_a_printer(NULL, &ntprinter, 2,
4016                                        lp_const_servicename(snum));
4017                 if (!W_ERROR_IS_OK(result)) {
4018                         goto out;
4019                 }
4020
4021                 switch (level) {
4022                 case 0:
4023                         result = construct_printer_info0(info, ntprinter,
4024                                                          &info[count].info0, snum);
4025                         break;
4026                 case 1:
4027                         result = construct_printer_info1(info, ntprinter, flags,
4028                                                          &info[count].info1, snum);
4029                         break;
4030                 case 2:
4031                         result = construct_printer_info2(info, ntprinter,
4032                                                          &info[count].info2, snum);
4033                         break;
4034                 case 4:
4035                         result = construct_printer_info4(info, ntprinter,
4036                                                          &info[count].info4, snum);
4037                         break;
4038                 case 5:
4039                         result = construct_printer_info5(info, ntprinter,
4040                                                          &info[count].info5, snum);
4041                         break;
4042
4043                 default:
4044                         result = WERR_UNKNOWN_LEVEL;
4045                         free_a_printer(&ntprinter, 2);
4046                         goto out;
4047                 }
4048
4049                 free_a_printer(&ntprinter, 2);
4050                 if (!W_ERROR_IS_OK(result)) {
4051                         goto out;
4052                 }
4053
4054                 count++;
4055         }
4056
4057         *count_p = count;
4058         *info_p = info;
4059
4060  out:
4061         if (!W_ERROR_IS_OK(result)) {
4062                 TALLOC_FREE(info);
4063                 return result;
4064         }
4065
4066         *info_p = info;
4067
4068         return WERR_OK;
4069 }
4070
4071 /********************************************************************
4072  * handle enumeration of printers at level 0
4073  ********************************************************************/
4074
4075 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4076                                   uint32_t flags,
4077                                   const char *servername,
4078                                   union spoolss_PrinterInfo **info,
4079                                   uint32_t *count)
4080 {
4081         DEBUG(4,("enum_all_printers_info_0\n"));
4082
4083         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4084 }
4085
4086
4087 /********************************************************************
4088 ********************************************************************/
4089
4090 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4091                                        uint32_t flags,
4092                                        union spoolss_PrinterInfo **info,
4093                                        uint32_t *count)
4094 {
4095         DEBUG(4,("enum_all_printers_info_1\n"));
4096
4097         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4098 }
4099
4100 /********************************************************************
4101  enum_all_printers_info_1_local.
4102 *********************************************************************/
4103
4104 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4105                                              union spoolss_PrinterInfo **info,
4106                                              uint32_t *count)
4107 {
4108         DEBUG(4,("enum_all_printers_info_1_local\n"));
4109
4110         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4111 }
4112
4113 /********************************************************************
4114  enum_all_printers_info_1_name.
4115 *********************************************************************/
4116
4117 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4118                                             const char *name,
4119                                             union spoolss_PrinterInfo **info,
4120                                             uint32_t *count)
4121 {
4122         const char *s = name;
4123
4124         DEBUG(4,("enum_all_printers_info_1_name\n"));
4125
4126         if ((name[0] == '\\') && (name[1] == '\\')) {
4127                 s = name + 2;
4128         }
4129
4130         if (!is_myname_or_ipaddr(s)) {
4131                 return WERR_INVALID_NAME;
4132         }
4133
4134         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4135 }
4136
4137 /********************************************************************
4138  enum_all_printers_info_1_network.
4139 *********************************************************************/
4140
4141 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4142                                                const char *name,
4143                                                union spoolss_PrinterInfo **info,
4144                                                uint32_t *count)
4145 {
4146         const char *s = name;
4147
4148         DEBUG(4,("enum_all_printers_info_1_network\n"));
4149
4150         /* If we respond to a enum_printers level 1 on our name with flags
4151            set to PRINTER_ENUM_REMOTE with a list of printers then these
4152            printers incorrectly appear in the APW browse list.
4153            Specifically the printers for the server appear at the workgroup
4154            level where all the other servers in the domain are
4155            listed. Windows responds to this call with a
4156            WERR_CAN_NOT_COMPLETE so we should do the same. */
4157
4158         if (name[0] == '\\' && name[1] == '\\') {
4159                  s = name + 2;
4160         }
4161
4162         if (is_myname_or_ipaddr(s)) {
4163                  return WERR_CAN_NOT_COMPLETE;
4164         }
4165
4166         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4167 }
4168
4169 /********************************************************************
4170  * api_spoolss_enumprinters
4171  *
4172  * called from api_spoolss_enumprinters (see this to understand)
4173  ********************************************************************/
4174
4175 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4176                                        union spoolss_PrinterInfo **info,
4177                                        uint32_t *count)
4178 {
4179         DEBUG(4,("enum_all_printers_info_2\n"));
4180
4181         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4182 }
4183
4184 /********************************************************************
4185  * handle enumeration of printers at level 1
4186  ********************************************************************/
4187
4188 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4189                                   uint32_t flags,
4190                                   const char *name,
4191                                   union spoolss_PrinterInfo **info,
4192                                   uint32_t *count)
4193 {
4194         /* Not all the flags are equals */
4195
4196         if (flags & PRINTER_ENUM_LOCAL) {
4197                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4198         }
4199
4200         if (flags & PRINTER_ENUM_NAME) {
4201                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4202         }
4203
4204         if (flags & PRINTER_ENUM_NETWORK) {
4205                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4206         }
4207
4208         return WERR_OK; /* NT4sp5 does that */
4209 }
4210
4211 /********************************************************************
4212  * handle enumeration of printers at level 2
4213  ********************************************************************/
4214
4215 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4216                                   uint32_t flags,
4217                                   const char *servername,
4218                                   union spoolss_PrinterInfo **info,
4219                                   uint32_t *count)
4220 {
4221         if (flags & PRINTER_ENUM_LOCAL) {
4222                 return enum_all_printers_info_2(mem_ctx, info, count);
4223         }
4224
4225         if (flags & PRINTER_ENUM_NAME) {
4226                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4227                         return WERR_INVALID_NAME;
4228                 }
4229
4230                 return enum_all_printers_info_2(mem_ctx, info, count);
4231         }
4232
4233         if (flags & PRINTER_ENUM_REMOTE) {
4234                 return WERR_UNKNOWN_LEVEL;
4235         }
4236
4237         return WERR_OK;
4238 }
4239
4240 /********************************************************************
4241  * handle enumeration of printers at level 4
4242  ********************************************************************/
4243
4244 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4245                                   uint32_t flags,
4246                                   const char *servername,
4247                                   union spoolss_PrinterInfo **info,
4248                                   uint32_t *count)
4249 {
4250         DEBUG(4,("enum_all_printers_info_4\n"));
4251
4252         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4253 }
4254
4255
4256 /********************************************************************
4257  * handle enumeration of printers at level 5
4258  ********************************************************************/
4259
4260 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4261                                   uint32_t flags,
4262                                   const char *servername,
4263                                   union spoolss_PrinterInfo **info,
4264                                   uint32_t *count)
4265 {
4266         DEBUG(4,("enum_all_printers_info_5\n"));
4267
4268         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4269 }
4270
4271 /****************************************************************
4272  _spoolss_EnumPrinters
4273 ****************************************************************/
4274
4275 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4276                              struct spoolss_EnumPrinters *r)
4277 {
4278         const char *name;
4279         WERROR result;
4280
4281         /* that's an [in out] buffer */
4282
4283         if (!r->in.buffer && (r->in.offered != 0)) {
4284                 return WERR_INVALID_PARAM;
4285         }
4286
4287         DEBUG(4,("_spoolss_EnumPrinters\n"));
4288
4289         *r->out.needed = 0;
4290         *r->out.count = 0;
4291         *r->out.info = NULL;
4292
4293         /*
4294          * Level 1:
4295          *          flags==PRINTER_ENUM_NAME
4296          *           if name=="" then enumerates all printers
4297          *           if name!="" then enumerate the printer
4298          *          flags==PRINTER_ENUM_REMOTE
4299          *          name is NULL, enumerate printers
4300          * Level 2: name!="" enumerates printers, name can't be NULL
4301          * Level 3: doesn't exist
4302          * Level 4: does a local registry lookup
4303          * Level 5: same as Level 2
4304          */
4305
4306         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4307         W_ERROR_HAVE_NO_MEMORY(name);
4308
4309         switch (r->in.level) {
4310         case 0:
4311                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4312                                              r->out.info, r->out.count);
4313                 break;
4314         case 1:
4315                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4316                                              r->out.info, r->out.count);
4317                 break;
4318         case 2:
4319                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4320                                              r->out.info, r->out.count);
4321                 break;
4322         case 4:
4323                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4324                                              r->out.info, r->out.count);
4325                 break;
4326         case 5:
4327                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4328                                              r->out.info, r->out.count);
4329                 break;
4330         default:
4331                 return WERR_UNKNOWN_LEVEL;
4332         }
4333
4334         if (!W_ERROR_IS_OK(result)) {
4335                 return result;
4336         }
4337
4338         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4339                                                      spoolss_EnumPrinters, NULL,
4340                                                      *r->out.info, r->in.level,
4341                                                      *r->out.count);
4342         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4343         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4344
4345         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4346 }
4347
4348 /****************************************************************
4349  _spoolss_GetPrinter
4350 ****************************************************************/
4351
4352 WERROR _spoolss_GetPrinter(pipes_struct *p,
4353                            struct spoolss_GetPrinter *r)
4354 {
4355         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4356         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4357         WERROR result = WERR_OK;
4358
4359         int snum;
4360
4361         /* that's an [in out] buffer */
4362
4363         if (!r->in.buffer && (r->in.offered != 0)) {
4364                 return WERR_INVALID_PARAM;
4365         }
4366
4367         *r->out.needed = 0;
4368
4369         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4370                 return WERR_BADFID;
4371         }
4372
4373         result = get_a_printer(Printer, &ntprinter, 2,
4374                                lp_const_servicename(snum));
4375         if (!W_ERROR_IS_OK(result)) {
4376                 return result;
4377         }
4378
4379         switch (r->in.level) {
4380         case 0:
4381                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4382                                                  &r->out.info->info0, snum);
4383                 break;
4384         case 1:
4385                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4386                                                  PRINTER_ENUM_ICON8,
4387                                                  &r->out.info->info1, snum);
4388                 break;
4389         case 2:
4390                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4391                                                  &r->out.info->info2, snum);
4392                 break;
4393         case 3:
4394                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4395                                                  &r->out.info->info3, snum);
4396                 break;
4397         case 4:
4398                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4399                                                  &r->out.info->info4, snum);
4400                 break;
4401         case 5:
4402                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4403                                                  &r->out.info->info5, snum);
4404                 break;
4405         case 6:
4406                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4407                                                  &r->out.info->info6, snum);
4408                 break;
4409         case 7:
4410                 result = construct_printer_info7(p->mem_ctx, Printer,
4411                                                  &r->out.info->info7, snum);
4412                 break;
4413         case 8:
4414                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4415                                                  &r->out.info->info8, snum);
4416                 break;
4417         default:
4418                 result = WERR_UNKNOWN_LEVEL;
4419                 break;
4420         }
4421
4422         free_a_printer(&ntprinter, 2);
4423
4424         if (!W_ERROR_IS_OK(result)) {
4425                 TALLOC_FREE(r->out.info);
4426                 return result;
4427         }
4428
4429         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4430                                                r->out.info, r->in.level);
4431         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4432
4433         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4434 }
4435
4436 /********************************************************************
4437  ********************************************************************/
4438
4439 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4440                                                   const char **string_array,
4441                                                   const char *cservername)
4442 {
4443         int i, num_strings = 0;
4444         const char **array = NULL;
4445
4446         if (!string_array) {
4447                 return NULL;
4448         }
4449
4450         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4451
4452                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4453                                                   cservername, string_array[i]);
4454                 if (!str) {
4455                         TALLOC_FREE(array);
4456                         return NULL;
4457                 }
4458
4459
4460                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4461                         TALLOC_FREE(array);
4462                         return NULL;
4463                 }
4464         }
4465
4466         if (i > 0) {
4467                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4468                              &array, &num_strings);
4469         }
4470
4471         return array;
4472 }
4473
4474 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4475         do { \
4476                 if (in && strlen(in)) { \
4477                         out = talloc_strdup(mem_ctx, in); \
4478                         W_ERROR_HAVE_NO_MEMORY(out); \
4479                 } \
4480         } while (0);
4481
4482 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4483         do { \
4484                 if (in && strlen(in)) { \
4485                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4486                 } else { \
4487                         out = talloc_strdup(mem_ctx, ""); \
4488                 } \
4489                 W_ERROR_HAVE_NO_MEMORY(out); \
4490         } while (0);
4491
4492 /********************************************************************
4493  * fill a spoolss_DriverInfo1 struct
4494  ********************************************************************/
4495
4496 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4497                                         struct spoolss_DriverInfo1 *r,
4498                                         const struct spoolss_DriverInfo3 *driver,
4499                                         const char *servername,
4500                                         const char *architecture)
4501 {
4502         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4503         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4504
4505         return WERR_OK;
4506 }
4507
4508 /********************************************************************
4509  * fill a spoolss_DriverInfo2 struct
4510  ********************************************************************/
4511
4512 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4513                                         struct spoolss_DriverInfo2 *r,
4514                                         const struct spoolss_DriverInfo3 *driver,
4515                                         const char *servername)
4516
4517 {
4518         const char *cservername = canon_servername(servername);
4519
4520         r->version              = driver->version;
4521
4522         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4523         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4524         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4525         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4526
4527         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4528                                driver->driver_path,
4529                                r->driver_path);
4530
4531         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4532                                driver->data_file,
4533                                r->data_file);
4534
4535         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4536                                driver->config_file,
4537                                r->config_file);
4538
4539         return WERR_OK;
4540 }
4541
4542 /********************************************************************
4543  * fill a spoolss_DriverInfo3 struct
4544  ********************************************************************/
4545
4546 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4547                                         struct spoolss_DriverInfo3 *r,
4548                                         const struct spoolss_DriverInfo3 *driver,
4549                                         const char *servername)
4550 {
4551         const char *cservername = canon_servername(servername);
4552
4553         r->version              = driver->version;
4554
4555         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4556         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4557         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4558         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4559
4560         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4561                                driver->driver_path,
4562                                r->driver_path);
4563
4564         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4565                                driver->data_file,
4566                                r->data_file);
4567
4568         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4569                                driver->config_file,
4570                                r->config_file);
4571
4572         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573                                driver->help_file,
4574                                r->help_file);
4575
4576         FILL_DRIVER_STRING(mem_ctx,
4577                            driver->monitor_name,
4578                            r->monitor_name);
4579
4580         FILL_DRIVER_STRING(mem_ctx,
4581                            driver->default_datatype,
4582                            r->default_datatype);
4583
4584         r->dependent_files = string_array_from_driver_info(mem_ctx,
4585                                                            driver->dependent_files,
4586                                                            cservername);
4587         return WERR_OK;
4588 }
4589
4590 /********************************************************************
4591  * fill a spoolss_DriverInfo4 struct
4592  ********************************************************************/
4593
4594 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4595                                         struct spoolss_DriverInfo4 *r,
4596                                         const struct spoolss_DriverInfo3 *driver,
4597                                         const char *servername)
4598 {
4599         const char *cservername = canon_servername(servername);
4600
4601         r->version              = driver->version;
4602
4603         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4604         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4605         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4606         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4607
4608         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4609                                driver->driver_path,
4610                                r->driver_path);
4611
4612         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4613                                driver->data_file,
4614                                r->data_file);
4615
4616         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4617                                driver->config_file,
4618                                r->config_file);
4619
4620         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4621                                driver->help_file,
4622                                r->help_file);
4623
4624         r->dependent_files = string_array_from_driver_info(mem_ctx,
4625                                                            driver->dependent_files,
4626                                                            cservername);
4627
4628         FILL_DRIVER_STRING(mem_ctx,
4629                            driver->monitor_name,
4630                            r->monitor_name);
4631
4632         FILL_DRIVER_STRING(mem_ctx,
4633                            driver->default_datatype,
4634                            r->default_datatype);
4635
4636         r->previous_names = string_array_from_driver_info(mem_ctx,
4637                                                           NULL,
4638                                                           cservername);
4639
4640         return WERR_OK;
4641 }
4642
4643 /********************************************************************
4644  * fill a spoolss_DriverInfo5 struct
4645  ********************************************************************/
4646
4647 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4648                                         struct spoolss_DriverInfo5 *r,
4649                                         const struct spoolss_DriverInfo3 *driver,
4650                                         const char *servername)
4651 {
4652         const char *cservername = canon_servername(servername);
4653
4654         r->version              = driver->version;
4655
4656         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4657         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4658         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4659         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4660
4661         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4662                                driver->driver_path,
4663                                r->driver_path);
4664
4665         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4666                                driver->data_file,
4667                                r->data_file);
4668
4669         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4670                                driver->config_file,
4671                                r->config_file);
4672
4673         r->driver_attributes    = 0;
4674         r->config_version       = 0;
4675         r->driver_version       = 0;
4676
4677         return WERR_OK;
4678 }
4679 /********************************************************************
4680  * fill a spoolss_DriverInfo6 struct
4681  ********************************************************************/
4682
4683 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4684                                         struct spoolss_DriverInfo6 *r,
4685                                         const struct spoolss_DriverInfo3 *driver,
4686                                         const char *servername)
4687 {
4688         const char *cservername = canon_servername(servername);
4689
4690         r->version              = driver->version;
4691
4692         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4693         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4694         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4695         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4696
4697         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4698                                driver->driver_path,
4699                                r->driver_path);
4700
4701         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4702                                driver->data_file,
4703                                r->data_file);
4704
4705         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4706                                driver->config_file,
4707                                r->config_file);
4708
4709         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4710                                driver->help_file,
4711                                r->help_file);
4712
4713         FILL_DRIVER_STRING(mem_ctx,
4714                            driver->monitor_name,
4715                            r->monitor_name);
4716
4717         FILL_DRIVER_STRING(mem_ctx,
4718                            driver->default_datatype,
4719                            r->default_datatype);
4720
4721         r->dependent_files = string_array_from_driver_info(mem_ctx,
4722                                                            driver->dependent_files,
4723                                                            cservername);
4724         r->previous_names = string_array_from_driver_info(mem_ctx,
4725                                                           NULL,
4726                                                           cservername);
4727
4728         r->driver_date          = 0;
4729         r->driver_version       = 0;
4730
4731         FILL_DRIVER_STRING(mem_ctx, "",
4732                            r->manufacturer_name);
4733         FILL_DRIVER_STRING(mem_ctx, "",
4734                            r->manufacturer_url);
4735         FILL_DRIVER_STRING(mem_ctx, "",
4736                            r->hardware_id);
4737         FILL_DRIVER_STRING(mem_ctx, "",
4738                            r->provider);
4739
4740         return WERR_OK;
4741 }
4742
4743 /********************************************************************
4744  ********************************************************************/
4745
4746 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4747                                           struct spoolss_DriverFileInfo *r,
4748                                           const char *cservername,
4749                                           const char *file_name,
4750                                           enum spoolss_DriverFileType file_type,
4751                                           uint32_t file_version)
4752 {
4753         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4754                                           cservername, file_name);
4755         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4756         r->file_type    = file_type;
4757         r->file_version = file_version;
4758
4759         return WERR_OK;
4760 }
4761
4762 /********************************************************************
4763  ********************************************************************/
4764
4765 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4766                                                  const struct spoolss_DriverInfo3 *driver,
4767                                                  const char *cservername,
4768                                                  struct spoolss_DriverFileInfo **info_p,
4769                                                  uint32_t *count_p)
4770 {
4771         struct spoolss_DriverFileInfo *info = NULL;
4772         uint32_t count = 0;
4773         WERROR result;
4774         uint32_t i;
4775
4776         *info_p = NULL;
4777         *count_p = 0;
4778
4779         if (strlen(driver->driver_path)) {
4780                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4781                                             struct spoolss_DriverFileInfo,
4782                                             count + 1);
4783                 W_ERROR_HAVE_NO_MEMORY(info);
4784                 result = fill_spoolss_DriverFileInfo(info,
4785                                                      &info[count],
4786                                                      cservername,
4787                                                      driver->driver_path,
4788                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4789                                                      0);
4790                 W_ERROR_NOT_OK_RETURN(result);
4791                 count++;
4792         }
4793
4794         if (strlen(driver->config_file)) {
4795                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4796                                             struct spoolss_DriverFileInfo,
4797                                             count + 1);
4798                 W_ERROR_HAVE_NO_MEMORY(info);
4799                 result = fill_spoolss_DriverFileInfo(info,
4800                                                      &info[count],
4801                                                      cservername,
4802                                                      driver->config_file,
4803                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4804                                                      0);
4805                 W_ERROR_NOT_OK_RETURN(result);
4806                 count++;
4807         }
4808
4809         if (strlen(driver->data_file)) {
4810                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4811                                             struct spoolss_DriverFileInfo,
4812                                             count + 1);
4813                 W_ERROR_HAVE_NO_MEMORY(info);
4814                 result = fill_spoolss_DriverFileInfo(info,
4815                                                      &info[count],
4816                                                      cservername,
4817                                                      driver->data_file,
4818                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4819                                                      0);
4820                 W_ERROR_NOT_OK_RETURN(result);
4821                 count++;
4822         }
4823
4824         if (strlen(driver->help_file)) {
4825                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4826                                             struct spoolss_DriverFileInfo,
4827                                             count + 1);
4828                 W_ERROR_HAVE_NO_MEMORY(info);
4829                 result = fill_spoolss_DriverFileInfo(info,
4830                                                      &info[count],
4831                                                      cservername,
4832                                                      driver->help_file,
4833                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4834                                                      0);
4835                 W_ERROR_NOT_OK_RETURN(result);
4836                 count++;
4837         }
4838
4839         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4840                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4841                                             struct spoolss_DriverFileInfo,
4842                                             count + 1);
4843                 W_ERROR_HAVE_NO_MEMORY(info);
4844                 result = fill_spoolss_DriverFileInfo(info,
4845                                                      &info[count],
4846                                                      cservername,
4847                                                      driver->dependent_files[i],
4848                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4849                                                      0);
4850                 W_ERROR_NOT_OK_RETURN(result);
4851                 count++;
4852         }
4853
4854         *info_p = info;
4855         *count_p = count;
4856
4857         return WERR_OK;
4858 }
4859
4860 /********************************************************************
4861  * fill a spoolss_DriverInfo101 sttruct
4862  ********************************************************************/
4863
4864 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4865                                           struct spoolss_DriverInfo101 *r,
4866                                           const struct spoolss_DriverInfo3 *driver,
4867                                           const char *servername)
4868 {
4869         const char *cservername = canon_servername(servername);
4870         WERROR result;
4871
4872         r->version              = driver->version;
4873
4874         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4875         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4876         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4877         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4878
4879         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4880                                                     cservername,
4881                                                     &r->file_info,
4882                                                     &r->file_count);
4883         if (!W_ERROR_IS_OK(result)) {
4884                 return result;
4885         }
4886
4887         FILL_DRIVER_STRING(mem_ctx,
4888                            driver->monitor_name,
4889                            r->monitor_name);
4890
4891         FILL_DRIVER_STRING(mem_ctx,
4892                            driver->default_datatype,
4893                            r->default_datatype);
4894
4895         r->previous_names = string_array_from_driver_info(mem_ctx,
4896                                                           NULL,
4897                                                           cservername);
4898         r->driver_date          = 0;
4899         r->driver_version       = 0;
4900
4901         FILL_DRIVER_STRING(mem_ctx, "",
4902                            r->manufacturer_name);
4903         FILL_DRIVER_STRING(mem_ctx, "",
4904                            r->manufacturer_url);
4905         FILL_DRIVER_STRING(mem_ctx, "",
4906                            r->hardware_id);
4907         FILL_DRIVER_STRING(mem_ctx, "",
4908                            r->provider);
4909
4910         return WERR_OK;
4911 }
4912
4913 /********************************************************************
4914  * construct_printer_driver_info_1
4915  ********************************************************************/
4916
4917 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
4918                                               struct spoolss_DriverInfo1 *r,
4919                                               int snum,
4920                                               const char *servername,
4921                                               const char *architecture,
4922                                               uint32_t version)
4923 {
4924         NT_PRINTER_INFO_LEVEL *printer = NULL;
4925         union spoolss_DriverInfo *driver;
4926         WERROR result;
4927
4928         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4929                 return WERR_INVALID_PRINTER_NAME;
4930
4931         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
4932                 free_a_printer(&printer, 2);
4933                 return WERR_UNKNOWN_PRINTER_DRIVER;
4934         }
4935
4936         result = fill_printer_driver_info1(mem_ctx, r, &driver->info3, servername, architecture);
4937
4938         free_a_printer_driver(driver);
4939         free_a_printer(&printer,2);
4940
4941         return result;
4942 }
4943
4944 /********************************************************************
4945  * construct_printer_driver_info_2
4946  * fill a printer_info_2 struct
4947  ********************************************************************/
4948
4949 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
4950                                               struct spoolss_DriverInfo2 *r,
4951                                               int snum,
4952                                               const char *servername,
4953                                               const char *architecture,
4954                                               uint32_t version)
4955 {
4956         NT_PRINTER_INFO_LEVEL *printer = NULL;
4957         union spoolss_DriverInfo *driver;
4958         WERROR result;
4959
4960         ZERO_STRUCT(printer);
4961
4962         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4963                 return WERR_INVALID_PRINTER_NAME;
4964
4965         if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version))) {
4966                 free_a_printer(&printer, 2);
4967                 return WERR_UNKNOWN_PRINTER_DRIVER;
4968         }
4969
4970         result = fill_printer_driver_info2(mem_ctx, r, &driver->info3, servername);
4971
4972         free_a_printer_driver(driver);
4973         free_a_printer(&printer,2);
4974
4975         return result;
4976 }
4977
4978 /********************************************************************
4979  * construct_printer_info_3
4980  * fill a printer_info_3 struct
4981  ********************************************************************/
4982
4983 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
4984                                               struct spoolss_DriverInfo3 *r,
4985                                               int snum,
4986                                               const char *servername,
4987                                               const char *architecture,
4988                                               uint32_t version)
4989 {
4990         NT_PRINTER_INFO_LEVEL *printer = NULL;
4991         union spoolss_DriverInfo *driver;
4992         WERROR status;
4993         ZERO_STRUCT(driver);
4994
4995         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
4996         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
4997         if (!W_ERROR_IS_OK(status))
4998                 return WERR_INVALID_PRINTER_NAME;
4999
5000         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5001         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5002
5003 #if 0   /* JERRY */
5004
5005         /*
5006          * I put this code in during testing.  Helpful when commenting out the
5007          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5008          * as win2k always queries the driver using an infor level of 6.
5009          * I've left it in (but ifdef'd out) because I'll probably
5010          * use it in experimentation again in the future.   --jerry 22/01/2002
5011          */
5012
5013         if (!W_ERROR_IS_OK(status)) {
5014                 /*
5015                  * Is this a W2k client ?
5016                  */
5017                 if (version == 3) {
5018                         /* Yes - try again with a WinNT driver. */
5019                         version = 2;
5020                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5021                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5022                 }
5023 #endif
5024
5025                 if (!W_ERROR_IS_OK(status)) {
5026                         free_a_printer(&printer,2);
5027                         return WERR_UNKNOWN_PRINTER_DRIVER;
5028                 }
5029
5030 #if 0   /* JERRY */
5031         }
5032 #endif
5033
5034
5035         status = fill_printer_driver_info3(mem_ctx, r, &driver->info3, servername);
5036
5037         free_a_printer_driver(driver);
5038         free_a_printer(&printer,2);
5039
5040         return status;
5041 }
5042
5043 /********************************************************************
5044  * construct_printer_info_6
5045  * fill a printer_info_6 struct
5046  ********************************************************************/
5047
5048 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5049                                               struct spoolss_DriverInfo6 *r,
5050                                               int snum,
5051                                               const char *servername,
5052                                               const char *architecture,
5053                                               uint32_t version)
5054 {
5055         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5056         union spoolss_DriverInfo *driver;
5057         WERROR                          status;
5058
5059         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5060
5061         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5062
5063         if (!W_ERROR_IS_OK(status))
5064                 return WERR_INVALID_PRINTER_NAME;
5065
5066         status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5067
5068         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5069
5070         if (!W_ERROR_IS_OK(status))
5071         {
5072                 /*
5073                  * Is this a W2k client ?
5074                  */
5075
5076                 if (version < 3) {
5077                         free_a_printer(&printer,2);
5078                         return WERR_UNKNOWN_PRINTER_DRIVER;
5079                 }
5080
5081                 /* Yes - try again with a WinNT driver. */
5082                 version = 2;
5083                 status = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername, architecture, version);
5084                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5085                 if (!W_ERROR_IS_OK(status)) {
5086                         free_a_printer(&printer,2);
5087                         return WERR_UNKNOWN_PRINTER_DRIVER;
5088                 }
5089         }
5090
5091         status = fill_printer_driver_info6(mem_ctx, r, &driver->info3, servername);
5092
5093         free_a_printer(&printer,2);
5094         free_a_printer_driver(driver);
5095
5096         return status;
5097 }
5098
5099 /********************************************************************
5100  * construct_printer_info_101
5101  * fill a printer_info_101 struct
5102  ********************************************************************/
5103
5104 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5105                                                 struct spoolss_DriverInfo101 *r,
5106                                                 int snum,
5107                                                 const char *servername,
5108                                                 const char *architecture,
5109                                                 uint32_t version)
5110 {
5111         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5112         union spoolss_DriverInfo *driver;
5113         WERROR                          result;
5114
5115         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5116
5117         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5118                 win_errstr(result)));
5119
5120         if (!W_ERROR_IS_OK(result)) {
5121                 return WERR_INVALID_PRINTER_NAME;
5122         }
5123
5124         result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5125                                       architecture, version);
5126
5127         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5128                 win_errstr(result)));
5129
5130         if (!W_ERROR_IS_OK(result)) {
5131                 /*
5132                  * Is this a W2k client ?
5133                  */
5134
5135                 if (version < 3) {
5136                         free_a_printer(&printer, 2);
5137                         return WERR_UNKNOWN_PRINTER_DRIVER;
5138                 }
5139
5140                 /* Yes - try again with a WinNT driver. */
5141                 version = 2;
5142                 result = get_a_printer_driver(mem_ctx, &driver, 3, printer->info_2->drivername,
5143                                               architecture, version);
5144                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5145                         win_errstr(result)));
5146                 if (!W_ERROR_IS_OK(result)) {
5147                         free_a_printer(&printer, 2);
5148                         return WERR_UNKNOWN_PRINTER_DRIVER;
5149                 }
5150         }
5151
5152         result = fill_printer_driver_info101(mem_ctx, r, &driver->info3, servername);
5153
5154         free_a_printer(&printer, 2);
5155         free_a_printer_driver(driver);
5156
5157         return result;
5158 }
5159
5160 /****************************************************************
5161  _spoolss_GetPrinterDriver2
5162 ****************************************************************/
5163
5164 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5165                                   struct spoolss_GetPrinterDriver2 *r)
5166 {
5167         Printer_entry *printer;
5168         WERROR result;
5169
5170         const char *servername;
5171         int snum;
5172
5173         /* that's an [in out] buffer */
5174
5175         if (!r->in.buffer && (r->in.offered != 0)) {
5176                 return WERR_INVALID_PARAM;
5177         }
5178
5179         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5180
5181         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5182                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5183                 return WERR_INVALID_PRINTER_NAME;
5184         }
5185
5186         *r->out.needed = 0;
5187         *r->out.server_major_version = 0;
5188         *r->out.server_minor_version = 0;
5189
5190         servername = get_server_name(printer);
5191
5192         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5193                 return WERR_BADFID;
5194         }
5195
5196         switch (r->in.level) {
5197         case 1:
5198                 result = construct_printer_driver_info_1(p->mem_ctx,
5199                                                          &r->out.info->info1,
5200                                                          snum,
5201                                                          servername,
5202                                                          r->in.architecture,
5203                                                          r->in.client_major_version);
5204                 break;
5205         case 2:
5206                 result = construct_printer_driver_info_2(p->mem_ctx,
5207                                                          &r->out.info->info2,
5208                                                          snum,
5209                                                          servername,
5210                                                          r->in.architecture,
5211                                                          r->in.client_major_version);
5212                 break;
5213         case 3:
5214                 result = construct_printer_driver_info_3(p->mem_ctx,
5215                                                          &r->out.info->info3,
5216                                                          snum,
5217                                                          servername,
5218                                                          r->in.architecture,
5219                                                          r->in.client_major_version);
5220                 break;
5221         case 6:
5222                 result = construct_printer_driver_info_6(p->mem_ctx,
5223                                                          &r->out.info->info6,
5224                                                          snum,
5225                                                          servername,
5226                                                          r->in.architecture,
5227                                                          r->in.client_major_version);
5228                 break;
5229         case 101:
5230                 result = construct_printer_driver_info_101(p->mem_ctx,
5231                                                            &r->out.info->info101,
5232                                                            snum,
5233                                                            servername,
5234                                                            r->in.architecture,
5235                                                            r->in.client_major_version);
5236                 break;
5237         default:
5238                 result = WERR_UNKNOWN_LEVEL;
5239                 break;
5240         }
5241
5242         if (!W_ERROR_IS_OK(result)) {
5243                 TALLOC_FREE(r->out.info);
5244                 return result;
5245         }
5246
5247         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5248                                                r->out.info, r->in.level);
5249         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5250
5251         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5252 }
5253
5254
5255 /****************************************************************
5256  _spoolss_StartPagePrinter
5257 ****************************************************************/
5258
5259 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5260                                  struct spoolss_StartPagePrinter *r)
5261 {
5262         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5263
5264         if (!Printer) {
5265                 DEBUG(3,("_spoolss_StartPagePrinter: "
5266                         "Error in startpageprinter printer handle\n"));
5267                 return WERR_BADFID;
5268         }
5269
5270         Printer->page_started = true;
5271         return WERR_OK;
5272 }
5273
5274 /****************************************************************
5275  _spoolss_EndPagePrinter
5276 ****************************************************************/
5277
5278 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5279                                struct spoolss_EndPagePrinter *r)
5280 {
5281         int snum;
5282
5283         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5284
5285         if (!Printer) {
5286                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5287                         OUR_HANDLE(r->in.handle)));
5288                 return WERR_BADFID;
5289         }
5290
5291         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5292                 return WERR_BADFID;
5293
5294         Printer->page_started = false;
5295         print_job_endpage(snum, Printer->jobid);
5296
5297         return WERR_OK;
5298 }
5299
5300 /****************************************************************
5301  _spoolss_StartDocPrinter
5302 ****************************************************************/
5303
5304 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5305                                 struct spoolss_StartDocPrinter *r)
5306 {
5307         struct spoolss_DocumentInfo1 *info_1;
5308         int snum;
5309         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5310
5311         if (!Printer) {
5312                 DEBUG(2,("_spoolss_StartDocPrinter: "
5313                         "Invalid handle (%s:%u:%u)\n",
5314                         OUR_HANDLE(r->in.handle)));
5315                 return WERR_BADFID;
5316         }
5317
5318         if (r->in.level != 1) {
5319                 return WERR_UNKNOWN_LEVEL;
5320         }
5321
5322         info_1 = r->in.info.info1;
5323
5324         /*
5325          * a nice thing with NT is it doesn't listen to what you tell it.
5326          * when asked to send _only_ RAW datas, it tries to send datas
5327          * in EMF format.
5328          *
5329          * So I add checks like in NT Server ...
5330          */
5331
5332         if (info_1->datatype) {
5333                 if (strcmp(info_1->datatype, "RAW") != 0) {
5334                         *r->out.job_id = 0;
5335                         return WERR_INVALID_DATATYPE;
5336                 }
5337         }
5338
5339         /* get the share number of the printer */
5340         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5341                 return WERR_BADFID;
5342         }
5343
5344         Printer->jobid = print_job_start(p->server_info, snum,
5345                                          info_1->document_name,
5346                                          Printer->nt_devmode);
5347
5348         /* An error occured in print_job_start() so return an appropriate
5349            NT error code. */
5350
5351         if (Printer->jobid == -1) {
5352                 return map_werror_from_unix(errno);
5353         }
5354
5355         Printer->document_started = true;
5356         *r->out.job_id = Printer->jobid;
5357
5358         return WERR_OK;
5359 }
5360
5361 /****************************************************************
5362  _spoolss_EndDocPrinter
5363 ****************************************************************/
5364
5365 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5366                               struct spoolss_EndDocPrinter *r)
5367 {
5368         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5369         int snum;
5370
5371         if (!Printer) {
5372                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5373                         OUR_HANDLE(r->in.handle)));
5374                 return WERR_BADFID;
5375         }
5376
5377         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5378                 return WERR_BADFID;
5379         }
5380
5381         Printer->document_started = false;
5382         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5383         /* error codes unhandled so far ... */
5384
5385         return WERR_OK;
5386 }
5387
5388 /****************************************************************
5389  _spoolss_WritePrinter
5390 ****************************************************************/
5391
5392 WERROR _spoolss_WritePrinter(pipes_struct *p,
5393                              struct spoolss_WritePrinter *r)
5394 {
5395         uint32_t buffer_written;
5396         int snum;
5397         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5398
5399         if (!Printer) {
5400                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5401                         OUR_HANDLE(r->in.handle)));
5402                 *r->out.num_written = r->in._data_size;
5403                 return WERR_BADFID;
5404         }
5405
5406         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5407                 return WERR_BADFID;
5408
5409         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5410                                                    (const char *)r->in.data.data,
5411                                                    (SMB_OFF_T)-1,
5412                                                    (size_t)r->in._data_size);
5413         if (buffer_written == (uint32_t)-1) {
5414                 *r->out.num_written = 0;
5415                 if (errno == ENOSPC)
5416                         return WERR_NO_SPOOL_SPACE;
5417                 else
5418                         return WERR_ACCESS_DENIED;
5419         }
5420
5421         *r->out.num_written = r->in._data_size;
5422
5423         return WERR_OK;
5424 }
5425
5426 /********************************************************************
5427  * api_spoolss_getprinter
5428  * called from the spoolss dispatcher
5429  *
5430  ********************************************************************/
5431
5432 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5433                               pipes_struct *p)
5434 {
5435         int snum;
5436         WERROR errcode = WERR_BADFUNC;
5437         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5438
5439         if (!Printer) {
5440                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5441                         OUR_HANDLE(handle)));
5442                 return WERR_BADFID;
5443         }
5444
5445         if (!get_printer_snum(p, handle, &snum, NULL))
5446                 return WERR_BADFID;
5447
5448         switch (command) {
5449         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5450                 errcode = print_queue_pause(p->server_info, snum);
5451                 break;
5452         case SPOOLSS_PRINTER_CONTROL_RESUME:
5453         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5454                 errcode = print_queue_resume(p->server_info, snum);
5455                 break;
5456         case SPOOLSS_PRINTER_CONTROL_PURGE:
5457                 errcode = print_queue_purge(p->server_info, snum);
5458                 break;
5459         default:
5460                 return WERR_UNKNOWN_LEVEL;
5461         }
5462
5463         return errcode;
5464 }
5465
5466
5467 /****************************************************************
5468  _spoolss_AbortPrinter
5469  * From MSDN: "Deletes printer's spool file if printer is configured
5470  * for spooling"
5471 ****************************************************************/
5472
5473 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5474                              struct spoolss_AbortPrinter *r)
5475 {
5476         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5477         int             snum;
5478         WERROR          errcode = WERR_OK;
5479
5480         if (!Printer) {
5481                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5482                         OUR_HANDLE(r->in.handle)));
5483                 return WERR_BADFID;
5484         }
5485
5486         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5487                 return WERR_BADFID;
5488
5489         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5490
5491         return errcode;
5492 }
5493
5494 /********************************************************************
5495  * called by spoolss_api_setprinter
5496  * when updating a printer description
5497  ********************************************************************/
5498
5499 static WERROR update_printer_sec(struct policy_handle *handle,
5500                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5501 {
5502         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5503         WERROR result;
5504         int snum;
5505
5506         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5507
5508         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5509                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5510                          OUR_HANDLE(handle)));
5511
5512                 result = WERR_BADFID;
5513                 goto done;
5514         }
5515
5516         if (!secdesc_ctr) {
5517                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5518                 result = WERR_INVALID_PARAM;
5519                 goto done;
5520         }
5521
5522         /* Check the user has permissions to change the security
5523            descriptor.  By experimentation with two NT machines, the user
5524            requires Full Access to the printer to change security
5525            information. */
5526
5527         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5528                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5529                 result = WERR_ACCESS_DENIED;
5530                 goto done;
5531         }
5532
5533         /* NT seems to like setting the security descriptor even though
5534            nothing may have actually changed. */
5535
5536         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5537                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5538                 result = WERR_BADFID;
5539                 goto done;
5540         }
5541
5542         if (DEBUGLEVEL >= 10) {
5543                 SEC_ACL *the_acl;
5544                 int i;
5545
5546                 the_acl = old_secdesc_ctr->sd->dacl;
5547                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5548                            PRINTERNAME(snum), the_acl->num_aces));
5549
5550                 for (i = 0; i < the_acl->num_aces; i++) {
5551                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5552                                            &the_acl->aces[i].trustee),
5553                                   the_acl->aces[i].access_mask));
5554                 }
5555
5556                 the_acl = secdesc_ctr->sd->dacl;
5557
5558                 if (the_acl) {
5559                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5560                                    PRINTERNAME(snum), the_acl->num_aces));
5561
5562                         for (i = 0; i < the_acl->num_aces; i++) {
5563                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5564                                                    &the_acl->aces[i].trustee),
5565                                            the_acl->aces[i].access_mask));
5566                         }
5567                 } else {
5568                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5569                 }
5570         }
5571
5572         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5573         if (!new_secdesc_ctr) {
5574                 result = WERR_NOMEM;
5575                 goto done;
5576         }
5577
5578         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5579                 result = WERR_OK;
5580                 goto done;
5581         }
5582
5583         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5584
5585  done:
5586
5587         return result;
5588 }
5589
5590 /********************************************************************
5591  Canonicalize printer info from a client
5592
5593  ATTN: It does not matter what we set the servername to hear
5594  since we do the necessary work in get_a_printer() to set it to
5595  the correct value based on what the client sent in the
5596  _spoolss_open_printer_ex().
5597  ********************************************************************/
5598
5599 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5600 {
5601         fstring printername;
5602         const char *p;
5603
5604         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5605                 "portname=%s drivername=%s comment=%s location=%s\n",
5606                 info->servername, info->printername, info->sharename,
5607                 info->portname, info->drivername, info->comment, info->location));
5608
5609         /* we force some elements to "correct" values */
5610         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5611         fstrcpy(info->sharename, lp_servicename(snum));
5612
5613         /* check to see if we allow printername != sharename */
5614
5615         if ( lp_force_printername(snum) ) {
5616                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5617                         global_myname(), info->sharename );
5618         } else {
5619
5620                 /* make sure printername is in \\server\printername format */
5621
5622                 fstrcpy( printername, info->printername );
5623                 p = printername;
5624                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5625                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5626                                 p++;
5627                 }
5628
5629                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5630                          global_myname(), p );
5631         }
5632
5633         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5634         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5635
5636
5637
5638         return true;
5639 }
5640
5641 /****************************************************************************
5642 ****************************************************************************/
5643
5644 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5645 {
5646         char *cmd = lp_addport_cmd();
5647         char *command = NULL;
5648         int ret;
5649         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5650         bool is_print_op = false;
5651
5652         if ( !*cmd ) {
5653                 return WERR_ACCESS_DENIED;
5654         }
5655
5656         command = talloc_asprintf(ctx,
5657                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5658         if (!command) {
5659                 return WERR_NOMEM;
5660         }
5661
5662         if ( token )
5663                 is_print_op = user_has_privileges( token, &se_printop );
5664
5665         DEBUG(10,("Running [%s]\n", command));
5666
5667         /********* BEGIN SePrintOperatorPrivilege **********/
5668
5669         if ( is_print_op )
5670                 become_root();
5671
5672         ret = smbrun(command, NULL);
5673
5674         if ( is_print_op )
5675                 unbecome_root();
5676
5677         /********* END SePrintOperatorPrivilege **********/
5678
5679         DEBUGADD(10,("returned [%d]\n", ret));
5680
5681         TALLOC_FREE(command);
5682
5683         if ( ret != 0 ) {
5684                 return WERR_ACCESS_DENIED;
5685         }
5686
5687         return WERR_OK;
5688 }
5689
5690 /****************************************************************************
5691 ****************************************************************************/
5692
5693 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5694 {
5695         char *cmd = lp_addprinter_cmd();
5696         char **qlines;
5697         char *command = NULL;
5698         int numlines;
5699         int ret;
5700         int fd;
5701         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5702         bool is_print_op = false;
5703         char *remote_machine = talloc_strdup(ctx, "%m");
5704
5705         if (!remote_machine) {
5706                 return false;
5707         }
5708         remote_machine = talloc_sub_basic(ctx,
5709                                 current_user_info.smb_name,
5710                                 current_user_info.domain,
5711                                 remote_machine);
5712         if (!remote_machine) {
5713                 return false;
5714         }
5715
5716         command = talloc_asprintf(ctx,
5717                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5718                         cmd, printer->info_2->printername, printer->info_2->sharename,
5719                         printer->info_2->portname, printer->info_2->drivername,
5720                         printer->info_2->location, printer->info_2->comment, remote_machine);
5721         if (!command) {
5722                 return false;
5723         }
5724
5725         if ( token )
5726                 is_print_op = user_has_privileges( token, &se_printop );
5727
5728         DEBUG(10,("Running [%s]\n", command));
5729
5730         /********* BEGIN SePrintOperatorPrivilege **********/
5731
5732         if ( is_print_op )
5733                 become_root();
5734
5735         if ( (ret = smbrun(command, &fd)) == 0 ) {
5736                 /* Tell everyone we updated smb.conf. */
5737                 message_send_all(smbd_messaging_context(),
5738                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5739         }
5740
5741         if ( is_print_op )
5742                 unbecome_root();
5743
5744         /********* END SePrintOperatorPrivilege **********/
5745
5746         DEBUGADD(10,("returned [%d]\n", ret));
5747
5748         TALLOC_FREE(command);
5749         TALLOC_FREE(remote_machine);
5750
5751         if ( ret != 0 ) {
5752                 if (fd != -1)
5753                         close(fd);
5754                 return false;
5755         }
5756
5757         /* reload our services immediately */
5758         become_root();
5759         reload_services(false);
5760         unbecome_root();
5761
5762         numlines = 0;
5763         /* Get lines and convert them back to dos-codepage */
5764         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5765         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5766         close(fd);
5767
5768         /* Set the portname to what the script says the portname should be. */
5769         /* but don't require anything to be return from the script exit a good error code */
5770
5771         if (numlines) {
5772                 /* Set the portname to what the script says the portname should be. */
5773                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5774                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5775         }
5776
5777         TALLOC_FREE(qlines);
5778         return true;
5779 }
5780
5781
5782 /********************************************************************
5783  * Called by spoolss_api_setprinter
5784  * when updating a printer description.
5785  ********************************************************************/
5786
5787 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5788                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5789                              struct spoolss_DeviceMode *devmode)
5790 {
5791         int snum;
5792         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5793         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5794         WERROR result;
5795         DATA_BLOB buffer;
5796         fstring asc_buffer;
5797
5798         DEBUG(8,("update_printer\n"));
5799
5800         result = WERR_OK;
5801
5802         if (!Printer) {
5803                 result = WERR_BADFID;
5804                 goto done;
5805         }
5806
5807         if (!get_printer_snum(p, handle, &snum, NULL)) {
5808                 result = WERR_BADFID;
5809                 goto done;
5810         }
5811
5812         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5813             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5814                 result = WERR_BADFID;
5815                 goto done;
5816         }
5817
5818         DEBUGADD(8,("Converting info_2 struct\n"));
5819
5820         /*
5821          * convert_printer_info converts the incoming
5822          * info from the client and overwrites the info
5823          * just read from the tdb in the pointer 'printer'.
5824          */
5825
5826         if (!convert_printer_info(info_ctr, printer)) {
5827                 result =  WERR_NOMEM;
5828                 goto done;
5829         }
5830
5831         if (devmode) {
5832                 /* we have a valid devmode
5833                    convert it and link it*/
5834
5835                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5836                 if (!convert_devicemode(printer->info_2->printername, devmode,
5837                                         &printer->info_2->devmode)) {
5838                         result =  WERR_NOMEM;
5839                         goto done;
5840                 }
5841         }
5842
5843         /* Do sanity check on the requested changes for Samba */
5844
5845         if (!check_printer_ok(printer->info_2, snum)) {
5846                 result = WERR_INVALID_PARAM;
5847                 goto done;
5848         }
5849
5850         /* FIXME!!! If the driver has changed we really should verify that
5851            it is installed before doing much else   --jerry */
5852
5853         /* Check calling user has permission to update printer description */
5854
5855         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5856                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5857                 result = WERR_ACCESS_DENIED;
5858                 goto done;
5859         }
5860
5861         /* Call addprinter hook */
5862         /* Check changes to see if this is really needed */
5863
5864         if ( *lp_addprinter_cmd()
5865                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5866                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5867                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5868                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5869         {
5870                 /* add_printer_hook() will call reload_services() */
5871
5872                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5873                                        printer) ) {
5874                         result = WERR_ACCESS_DENIED;
5875                         goto done;
5876                 }
5877         }
5878
5879         /*
5880          * When a *new* driver is bound to a printer, the drivername is used to
5881          * lookup previously saved driver initialization info, which is then
5882          * bound to the printer, simulating what happens in the Windows arch.
5883          */
5884         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5885         {
5886                 if (!set_driver_init(printer, 2))
5887                 {
5888                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5889                                 printer->info_2->drivername));
5890                 }
5891
5892                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5893                         printer->info_2->drivername));
5894
5895                 notify_printer_driver(snum, printer->info_2->drivername);
5896         }
5897
5898         /*
5899          * flag which changes actually occured.  This is a small subset of
5900          * all the possible changes.  We also have to update things in the
5901          * DsSpooler key.
5902          */
5903
5904         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5905                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5906                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5907                         REG_SZ, buffer.data, buffer.length);
5908
5909                 notify_printer_comment(snum, printer->info_2->comment);
5910         }
5911
5912         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5913                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5914                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5915                         REG_SZ, buffer.data, buffer.length);
5916
5917                 notify_printer_sharename(snum, printer->info_2->sharename);
5918         }
5919
5920         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5921                 char *pname;
5922
5923                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5924                         pname++;
5925                 else
5926                         pname = printer->info_2->printername;
5927
5928
5929                 push_reg_sz(talloc_tos(), &buffer, pname);
5930                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5931                         REG_SZ, buffer.data, buffer.length);
5932
5933                 notify_printer_printername( snum, pname );
5934         }
5935
5936         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5937                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5938                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5939                         REG_SZ, buffer.data, buffer.length);
5940
5941                 notify_printer_port(snum, printer->info_2->portname);
5942         }
5943
5944         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5945                 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5946                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5947                         REG_SZ, buffer.data, buffer.length);
5948
5949                 notify_printer_location(snum, printer->info_2->location);
5950         }
5951
5952         /* here we need to update some more DsSpooler keys */
5953         /* uNCName, serverName, shortServerName */
5954
5955         push_reg_sz(talloc_tos(), &buffer, global_myname());
5956         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5957                 REG_SZ, buffer.data, buffer.length);
5958         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5959                 REG_SZ, buffer.data, buffer.length);
5960
5961         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5962                  global_myname(), printer->info_2->sharename );
5963         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5964         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5965                 REG_SZ, buffer.data, buffer.length);
5966
5967         /* Update printer info */
5968         result = mod_a_printer(printer, 2);
5969
5970 done:
5971         free_a_printer(&printer, 2);
5972         free_a_printer(&old_printer, 2);
5973
5974
5975         return result;
5976 }
5977
5978 /****************************************************************************
5979 ****************************************************************************/
5980 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5981                                            struct policy_handle *handle,
5982                                            struct spoolss_SetPrinterInfo7 *info7)
5983 {
5984 #ifdef HAVE_ADS
5985         int snum;
5986         Printer_entry *Printer;
5987
5988         if ( lp_security() != SEC_ADS ) {
5989                 return WERR_UNKNOWN_LEVEL;
5990         }
5991
5992         Printer = find_printer_index_by_hnd(p, handle);
5993
5994         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5995
5996         if (!Printer)
5997                 return WERR_BADFID;
5998
5999         if (!get_printer_snum(p, handle, &snum, NULL))
6000                 return WERR_BADFID;
6001
6002         nt_printer_publish(Printer, snum, info7->action);
6003
6004         return WERR_OK;
6005 #else
6006         return WERR_UNKNOWN_LEVEL;
6007 #endif
6008 }
6009
6010 /****************************************************************
6011  _spoolss_SetPrinter
6012 ****************************************************************/
6013
6014 WERROR _spoolss_SetPrinter(pipes_struct *p,
6015                            struct spoolss_SetPrinter *r)
6016 {
6017         WERROR result;
6018
6019         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6020
6021         if (!Printer) {
6022                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6023                         OUR_HANDLE(r->in.handle)));
6024                 return WERR_BADFID;
6025         }
6026
6027         /* check the level */
6028         switch (r->in.info_ctr->level) {
6029                 case 0:
6030                         return control_printer(r->in.handle, r->in.command, p);
6031                 case 2:
6032                         result = update_printer(p, r->in.handle,
6033                                                 r->in.info_ctr,
6034                                                 r->in.devmode_ctr->devmode);
6035                         if (!W_ERROR_IS_OK(result))
6036                                 return result;
6037                         if (r->in.secdesc_ctr->sd)
6038                                 result = update_printer_sec(r->in.handle, p,
6039                                                             r->in.secdesc_ctr);
6040                         return result;
6041                 case 3:
6042                         return update_printer_sec(r->in.handle, p,
6043                                                   r->in.secdesc_ctr);
6044                 case 7:
6045                         return publish_or_unpublish_printer(p, r->in.handle,
6046                                                             r->in.info_ctr->info.info7);
6047                 default:
6048                         return WERR_UNKNOWN_LEVEL;
6049         }
6050 }
6051
6052 /****************************************************************
6053  _spoolss_FindClosePrinterNotify
6054 ****************************************************************/
6055
6056 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6057                                        struct spoolss_FindClosePrinterNotify *r)
6058 {
6059         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6060
6061         if (!Printer) {
6062                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6063                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6064                 return WERR_BADFID;
6065         }
6066
6067         if (Printer->notify.client_connected == true) {
6068                 int snum = -1;
6069
6070                 if ( Printer->printer_type == SPLHND_SERVER)
6071                         snum = -1;
6072                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6073                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6074                         return WERR_BADFID;
6075
6076                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6077         }
6078
6079         Printer->notify.flags=0;
6080         Printer->notify.options=0;
6081         Printer->notify.localmachine[0]='\0';
6082         Printer->notify.printerlocal=0;
6083         TALLOC_FREE(Printer->notify.option);
6084         Printer->notify.client_connected = false;
6085
6086         return WERR_OK;
6087 }
6088
6089 /****************************************************************
6090  _spoolss_AddJob
6091 ****************************************************************/
6092
6093 WERROR _spoolss_AddJob(pipes_struct *p,
6094                        struct spoolss_AddJob *r)
6095 {
6096         if (!r->in.buffer && (r->in.offered != 0)) {
6097                 return WERR_INVALID_PARAM;
6098         }
6099
6100         /* this is what a NT server returns for AddJob. AddJob must fail on
6101          * non-local printers */
6102
6103         if (r->in.level != 1) {
6104                 return WERR_UNKNOWN_LEVEL;
6105         }
6106
6107         return WERR_INVALID_PARAM;
6108 }
6109
6110 /****************************************************************************
6111 fill_job_info1
6112 ****************************************************************************/
6113
6114 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6115                              struct spoolss_JobInfo1 *r,
6116                              const print_queue_struct *queue,
6117                              int position, int snum,
6118                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6119 {
6120         struct tm *t;
6121
6122         t = gmtime(&queue->time);
6123
6124         r->job_id               = queue->job;
6125
6126         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6127         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6128         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6129         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6130         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6131         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6132         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6133         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6134         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6135         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6136         r->text_status          = talloc_strdup(mem_ctx, "");
6137         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6138
6139         r->status               = nt_printj_status(queue->status);
6140         r->priority             = queue->priority;
6141         r->position             = position;
6142         r->total_pages          = queue->page_count;
6143         r->pages_printed        = 0; /* ??? */
6144
6145         init_systemtime(&r->submitted, t);
6146
6147         return WERR_OK;
6148 }
6149
6150 /****************************************************************************
6151 fill_job_info2
6152 ****************************************************************************/
6153
6154 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6155                              struct spoolss_JobInfo2 *r,
6156                              const print_queue_struct *queue,
6157                              int position, int snum,
6158                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6159                              struct spoolss_DeviceMode *devmode)
6160 {
6161         struct tm *t;
6162
6163         t = gmtime(&queue->time);
6164
6165         r->job_id               = queue->job;
6166
6167         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6168         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6169         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6170         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6171         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6172         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6173         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6174         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6175         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6176         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6177         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6178         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6179         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6180         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6181         r->parameters           = talloc_strdup(mem_ctx, "");
6182         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6183         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6184         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6185
6186         r->devmode              = devmode;
6187
6188         r->text_status          = talloc_strdup(mem_ctx, "");
6189         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6190
6191         r->secdesc              = NULL;
6192
6193         r->status               = nt_printj_status(queue->status);
6194         r->priority             = queue->priority;
6195         r->position             = position;
6196         r->start_time           = 0;
6197         r->until_time           = 0;
6198         r->total_pages          = queue->page_count;
6199         r->size                 = queue->size;
6200         init_systemtime(&r->submitted, t);
6201         r->time                 = 0;
6202         r->pages_printed        = 0; /* ??? */
6203
6204         return WERR_OK;
6205 }
6206
6207 /****************************************************************************
6208  Enumjobs at level 1.
6209 ****************************************************************************/
6210
6211 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6212                               const print_queue_struct *queue,
6213                               uint32_t num_queues, int snum,
6214                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6215                               union spoolss_JobInfo **info_p,
6216                               uint32_t *count)
6217 {
6218         union spoolss_JobInfo *info;
6219         int i;
6220         WERROR result = WERR_OK;
6221
6222         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6223         W_ERROR_HAVE_NO_MEMORY(info);
6224
6225         *count = num_queues;
6226
6227         for (i=0; i<*count; i++) {
6228                 result = fill_job_info1(info,
6229                                         &info[i].info1,
6230                                         &queue[i],
6231                                         i,
6232                                         snum,
6233                                         ntprinter);
6234                 if (!W_ERROR_IS_OK(result)) {
6235                         goto out;
6236                 }
6237         }
6238
6239  out:
6240         if (!W_ERROR_IS_OK(result)) {
6241                 TALLOC_FREE(info);
6242                 *count = 0;
6243                 return result;
6244         }
6245
6246         *info_p = info;
6247
6248         return WERR_OK;
6249 }
6250
6251 /****************************************************************************
6252  Enumjobs at level 2.
6253 ****************************************************************************/
6254
6255 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6256                               const print_queue_struct *queue,
6257                               uint32_t num_queues, int snum,
6258                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6259                               union spoolss_JobInfo **info_p,
6260                               uint32_t *count)
6261 {
6262         union spoolss_JobInfo *info;
6263         int i;
6264         WERROR result = WERR_OK;
6265
6266         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6267         W_ERROR_HAVE_NO_MEMORY(info);
6268
6269         *count = num_queues;
6270
6271         for (i=0; i<*count; i++) {
6272
6273                 struct spoolss_DeviceMode *devmode;
6274
6275                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6276                 if (!devmode) {
6277                         result = WERR_NOMEM;
6278                         goto out;
6279                 }
6280
6281                 result = fill_job_info2(info,
6282                                         &info[i].info2,
6283                                         &queue[i],
6284                                         i,
6285                                         snum,
6286                                         ntprinter,
6287                                         devmode);
6288                 if (!W_ERROR_IS_OK(result)) {
6289                         goto out;
6290                 }
6291         }
6292
6293  out:
6294         if (!W_ERROR_IS_OK(result)) {
6295                 TALLOC_FREE(info);
6296                 *count = 0;
6297                 return result;
6298         }
6299
6300         *info_p = info;
6301
6302         return WERR_OK;
6303 }
6304
6305 /****************************************************************
6306  _spoolss_EnumJobs
6307 ****************************************************************/
6308
6309 WERROR _spoolss_EnumJobs(pipes_struct *p,
6310                          struct spoolss_EnumJobs *r)
6311 {
6312         WERROR result;
6313         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6314         int snum;
6315         print_status_struct prt_status;
6316         print_queue_struct *queue = NULL;
6317         uint32_t count;
6318
6319         /* that's an [in out] buffer */
6320
6321         if (!r->in.buffer && (r->in.offered != 0)) {
6322                 return WERR_INVALID_PARAM;
6323         }
6324
6325         DEBUG(4,("_spoolss_EnumJobs\n"));
6326
6327         *r->out.needed = 0;
6328         *r->out.count = 0;
6329         *r->out.info = NULL;
6330
6331         /* lookup the printer snum and tdb entry */
6332
6333         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6334                 return WERR_BADFID;
6335         }
6336
6337         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6338         if (!W_ERROR_IS_OK(result)) {
6339                 return result;
6340         }
6341
6342         count = print_queue_status(snum, &queue, &prt_status);
6343         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6344                 count, prt_status.status, prt_status.message));
6345
6346         if (count == 0) {
6347                 SAFE_FREE(queue);
6348                 free_a_printer(&ntprinter, 2);
6349                 return WERR_OK;
6350         }
6351
6352         switch (r->in.level) {
6353         case 1:
6354                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6355                                          ntprinter, r->out.info, r->out.count);
6356                 break;
6357         case 2:
6358                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6359                                          ntprinter, r->out.info, r->out.count);
6360                 break;
6361         default:
6362                 result = WERR_UNKNOWN_LEVEL;
6363                 break;
6364         }
6365
6366         SAFE_FREE(queue);
6367         free_a_printer(&ntprinter, 2);
6368
6369         if (!W_ERROR_IS_OK(result)) {
6370                 return result;
6371         }
6372
6373         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6374                                                      spoolss_EnumJobs, NULL,
6375                                                      *r->out.info, r->in.level,
6376                                                      *r->out.count);
6377         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6378         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6379
6380         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6381 }
6382
6383 /****************************************************************
6384  _spoolss_ScheduleJob
6385 ****************************************************************/
6386
6387 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6388                             struct spoolss_ScheduleJob *r)
6389 {
6390         return WERR_OK;
6391 }
6392
6393 /****************************************************************
6394  _spoolss_SetJob
6395 ****************************************************************/
6396
6397 WERROR _spoolss_SetJob(pipes_struct *p,
6398                        struct spoolss_SetJob *r)
6399 {
6400         int snum;
6401         WERROR errcode = WERR_BADFUNC;
6402
6403         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6404                 return WERR_BADFID;
6405         }
6406
6407         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6408                 return WERR_INVALID_PRINTER_NAME;
6409         }
6410
6411         switch (r->in.command) {
6412         case SPOOLSS_JOB_CONTROL_CANCEL:
6413         case SPOOLSS_JOB_CONTROL_DELETE:
6414                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6415                         errcode = WERR_OK;
6416                 }
6417                 break;
6418         case SPOOLSS_JOB_CONTROL_PAUSE:
6419                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6420                         errcode = WERR_OK;
6421                 }
6422                 break;
6423         case SPOOLSS_JOB_CONTROL_RESTART:
6424         case SPOOLSS_JOB_CONTROL_RESUME:
6425                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6426                         errcode = WERR_OK;
6427                 }
6428                 break;
6429         default:
6430                 return WERR_UNKNOWN_LEVEL;
6431         }
6432
6433         return errcode;
6434 }
6435
6436 /****************************************************************************
6437  Enumerates all printer drivers by level and architecture.
6438 ****************************************************************************/
6439
6440 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6441                                                        const char *servername,
6442                                                        const char *architecture,
6443                                                        uint32_t level,
6444                                                        union spoolss_DriverInfo **info_p,
6445                                                        uint32_t *count_p)
6446 {
6447         int i;
6448         int ndrivers;
6449         uint32_t version;
6450         fstring *list = NULL;
6451         union spoolss_DriverInfo *driver;
6452         union spoolss_DriverInfo *info = NULL;
6453         uint32_t count = 0;
6454         WERROR result = WERR_OK;
6455
6456         *count_p = 0;
6457         *info_p = NULL;
6458
6459         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6460                 list = NULL;
6461                 ndrivers = get_ntdrivers(&list, architecture, version);
6462                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6463                         ndrivers, architecture, version));
6464
6465                 if (ndrivers == -1) {
6466                         result = WERR_NOMEM;
6467                         goto out;
6468                 }
6469
6470                 if (ndrivers != 0) {
6471                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6472                                                     union spoolss_DriverInfo,
6473                                                     count + ndrivers);
6474                         if (!info) {
6475                                 DEBUG(0,("enumprinterdrivers_level1: "
6476                                         "failed to enlarge driver info buffer!\n"));
6477                                 result = WERR_NOMEM;
6478                                 goto out;
6479                         }
6480                 }
6481
6482                 for (i=0; i<ndrivers; i++) {
6483                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6484                         ZERO_STRUCT(driver);
6485                         result = get_a_printer_driver(mem_ctx, &driver, 3, list[i],
6486                                                       architecture, version);
6487                         if (!W_ERROR_IS_OK(result)) {
6488                                 goto out;
6489                         }
6490
6491                         switch (level) {
6492                         case 1:
6493                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6494                                                                    &driver->info3, servername,
6495                                                                    architecture);
6496                                 break;
6497                         case 2:
6498                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6499                                                                    &driver->info3, servername);
6500                                 break;
6501                         case 3:
6502                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6503                                                                    &driver->info3, servername);
6504                                 break;
6505                         case 4:
6506                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6507                                                                    &driver->info3, servername);
6508                                 break;
6509                         case 5:
6510                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6511                                                                    &driver->info3, servername);
6512                                 break;
6513                         case 6:
6514                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6515                                                                    &driver->info3, servername);
6516                                 break;
6517                         default:
6518                                 result = WERR_UNKNOWN_LEVEL;
6519                                 break;
6520                         }
6521
6522                         free_a_printer_driver(driver);
6523
6524                         if (!W_ERROR_IS_OK(result)) {
6525                                 goto out;
6526                         }
6527                 }
6528
6529                 count += ndrivers;
6530                 SAFE_FREE(list);
6531         }
6532
6533  out:
6534         SAFE_FREE(list);
6535
6536         if (!W_ERROR_IS_OK(result)) {
6537                 TALLOC_FREE(info);
6538                 return result;
6539         }
6540
6541         *info_p = info;
6542         *count_p = count;
6543
6544         return WERR_OK;
6545 }
6546
6547 /****************************************************************************
6548  Enumerates all printer drivers by level.
6549 ****************************************************************************/
6550
6551 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6552                                        const char *servername,
6553                                        const char *architecture,
6554                                        uint32_t level,
6555                                        union spoolss_DriverInfo **info_p,
6556                                        uint32_t *count_p)
6557 {
6558         uint32_t a,i;
6559         WERROR result = WERR_OK;
6560
6561         if (strequal(architecture, "all")) {
6562
6563                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6564
6565                         union spoolss_DriverInfo *info = NULL;
6566                         uint32_t count = 0;
6567
6568                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6569                                                                           servername,
6570                                                                           archi_table[a].long_archi,
6571                                                                           level,
6572                                                                           &info,
6573                                                                           &count);
6574                         if (!W_ERROR_IS_OK(result)) {
6575                                 continue;
6576                         }
6577
6578                         for (i=0; i < count; i++) {
6579                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6580                                              info[i], info_p, count_p);
6581                         }
6582                 }
6583
6584                 return result;
6585         }
6586
6587         return enumprinterdrivers_level_by_architecture(mem_ctx,
6588                                                         servername,
6589                                                         architecture,
6590                                                         level,
6591                                                         info_p,
6592                                                         count_p);
6593 }
6594
6595 /****************************************************************************
6596  Enumerates all printer drivers at level 1.
6597 ****************************************************************************/
6598
6599 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6600                                         const char *servername,
6601                                         const char *architecture,
6602                                         union spoolss_DriverInfo **info_p,
6603                                         uint32_t *count)
6604 {
6605         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6606                                         info_p, count);
6607 }
6608
6609 /****************************************************************************
6610  Enumerates all printer drivers at level 2.
6611 ****************************************************************************/
6612
6613 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6614                                         const char *servername,
6615                                         const char *architecture,
6616                                         union spoolss_DriverInfo **info_p,
6617                                         uint32_t *count)
6618 {
6619         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6620                                         info_p, count);
6621 }
6622
6623 /****************************************************************************
6624  Enumerates all printer drivers at level 3.
6625 ****************************************************************************/
6626
6627 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6628                                         const char *servername,
6629                                         const char *architecture,
6630                                         union spoolss_DriverInfo **info_p,
6631                                         uint32_t *count)
6632 {
6633         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6634                                         info_p, count);
6635 }
6636
6637 /****************************************************************************
6638  Enumerates all printer drivers at level 4.
6639 ****************************************************************************/
6640
6641 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6642                                         const char *servername,
6643                                         const char *architecture,
6644                                         union spoolss_DriverInfo **info_p,
6645                                         uint32_t *count)
6646 {
6647         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6648                                         info_p, count);
6649 }
6650
6651 /****************************************************************************
6652  Enumerates all printer drivers at level 5.
6653 ****************************************************************************/
6654
6655 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6656                                         const char *servername,
6657                                         const char *architecture,
6658                                         union spoolss_DriverInfo **info_p,
6659                                         uint32_t *count)
6660 {
6661         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6662                                         info_p, count);
6663 }
6664
6665 /****************************************************************************
6666  Enumerates all printer drivers at level 6.
6667 ****************************************************************************/
6668
6669 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6670                                         const char *servername,
6671                                         const char *architecture,
6672                                         union spoolss_DriverInfo **info_p,
6673                                         uint32_t *count)
6674 {
6675         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6676                                         info_p, count);
6677 }
6678
6679
6680 /****************************************************************
6681  _spoolss_EnumPrinterDrivers
6682 ****************************************************************/
6683
6684 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6685                                    struct spoolss_EnumPrinterDrivers *r)
6686 {
6687         const char *cservername;
6688         WERROR result;
6689
6690         /* that's an [in out] buffer */
6691
6692         if (!r->in.buffer && (r->in.offered != 0)) {
6693                 return WERR_INVALID_PARAM;
6694         }
6695
6696         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6697
6698         *r->out.needed = 0;
6699         *r->out.count = 0;
6700         *r->out.info = NULL;
6701
6702         cservername = canon_servername(r->in.server);
6703
6704         if (!is_myname_or_ipaddr(cservername)) {
6705                 return WERR_UNKNOWN_PRINTER_DRIVER;
6706         }
6707
6708         switch (r->in.level) {
6709         case 1:
6710                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6711                                                    r->in.environment,
6712                                                    r->out.info, r->out.count);
6713                 break;
6714         case 2:
6715                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6716                                                    r->in.environment,
6717                                                    r->out.info, r->out.count);
6718                 break;
6719         case 3:
6720                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6721                                                    r->in.environment,
6722                                                    r->out.info, r->out.count);
6723                 break;
6724         case 4:
6725                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
6726                                                    r->in.environment,
6727                                                    r->out.info, r->out.count);
6728                 break;
6729         case 5:
6730                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
6731                                                    r->in.environment,
6732                                                    r->out.info, r->out.count);
6733                 break;
6734         case 6:
6735                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
6736                                                    r->in.environment,
6737                                                    r->out.info, r->out.count);
6738                 break;
6739         default:
6740                 return WERR_UNKNOWN_LEVEL;
6741         }
6742
6743         if (!W_ERROR_IS_OK(result)) {
6744                 return result;
6745         }
6746
6747         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6748                                                      spoolss_EnumPrinterDrivers, NULL,
6749                                                      *r->out.info, r->in.level,
6750                                                      *r->out.count);
6751         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6752         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6753
6754         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6755 }
6756
6757 /****************************************************************************
6758 ****************************************************************************/
6759
6760 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6761                                struct spoolss_FormInfo1 *r,
6762                                const nt_forms_struct *form)
6763 {
6764         r->form_name    = talloc_strdup(mem_ctx, form->name);
6765         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6766
6767         r->flags        = form->flag;
6768         r->size.width   = form->width;
6769         r->size.height  = form->length;
6770         r->area.left    = form->left;
6771         r->area.top     = form->top;
6772         r->area.right   = form->right;
6773         r->area.bottom  = form->bottom;
6774
6775         return WERR_OK;
6776 }
6777
6778 /****************************************************************
6779  spoolss_enumforms_level1
6780 ****************************************************************/
6781
6782 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6783                                        const nt_forms_struct *builtin_forms,
6784                                        uint32_t num_builtin_forms,
6785                                        const nt_forms_struct *user_forms,
6786                                        uint32_t num_user_forms,
6787                                        union spoolss_FormInfo **info_p,
6788                                        uint32_t *count)
6789 {
6790         union spoolss_FormInfo *info;
6791         WERROR result = WERR_OK;
6792         int i;
6793
6794         *count = num_builtin_forms + num_user_forms;
6795
6796         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6797         W_ERROR_HAVE_NO_MEMORY(info);
6798
6799         /* construct the list of form structures */
6800         for (i=0; i<num_builtin_forms; i++) {
6801                 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6802                 result = fill_form_info_1(info, &info[i].info1,
6803                                           &builtin_forms[i]);
6804                 if (!W_ERROR_IS_OK(result)) {
6805                         goto out;
6806                 }
6807         }
6808
6809         for (i=0; i<num_user_forms; i++) {
6810                 DEBUGADD(6,("Filling user form number [%d]\n",i));
6811                 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6812                                           &user_forms[i]);
6813                 if (!W_ERROR_IS_OK(result)) {
6814                         goto out;
6815                 }
6816         }
6817
6818  out:
6819         if (!W_ERROR_IS_OK(result)) {
6820                 TALLOC_FREE(info);
6821                 *count = 0;
6822                 return result;
6823         }
6824
6825         *info_p = info;
6826
6827         return WERR_OK;
6828 }
6829
6830 /****************************************************************
6831  _spoolss_EnumForms
6832 ****************************************************************/
6833
6834 WERROR _spoolss_EnumForms(pipes_struct *p,
6835                           struct spoolss_EnumForms *r)
6836 {
6837         WERROR result;
6838         nt_forms_struct *user_forms = NULL;
6839         nt_forms_struct *builtin_forms = NULL;
6840         uint32_t num_user_forms;
6841         uint32_t num_builtin_forms;
6842
6843         *r->out.count = 0;
6844         *r->out.needed = 0;
6845         *r->out.info = NULL;
6846
6847         /* that's an [in out] buffer */
6848
6849         if (!r->in.buffer && (r->in.offered != 0) ) {
6850                 return WERR_INVALID_PARAM;
6851         }
6852
6853         DEBUG(4,("_spoolss_EnumForms\n"));
6854         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6855         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6856
6857         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6858         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6859         num_user_forms = get_ntforms(&user_forms);
6860         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6861
6862         if (num_user_forms + num_builtin_forms == 0) {
6863                 SAFE_FREE(builtin_forms);
6864                 SAFE_FREE(user_forms);
6865                 return WERR_NO_MORE_ITEMS;
6866         }
6867
6868         switch (r->in.level) {
6869         case 1:
6870                 result = spoolss_enumforms_level1(p->mem_ctx,
6871                                                   builtin_forms,
6872                                                   num_builtin_forms,
6873                                                   user_forms,
6874                                                   num_user_forms,
6875                                                   r->out.info,
6876                                                   r->out.count);
6877                 break;
6878         default:
6879                 result = WERR_UNKNOWN_LEVEL;
6880                 break;
6881         }
6882
6883         SAFE_FREE(user_forms);
6884         SAFE_FREE(builtin_forms);
6885
6886         if (!W_ERROR_IS_OK(result)) {
6887                 return result;
6888         }
6889
6890         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6891                                                      spoolss_EnumForms, NULL,
6892                                                      *r->out.info, r->in.level,
6893                                                      *r->out.count);
6894         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6895         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6896
6897         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6898 }
6899
6900 /****************************************************************
6901 ****************************************************************/
6902
6903 static WERROR find_form_byname(const char *name,
6904                                nt_forms_struct *form)
6905 {
6906         nt_forms_struct *list = NULL;
6907         int num_forms = 0, i = 0;
6908
6909         if (get_a_builtin_ntform_by_string(name, form)) {
6910                 return WERR_OK;
6911         }
6912
6913         num_forms = get_ntforms(&list);
6914         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6915
6916         if (num_forms == 0) {
6917                 return WERR_BADFID;
6918         }
6919
6920         /* Check if the requested name is in the list of form structures */
6921         for (i = 0; i < num_forms; i++) {
6922
6923                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6924
6925                 if (strequal(name, list[i].name)) {
6926                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6927                         *form = list[i];
6928                         SAFE_FREE(list);
6929                         return WERR_OK;
6930                 }
6931         }
6932
6933         SAFE_FREE(list);
6934
6935         return WERR_BADFID;
6936 }
6937
6938 /****************************************************************
6939  _spoolss_GetForm
6940 ****************************************************************/
6941
6942 WERROR _spoolss_GetForm(pipes_struct *p,
6943                         struct spoolss_GetForm *r)
6944 {
6945         WERROR result;
6946         nt_forms_struct form;
6947
6948         /* that's an [in out] buffer */
6949
6950         if (!r->in.buffer && (r->in.offered != 0)) {
6951                 return WERR_INVALID_PARAM;
6952         }
6953
6954         DEBUG(4,("_spoolss_GetForm\n"));
6955         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6956         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6957
6958         result = find_form_byname(r->in.form_name, &form);
6959         if (!W_ERROR_IS_OK(result)) {
6960                 TALLOC_FREE(r->out.info);
6961                 return result;
6962         }
6963
6964         switch (r->in.level) {
6965         case 1:
6966                 result = fill_form_info_1(p->mem_ctx,
6967                                           &r->out.info->info1,
6968                                           &form);
6969                 break;
6970
6971         default:
6972                 result = WERR_UNKNOWN_LEVEL;
6973                 break;
6974         }
6975
6976         if (!W_ERROR_IS_OK(result)) {
6977                 TALLOC_FREE(r->out.info);
6978                 return result;
6979         }
6980
6981         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
6982                                                r->out.info, r->in.level);
6983         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6984
6985         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6986 }
6987
6988 /****************************************************************************
6989 ****************************************************************************/
6990
6991 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6992                           struct spoolss_PortInfo1 *r,
6993                           const char *name)
6994 {
6995         r->port_name = talloc_strdup(mem_ctx, name);
6996         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6997
6998         return WERR_OK;
6999 }
7000
7001 /****************************************************************************
7002  TODO: This probably needs distinguish between TCP/IP and Local ports
7003  somehow.
7004 ****************************************************************************/
7005
7006 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7007                           struct spoolss_PortInfo2 *r,
7008                           const char *name)
7009 {
7010         r->port_name = talloc_strdup(mem_ctx, name);
7011         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7012
7013         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7014         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7015
7016         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7017         W_ERROR_HAVE_NO_MEMORY(r->description);
7018
7019         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7020         r->reserved = 0;
7021
7022         return WERR_OK;
7023 }
7024
7025
7026 /****************************************************************************
7027  wrapper around the enumer ports command
7028 ****************************************************************************/
7029
7030 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7031 {
7032         char *cmd = lp_enumports_cmd();
7033         char **qlines = NULL;
7034         char *command = NULL;
7035         int numlines;
7036         int ret;
7037         int fd;
7038
7039         *count = 0;
7040         *lines = NULL;
7041
7042         /* if no hook then just fill in the default port */
7043
7044         if ( !*cmd ) {
7045                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7046                         return WERR_NOMEM;
7047                 }
7048                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7049                         TALLOC_FREE(qlines);
7050                         return WERR_NOMEM;
7051                 }
7052                 qlines[1] = NULL;
7053                 numlines = 1;
7054         }
7055         else {
7056                 /* we have a valid enumport command */
7057
7058                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7059                 if (!command) {
7060                         return WERR_NOMEM;
7061                 }
7062
7063                 DEBUG(10,("Running [%s]\n", command));
7064                 ret = smbrun(command, &fd);
7065                 DEBUG(10,("Returned [%d]\n", ret));
7066                 TALLOC_FREE(command);
7067                 if (ret != 0) {
7068                         if (fd != -1) {
7069                                 close(fd);
7070                         }
7071                         return WERR_ACCESS_DENIED;
7072                 }
7073
7074                 numlines = 0;
7075                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7076                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7077                 close(fd);
7078         }
7079
7080         *count = numlines;
7081         *lines = qlines;
7082
7083         return WERR_OK;
7084 }
7085
7086 /****************************************************************************
7087  enumports level 1.
7088 ****************************************************************************/
7089
7090 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7091                                 union spoolss_PortInfo **info_p,
7092                                 uint32_t *count)
7093 {
7094         union spoolss_PortInfo *info = NULL;
7095         int i=0;
7096         WERROR result = WERR_OK;
7097         char **qlines = NULL;
7098         int numlines = 0;
7099
7100         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7101         if (!W_ERROR_IS_OK(result)) {
7102                 goto out;
7103         }
7104
7105         if (numlines) {
7106                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7107                 if (!info) {
7108                         DEBUG(10,("Returning WERR_NOMEM\n"));
7109                         result = WERR_NOMEM;
7110                         goto out;
7111                 }
7112
7113                 for (i=0; i<numlines; i++) {
7114                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7115                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7116                         if (!W_ERROR_IS_OK(result)) {
7117                                 goto out;
7118                         }
7119                 }
7120         }
7121         TALLOC_FREE(qlines);
7122
7123 out:
7124         if (!W_ERROR_IS_OK(result)) {
7125                 TALLOC_FREE(info);
7126                 TALLOC_FREE(qlines);
7127                 *count = 0;
7128                 *info_p = NULL;
7129                 return result;
7130         }
7131
7132         *info_p = info;
7133         *count = numlines;
7134
7135         return WERR_OK;
7136 }
7137
7138 /****************************************************************************
7139  enumports level 2.
7140 ****************************************************************************/
7141
7142 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7143                                 union spoolss_PortInfo **info_p,
7144                                 uint32_t *count)
7145 {
7146         union spoolss_PortInfo *info = NULL;
7147         int i=0;
7148         WERROR result = WERR_OK;
7149         char **qlines = NULL;
7150         int numlines = 0;
7151
7152         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7153         if (!W_ERROR_IS_OK(result)) {
7154                 goto out;
7155         }
7156
7157         if (numlines) {
7158                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7159                 if (!info) {
7160                         DEBUG(10,("Returning WERR_NOMEM\n"));
7161                         result = WERR_NOMEM;
7162                         goto out;
7163                 }
7164
7165                 for (i=0; i<numlines; i++) {
7166                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7167                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7168                         if (!W_ERROR_IS_OK(result)) {
7169                                 goto out;
7170                         }
7171                 }
7172         }
7173         TALLOC_FREE(qlines);
7174
7175 out:
7176         if (!W_ERROR_IS_OK(result)) {
7177                 TALLOC_FREE(info);
7178                 TALLOC_FREE(qlines);
7179                 *count = 0;
7180                 *info_p = NULL;
7181                 return result;
7182         }
7183
7184         *info_p = info;
7185         *count = numlines;
7186
7187         return WERR_OK;
7188 }
7189
7190 /****************************************************************
7191  _spoolss_EnumPorts
7192 ****************************************************************/
7193
7194 WERROR _spoolss_EnumPorts(pipes_struct *p,
7195                           struct spoolss_EnumPorts *r)
7196 {
7197         WERROR result;
7198
7199         /* that's an [in out] buffer */
7200
7201         if (!r->in.buffer && (r->in.offered != 0)) {
7202                 return WERR_INVALID_PARAM;
7203         }
7204
7205         DEBUG(4,("_spoolss_EnumPorts\n"));
7206
7207         *r->out.count = 0;
7208         *r->out.needed = 0;
7209         *r->out.info = NULL;
7210
7211         switch (r->in.level) {
7212         case 1:
7213                 result = enumports_level_1(p->mem_ctx, r->out.info,
7214                                            r->out.count);
7215                 break;
7216         case 2:
7217                 result = enumports_level_2(p->mem_ctx, r->out.info,
7218                                            r->out.count);
7219                 break;
7220         default:
7221                 return WERR_UNKNOWN_LEVEL;
7222         }
7223
7224         if (!W_ERROR_IS_OK(result)) {
7225                 return result;
7226         }
7227
7228         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7229                                                      spoolss_EnumPorts, NULL,
7230                                                      *r->out.info, r->in.level,
7231                                                      *r->out.count);
7232         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7233         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7234
7235         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7236 }
7237
7238 /****************************************************************************
7239 ****************************************************************************/
7240
7241 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7242                                            const char *server,
7243                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7244                                            struct spoolss_DeviceMode *devmode,
7245                                            struct security_descriptor *sec_desc,
7246                                            struct spoolss_UserLevelCtr *user_ctr,
7247                                            struct policy_handle *handle)
7248 {
7249         NT_PRINTER_INFO_LEVEL *printer = NULL;
7250         fstring name;
7251         int     snum;
7252         WERROR err = WERR_OK;
7253
7254         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7255                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7256                 return WERR_NOMEM;
7257         }
7258
7259         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7260         if (!convert_printer_info(info_ctr, printer)) {
7261                 free_a_printer(&printer, 2);
7262                 return WERR_NOMEM;
7263         }
7264
7265         /* check to see if the printer already exists */
7266
7267         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7268                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7269                         printer->info_2->sharename));
7270                 free_a_printer(&printer, 2);
7271                 return WERR_PRINTER_ALREADY_EXISTS;
7272         }
7273
7274         /* FIXME!!!  smbd should check to see if the driver is installed before
7275            trying to add a printer like this  --jerry */
7276
7277         if (*lp_addprinter_cmd() ) {
7278                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7279                                        printer) ) {
7280                         free_a_printer(&printer,2);
7281                         return WERR_ACCESS_DENIED;
7282                 }
7283         } else {
7284                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7285                         "smb.conf parameter \"addprinter command\" is defined. This"
7286                         "parameter must exist for this call to succeed\n",
7287                         printer->info_2->sharename ));
7288         }
7289
7290         /* use our primary netbios name since get_a_printer() will convert
7291            it to what the client expects on a case by case basis */
7292
7293         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7294              printer->info_2->sharename);
7295
7296
7297         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7298                 free_a_printer(&printer,2);
7299                 return WERR_ACCESS_DENIED;
7300         }
7301
7302         /* you must be a printer admin to add a new printer */
7303         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7304                 free_a_printer(&printer,2);
7305                 return WERR_ACCESS_DENIED;
7306         }
7307
7308         /*
7309          * Do sanity check on the requested changes for Samba.
7310          */
7311
7312         if (!check_printer_ok(printer->info_2, snum)) {
7313                 free_a_printer(&printer,2);
7314                 return WERR_INVALID_PARAM;
7315         }
7316
7317         /*
7318          * When a printer is created, the drivername bound to the printer is used
7319          * to lookup previously saved driver initialization info, which is then
7320          * bound to the new printer, simulating what happens in the Windows arch.
7321          */
7322
7323         if (!devmode)
7324         {
7325                 set_driver_init(printer, 2);
7326         }
7327         else
7328         {
7329                 /* A valid devmode was included, convert and link it
7330                 */
7331                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7332
7333                 if (!convert_devicemode(printer->info_2->printername, devmode,
7334                                         &printer->info_2->devmode)) {
7335                         return  WERR_NOMEM;
7336                 }
7337         }
7338
7339         /* write the ASCII on disk */
7340         err = mod_a_printer(printer, 2);
7341         if (!W_ERROR_IS_OK(err)) {
7342                 free_a_printer(&printer,2);
7343                 return err;
7344         }
7345
7346         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7347                 /* Handle open failed - remove addition. */
7348                 del_a_printer(printer->info_2->sharename);
7349                 free_a_printer(&printer,2);
7350                 ZERO_STRUCTP(handle);
7351                 return WERR_ACCESS_DENIED;
7352         }
7353
7354         update_c_setprinter(false);
7355         free_a_printer(&printer,2);
7356
7357         return WERR_OK;
7358 }
7359
7360 /****************************************************************
7361  _spoolss_AddPrinterEx
7362 ****************************************************************/
7363
7364 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7365                              struct spoolss_AddPrinterEx *r)
7366 {
7367         switch (r->in.info_ctr->level) {
7368         case 1:
7369                 /* we don't handle yet */
7370                 /* but I know what to do ... */
7371                 return WERR_UNKNOWN_LEVEL;
7372         case 2:
7373                 return spoolss_addprinterex_level_2(p, r->in.server,
7374                                                     r->in.info_ctr,
7375                                                     r->in.devmode_ctr->devmode,
7376                                                     r->in.secdesc_ctr->sd,
7377                                                     r->in.userlevel_ctr,
7378                                                     r->out.handle);
7379         default:
7380                 return WERR_UNKNOWN_LEVEL;
7381         }
7382 }
7383
7384 /****************************************************************
7385  _spoolss_AddPrinter
7386 ****************************************************************/
7387
7388 WERROR _spoolss_AddPrinter(pipes_struct *p,
7389                            struct spoolss_AddPrinter *r)
7390 {
7391         struct spoolss_AddPrinterEx a;
7392         struct spoolss_UserLevelCtr userlevel_ctr;
7393
7394         ZERO_STRUCT(userlevel_ctr);
7395
7396         userlevel_ctr.level = 1;
7397
7398         a.in.server             = r->in.server;
7399         a.in.info_ctr           = r->in.info_ctr;
7400         a.in.devmode_ctr        = r->in.devmode_ctr;
7401         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7402         a.in.userlevel_ctr      = &userlevel_ctr;
7403         a.out.handle            = r->out.handle;
7404
7405         return _spoolss_AddPrinterEx(p, &a);
7406 }
7407
7408 /****************************************************************
7409  _spoolss_AddPrinterDriver
7410 ****************************************************************/
7411
7412 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7413                                  struct spoolss_AddPrinterDriver *r)
7414 {
7415         WERROR err = WERR_OK;
7416         char *driver_name = NULL;
7417         uint32_t version;
7418         const char *fn;
7419
7420         switch (p->hdr_req.opnum) {
7421                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7422                         fn = "_spoolss_AddPrinterDriver";
7423                         break;
7424                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7425                         fn = "_spoolss_AddPrinterDriverEx";
7426                         break;
7427                 default:
7428                         return WERR_INVALID_PARAM;
7429         }
7430
7431
7432         /* FIXME */
7433         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7434                 /* Clever hack from Martin Zielinski <mz@seh.de>
7435                  * to allow downgrade from level 8 (Vista).
7436                  */
7437                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7438                         r->in.info_ctr->level));
7439                 return WERR_UNKNOWN_LEVEL;
7440         }
7441
7442         DEBUG(5,("Cleaning driver's information\n"));
7443         err = clean_up_driver_struct(p, r->in.info_ctr);
7444         if (!W_ERROR_IS_OK(err))
7445                 goto done;
7446
7447         DEBUG(5,("Moving driver to final destination\n"));
7448         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7449                                                               &err)) ) {
7450                 goto done;
7451         }
7452
7453         if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7454                 err = WERR_ACCESS_DENIED;
7455                 goto done;
7456         }
7457
7458         /*
7459          * I think this is where he DrvUpgradePrinter() hook would be
7460          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7461          * server.  Right now, we just need to send ourselves a message
7462          * to update each printer bound to this driver.   --jerry
7463          */
7464
7465         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7466                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7467                         fn, driver_name));
7468         }
7469
7470         /*
7471          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7472          * decide if the driver init data should be deleted. The rules are:
7473          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7474          *  2) delete init data only if there is no 2k/Xp driver
7475          *  3) always delete init data
7476          * The generalized rule is always use init data from the highest order driver.
7477          * It is necessary to follow the driver install by an initialization step to
7478          * finish off this process.
7479         */
7480
7481         switch (version) {
7482                 /*
7483                  * 9x printer driver - never delete init data
7484                 */
7485                 case 0:
7486                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7487                                 fn, driver_name));
7488                         break;
7489
7490                 /*
7491                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7492                  * there is no 2k/Xp driver init data for this driver name.
7493                 */
7494                 case 2:
7495                 {
7496                         union spoolss_DriverInfo *driver1;
7497
7498                         if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &driver1, 3, driver_name, "Windows NT x86", 3))) {
7499                                 /*
7500                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7501                                 */
7502                                 if (!del_driver_init(driver_name))
7503                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7504                                                 fn, driver_name));
7505                         } else {
7506                                 /*
7507                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7508                                 */
7509                                 free_a_printer_driver(driver1);
7510                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7511                                         fn, driver_name));
7512                         }
7513                 }
7514                 break;
7515
7516                 /*
7517                  * 2k or Xp printer driver - always delete init data
7518                 */
7519                 case 3:
7520                         if (!del_driver_init(driver_name))
7521                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7522                                         fn, driver_name));
7523                         break;
7524
7525                 default:
7526                         DEBUG(0,("%s: invalid level=%d\n", fn,
7527                                 r->in.info_ctr->level));
7528                         break;
7529         }
7530
7531
7532 done:
7533         return err;
7534 }
7535
7536 /****************************************************************
7537  _spoolss_AddPrinterDriverEx
7538 ****************************************************************/
7539
7540 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7541                                    struct spoolss_AddPrinterDriverEx *r)
7542 {
7543         struct spoolss_AddPrinterDriver a;
7544
7545         /*
7546          * we only support the semantics of AddPrinterDriver()
7547          * i.e. only copy files that are newer than existing ones
7548          */
7549
7550         if (r->in.flags != APD_COPY_NEW_FILES) {
7551                 return WERR_ACCESS_DENIED;
7552         }
7553
7554         a.in.servername         = r->in.servername;
7555         a.in.info_ctr           = r->in.info_ctr;
7556
7557         return _spoolss_AddPrinterDriver(p, &a);
7558 }
7559
7560 /****************************************************************************
7561 ****************************************************************************/
7562
7563 struct _spoolss_paths {
7564         int type;
7565         const char *share;
7566         const char *dir;
7567 };
7568
7569 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7570
7571 static const struct _spoolss_paths spoolss_paths[]= {
7572         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7573         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7574 };
7575
7576 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7577                                           const char *servername,
7578                                           const char *environment,
7579                                           int component,
7580                                           char **path)
7581 {
7582         const char *pservername = NULL;
7583         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7584         const char *short_archi;
7585
7586         *path = NULL;
7587
7588         /* environment may be empty */
7589         if (environment && strlen(environment)) {
7590                 long_archi = environment;
7591         }
7592
7593         /* servername may be empty */
7594         if (servername && strlen(servername)) {
7595                 pservername = canon_servername(servername);
7596
7597                 if (!is_myname_or_ipaddr(pservername)) {
7598                         return WERR_INVALID_PARAM;
7599                 }
7600         }
7601
7602         if (!(short_archi = get_short_archi(long_archi))) {
7603                 return WERR_INVALID_ENVIRONMENT;
7604         }
7605
7606         switch (component) {
7607         case SPOOLSS_PRTPROCS_PATH:
7608         case SPOOLSS_DRIVER_PATH:
7609                 if (pservername) {
7610                         *path = talloc_asprintf(mem_ctx,
7611                                         "\\\\%s\\%s\\%s",
7612                                         pservername,
7613                                         spoolss_paths[component].share,
7614                                         short_archi);
7615                 } else {
7616                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7617                                         SPOOLSS_DEFAULT_SERVER_PATH,
7618                                         spoolss_paths[component].dir,
7619                                         short_archi);
7620                 }
7621                 break;
7622         default:
7623                 return WERR_INVALID_PARAM;
7624         }
7625
7626         if (!*path) {
7627                 return WERR_NOMEM;
7628         }
7629
7630         return WERR_OK;
7631 }
7632
7633 /****************************************************************************
7634 ****************************************************************************/
7635
7636 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7637                                           const char *servername,
7638                                           const char *environment,
7639                                           struct spoolss_DriverDirectoryInfo1 *r)
7640 {
7641         WERROR werr;
7642         char *path = NULL;
7643
7644         werr = compose_spoolss_server_path(mem_ctx,
7645                                            servername,
7646                                            environment,
7647                                            SPOOLSS_DRIVER_PATH,
7648                                            &path);
7649         if (!W_ERROR_IS_OK(werr)) {
7650                 return werr;
7651         }
7652
7653         DEBUG(4,("printer driver directory: [%s]\n", path));
7654
7655         r->directory_name = path;
7656
7657         return WERR_OK;
7658 }
7659
7660 /****************************************************************
7661  _spoolss_GetPrinterDriverDirectory
7662 ****************************************************************/
7663
7664 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7665                                           struct spoolss_GetPrinterDriverDirectory *r)
7666 {
7667         WERROR werror;
7668
7669         /* that's an [in out] buffer */
7670
7671         if (!r->in.buffer && (r->in.offered != 0)) {
7672                 return WERR_INVALID_PARAM;
7673         }
7674
7675         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7676                 r->in.level));
7677
7678         *r->out.needed = 0;
7679
7680         /* r->in.level is ignored */
7681
7682         werror = getprinterdriverdir_level_1(p->mem_ctx,
7683                                              r->in.server,
7684                                              r->in.environment,
7685                                              &r->out.info->info1);
7686         if (!W_ERROR_IS_OK(werror)) {
7687                 TALLOC_FREE(r->out.info);
7688                 return werror;
7689         }
7690
7691         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7692                                                r->out.info, r->in.level);
7693         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7694
7695         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7696 }
7697
7698 /****************************************************************
7699  _spoolss_EnumPrinterData
7700 ****************************************************************/
7701
7702 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7703                                 struct spoolss_EnumPrinterData *r)
7704 {
7705         NT_PRINTER_INFO_LEVEL *printer = NULL;
7706         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7707         int             snum;
7708         WERROR          result;
7709         struct regval_blob      *val = NULL;
7710         NT_PRINTER_DATA *p_data;
7711         int             i, key_index, num_values;
7712         int             name_length;
7713
7714         *r->out.value_needed    = 0;
7715         *r->out.type            = REG_NONE;
7716         *r->out.data_needed     = 0;
7717
7718         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7719
7720         if (!Printer) {
7721                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7722                         OUR_HANDLE(r->in.handle)));
7723                 return WERR_BADFID;
7724         }
7725
7726         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7727                 return WERR_BADFID;
7728         }
7729
7730         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7731         if (!W_ERROR_IS_OK(result)) {
7732                 return result;
7733         }
7734
7735         p_data = printer->info_2->data;
7736         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7737
7738         result = WERR_OK;
7739
7740         /*
7741          * The NT machine wants to know the biggest size of value and data
7742          *
7743          * cf: MSDN EnumPrinterData remark section
7744          */
7745
7746         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7747
7748                 uint32_t biggest_valuesize = 0;
7749                 uint32_t biggest_datasize = 0;
7750
7751                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7752
7753                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7754
7755                 for ( i=0; i<num_values; i++ )
7756                 {
7757                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7758
7759                         name_length = strlen(val->valuename);
7760                         if ( strlen(val->valuename) > biggest_valuesize )
7761                                 biggest_valuesize = name_length;
7762
7763                         if ( val->size > biggest_datasize )
7764                                 biggest_datasize = val->size;
7765
7766                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7767                                 biggest_datasize));
7768                 }
7769
7770                 /* the value is an UNICODE string but real_value_size is the length
7771                    in bytes including the trailing 0 */
7772
7773                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7774                 *r->out.data_needed  = biggest_datasize;
7775
7776                 DEBUG(6,("final values: [%d], [%d]\n",
7777                         *r->out.value_needed, *r->out.data_needed));
7778
7779                 goto done;
7780         }
7781
7782         /*
7783          * the value len is wrong in NT sp3
7784          * that's the number of bytes not the number of unicode chars
7785          */
7786
7787         if (key_index != -1) {
7788                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7789                                                 r->in.enum_index);
7790         }
7791
7792         if (!val) {
7793
7794                 /* out_value should default to "" or else NT4 has
7795                    problems unmarshalling the response */
7796
7797                 if (r->in.value_offered) {
7798                         *r->out.value_needed = 1;
7799                         r->out.value_name = talloc_strdup(r, "");
7800                         if (!r->out.value_name) {
7801                                 result = WERR_NOMEM;
7802                                 goto done;
7803                         }
7804                 } else {
7805                         r->out.value_name = NULL;
7806                         *r->out.value_needed = 0;
7807                 }
7808
7809                 /* the data is counted in bytes */
7810
7811                 *r->out.data_needed = r->in.data_offered;
7812
7813                 result = WERR_NO_MORE_ITEMS;
7814         } else {
7815                 /*
7816                  * the value is:
7817                  * - counted in bytes in the request
7818                  * - counted in UNICODE chars in the max reply
7819                  * - counted in bytes in the real size
7820                  *
7821                  * take a pause *before* coding not *during* coding
7822                  */
7823
7824                 /* name */
7825                 if (r->in.value_offered) {
7826                         r->out.value_name = talloc_strdup(r, regval_name(val));
7827                         if (!r->out.value_name) {
7828                                 result = WERR_NOMEM;
7829                                 goto done;
7830                         }
7831                         *r->out.value_needed = strlen_m(regval_name(val));
7832                 } else {
7833                         r->out.value_name = NULL;
7834                         *r->out.value_needed = 0;
7835                 }
7836
7837                 /* type */
7838
7839                 *r->out.type = regval_type(val);
7840
7841                 /* data - counted in bytes */
7842
7843                 if (r->out.data && regval_size(val)) {
7844                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
7845                 }
7846
7847                 *r->out.data_needed = regval_size(val);
7848         }
7849
7850 done:
7851         free_a_printer(&printer, 2);
7852         return result;
7853 }
7854
7855 /****************************************************************
7856  _spoolss_SetPrinterData
7857 ****************************************************************/
7858
7859 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7860                                struct spoolss_SetPrinterData *r)
7861 {
7862         NT_PRINTER_INFO_LEVEL *printer = NULL;
7863         int snum=0;
7864         WERROR result = WERR_OK;
7865         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7866         DATA_BLOB blob;
7867
7868         DEBUG(5,("_spoolss_SetPrinterData\n"));
7869
7870         if (!Printer) {
7871                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
7872                         OUR_HANDLE(r->in.handle)));
7873                 return WERR_BADFID;
7874         }
7875
7876         if (Printer->printer_type == SPLHND_SERVER) {
7877                 DEBUG(10,("_spoolss_SetPrinterData: "
7878                         "Not implemented for server handles yet\n"));
7879                 return WERR_INVALID_PARAM;
7880         }
7881
7882         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7883                 return WERR_BADFID;
7884         }
7885
7886         /*
7887          * Access check : NT returns "access denied" if you make a
7888          * SetPrinterData call without the necessary privildge.
7889          * we were originally returning OK if nothing changed
7890          * which made Win2k issue **a lot** of SetPrinterData
7891          * when connecting to a printer  --jerry
7892          */
7893
7894         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7895                 DEBUG(3,("_spoolss_SetPrinterData: "
7896                         "change denied by handle access permissions\n"));
7897                 result = WERR_ACCESS_DENIED;
7898                 goto done;
7899         }
7900
7901         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7902         if (!W_ERROR_IS_OK(result)) {
7903                 return result;
7904         }
7905
7906         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
7907                                           r->in.type, &r->in.data);
7908         if (!W_ERROR_IS_OK(result)) {
7909                 goto done;
7910         }
7911
7912         /*
7913          * When client side code sets a magic printer data key, detect it and save
7914          * the current printer data and the magic key's data (its the DEVMODE) for
7915          * future printer/driver initializations.
7916          */
7917         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
7918                 /* Set devmode and printer initialization info */
7919                 result = save_driver_init(printer, 2, blob.data, blob.length);
7920
7921                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
7922
7923                 goto done;
7924         }
7925
7926         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
7927                                     r->in.value_name, r->in.type,
7928                                     blob.data, blob.length);
7929         if (W_ERROR_IS_OK(result)) {
7930                 result = mod_a_printer(printer, 2);
7931         }
7932
7933 done:
7934         free_a_printer(&printer, 2);
7935
7936         return result;
7937 }
7938
7939 /****************************************************************
7940  _spoolss_ResetPrinter
7941 ****************************************************************/
7942
7943 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7944                              struct spoolss_ResetPrinter *r)
7945 {
7946         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7947         int             snum;
7948
7949         DEBUG(5,("_spoolss_ResetPrinter\n"));
7950
7951         /*
7952          * All we do is to check to see if the handle and queue is valid.
7953          * This call really doesn't mean anything to us because we only
7954          * support RAW printing.   --jerry
7955          */
7956
7957         if (!Printer) {
7958                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7959                         OUR_HANDLE(r->in.handle)));
7960                 return WERR_BADFID;
7961         }
7962
7963         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7964                 return WERR_BADFID;
7965
7966
7967         /* blindly return success */
7968         return WERR_OK;
7969 }
7970
7971 /****************************************************************
7972  _spoolss_DeletePrinterData
7973 ****************************************************************/
7974
7975 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7976                                   struct spoolss_DeletePrinterData *r)
7977 {
7978         NT_PRINTER_INFO_LEVEL   *printer = NULL;
7979         int             snum=0;
7980         WERROR          status = WERR_OK;
7981         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7982
7983         DEBUG(5,("_spoolss_DeletePrinterData\n"));
7984
7985         if (!Printer) {
7986                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
7987                         OUR_HANDLE(r->in.handle)));
7988                 return WERR_BADFID;
7989         }
7990
7991         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7992                 return WERR_BADFID;
7993
7994         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7995                 DEBUG(3, ("_spoolss_DeletePrinterData: "
7996                         "printer properties change denied by handle\n"));
7997                 return WERR_ACCESS_DENIED;
7998         }
7999
8000         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8001         if (!W_ERROR_IS_OK(status))
8002                 return status;
8003
8004         if (!r->in.value_name) {
8005                 free_a_printer(&printer, 2);
8006                 return WERR_NOMEM;
8007         }
8008
8009         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8010                                         r->in.value_name );
8011
8012         if ( W_ERROR_IS_OK(status) )
8013                 mod_a_printer( printer, 2 );
8014
8015         free_a_printer(&printer, 2);
8016
8017         return status;
8018 }
8019
8020 /****************************************************************
8021  _spoolss_AddForm
8022 ****************************************************************/
8023
8024 WERROR _spoolss_AddForm(pipes_struct *p,
8025                         struct spoolss_AddForm *r)
8026 {
8027         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8028         nt_forms_struct tmpForm;
8029         int snum = -1;
8030         WERROR status = WERR_OK;
8031         NT_PRINTER_INFO_LEVEL *printer = NULL;
8032         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8033
8034         int count=0;
8035         nt_forms_struct *list=NULL;
8036         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8037
8038         DEBUG(5,("_spoolss_AddForm\n"));
8039
8040         if (!Printer) {
8041                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8042                         OUR_HANDLE(r->in.handle)));
8043                 return WERR_BADFID;
8044         }
8045
8046
8047         /* forms can be added on printer of on the print server handle */
8048
8049         if ( Printer->printer_type == SPLHND_PRINTER )
8050         {
8051                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8052                         return WERR_BADFID;
8053
8054                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8055                 if (!W_ERROR_IS_OK(status))
8056                         goto done;
8057         }
8058
8059         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8060            and not a printer admin, then fail */
8061
8062         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8063              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8064              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8065                                           NULL, NULL,
8066                                           p->server_info->ptok,
8067                                           lp_printer_admin(snum))) {
8068                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8069                 return WERR_ACCESS_DENIED;
8070         }
8071
8072         /* can't add if builtin */
8073
8074         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8075                 status = WERR_FILE_EXISTS;
8076                 goto done;
8077         }
8078
8079         count = get_ntforms(&list);
8080
8081         if(!add_a_form(&list, form, &count)) {
8082                 status =  WERR_NOMEM;
8083                 goto done;
8084         }
8085
8086         become_root();
8087         write_ntforms(&list, count);
8088         unbecome_root();
8089
8090         /*
8091          * ChangeID must always be set if this is a printer
8092          */
8093
8094         if ( Printer->printer_type == SPLHND_PRINTER )
8095                 status = mod_a_printer(printer, 2);
8096
8097 done:
8098         if ( printer )
8099                 free_a_printer(&printer, 2);
8100         SAFE_FREE(list);
8101
8102         return status;
8103 }
8104
8105 /****************************************************************
8106  _spoolss_DeleteForm
8107 ****************************************************************/
8108
8109 WERROR _spoolss_DeleteForm(pipes_struct *p,
8110                            struct spoolss_DeleteForm *r)
8111 {
8112         const char *form_name = r->in.form_name;
8113         nt_forms_struct tmpForm;
8114         int count=0;
8115         nt_forms_struct *list=NULL;
8116         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8117         int snum = -1;
8118         WERROR status = WERR_OK;
8119         NT_PRINTER_INFO_LEVEL *printer = NULL;
8120         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8121         bool ret = false;
8122
8123         DEBUG(5,("_spoolss_DeleteForm\n"));
8124
8125         if (!Printer) {
8126                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8127                         OUR_HANDLE(r->in.handle)));
8128                 return WERR_BADFID;
8129         }
8130
8131         /* forms can be deleted on printer of on the print server handle */
8132
8133         if ( Printer->printer_type == SPLHND_PRINTER )
8134         {
8135                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8136                         return WERR_BADFID;
8137
8138                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8139                 if (!W_ERROR_IS_OK(status))
8140                         goto done;
8141         }
8142
8143         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8144              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8145              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8146                                           NULL, NULL,
8147                                           p->server_info->ptok,
8148                                           lp_printer_admin(snum))) {
8149                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8150                 return WERR_ACCESS_DENIED;
8151         }
8152
8153
8154         /* can't delete if builtin */
8155
8156         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8157                 status = WERR_INVALID_PARAM;
8158                 goto done;
8159         }
8160
8161         count = get_ntforms(&list);
8162
8163         become_root();
8164         ret = delete_a_form(&list, form_name, &count, &status);
8165         unbecome_root();
8166         if (ret == false) {
8167                 goto done;
8168         }
8169
8170         /*
8171          * ChangeID must always be set if this is a printer
8172          */
8173
8174         if ( Printer->printer_type == SPLHND_PRINTER )
8175                 status = mod_a_printer(printer, 2);
8176
8177 done:
8178         if ( printer )
8179                 free_a_printer(&printer, 2);
8180         SAFE_FREE(list);
8181
8182         return status;
8183 }
8184
8185 /****************************************************************
8186  _spoolss_SetForm
8187 ****************************************************************/
8188
8189 WERROR _spoolss_SetForm(pipes_struct *p,
8190                         struct spoolss_SetForm *r)
8191 {
8192         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8193         nt_forms_struct tmpForm;
8194         int snum = -1;
8195         WERROR status = WERR_OK;
8196         NT_PRINTER_INFO_LEVEL *printer = NULL;
8197         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8198
8199         int count=0;
8200         nt_forms_struct *list=NULL;
8201         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8202
8203         DEBUG(5,("_spoolss_SetForm\n"));
8204
8205         if (!Printer) {
8206                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8207                         OUR_HANDLE(r->in.handle)));
8208                 return WERR_BADFID;
8209         }
8210
8211         /* forms can be modified on printer of on the print server handle */
8212
8213         if ( Printer->printer_type == SPLHND_PRINTER )
8214         {
8215                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8216                         return WERR_BADFID;
8217
8218                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8219                 if (!W_ERROR_IS_OK(status))
8220                         goto done;
8221         }
8222
8223         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8224            and not a printer admin, then fail */
8225
8226         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8227              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8228              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8229                                           NULL, NULL,
8230                                           p->server_info->ptok,
8231                                           lp_printer_admin(snum))) {
8232                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8233                 return WERR_ACCESS_DENIED;
8234         }
8235
8236         /* can't set if builtin */
8237         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8238                 status = WERR_INVALID_PARAM;
8239                 goto done;
8240         }
8241
8242         count = get_ntforms(&list);
8243         update_a_form(&list, form, count);
8244         become_root();
8245         write_ntforms(&list, count);
8246         unbecome_root();
8247
8248         /*
8249          * ChangeID must always be set if this is a printer
8250          */
8251
8252         if ( Printer->printer_type == SPLHND_PRINTER )
8253                 status = mod_a_printer(printer, 2);
8254
8255
8256 done:
8257         if ( printer )
8258                 free_a_printer(&printer, 2);
8259         SAFE_FREE(list);
8260
8261         return status;
8262 }
8263
8264 /****************************************************************************
8265  fill_print_processor1
8266 ****************************************************************************/
8267
8268 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8269                                     struct spoolss_PrintProcessorInfo1 *r,
8270                                     const char *print_processor_name)
8271 {
8272         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8273         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8274
8275         return WERR_OK;
8276 }
8277
8278 /****************************************************************************
8279  enumprintprocessors level 1.
8280 ****************************************************************************/
8281
8282 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8283                                           union spoolss_PrintProcessorInfo **info_p,
8284                                           uint32_t *count)
8285 {
8286         union spoolss_PrintProcessorInfo *info;
8287         WERROR result;
8288
8289         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8290         W_ERROR_HAVE_NO_MEMORY(info);
8291
8292         *count = 1;
8293
8294         result = fill_print_processor1(info, &info[0].info1, "winprint");
8295         if (!W_ERROR_IS_OK(result)) {
8296                 goto out;
8297         }
8298
8299  out:
8300         if (!W_ERROR_IS_OK(result)) {
8301                 TALLOC_FREE(info);
8302                 *count = 0;
8303                 return result;
8304         }
8305
8306         *info_p = info;
8307
8308         return WERR_OK;
8309 }
8310
8311 /****************************************************************
8312  _spoolss_EnumPrintProcessors
8313 ****************************************************************/
8314
8315 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8316                                     struct spoolss_EnumPrintProcessors *r)
8317 {
8318         WERROR result;
8319
8320         /* that's an [in out] buffer */
8321
8322         if (!r->in.buffer && (r->in.offered != 0)) {
8323                 return WERR_INVALID_PARAM;
8324         }
8325
8326         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8327
8328         /*
8329          * Enumerate the print processors ...
8330          *
8331          * Just reply with "winprint", to keep NT happy
8332          * and I can use my nice printer checker.
8333          */
8334
8335         *r->out.count = 0;
8336         *r->out.needed = 0;
8337         *r->out.info = NULL;
8338
8339         switch (r->in.level) {
8340         case 1:
8341                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8342                                                      r->out.count);
8343                 break;
8344         default:
8345                 return WERR_UNKNOWN_LEVEL;
8346         }
8347
8348         if (!W_ERROR_IS_OK(result)) {
8349                 return result;
8350         }
8351
8352         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8353                                                      spoolss_EnumPrintProcessors, NULL,
8354                                                      *r->out.info, r->in.level,
8355                                                      *r->out.count);
8356         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8357         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8358
8359         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8360 }
8361
8362 /****************************************************************************
8363  fill_printprocdatatype1
8364 ****************************************************************************/
8365
8366 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8367                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8368                                       const char *name_array)
8369 {
8370         r->name_array = talloc_strdup(mem_ctx, name_array);
8371         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8372
8373         return WERR_OK;
8374 }
8375
8376 /****************************************************************************
8377  enumprintprocdatatypes level 1.
8378 ****************************************************************************/
8379
8380 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8381                                              union spoolss_PrintProcDataTypesInfo **info_p,
8382                                              uint32_t *count)
8383 {
8384         WERROR result;
8385         union spoolss_PrintProcDataTypesInfo *info;
8386
8387         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8388         W_ERROR_HAVE_NO_MEMORY(info);
8389
8390         *count = 1;
8391
8392         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8393         if (!W_ERROR_IS_OK(result)) {
8394                 goto out;
8395         }
8396
8397  out:
8398         if (!W_ERROR_IS_OK(result)) {
8399                 TALLOC_FREE(info);
8400                 *count = 0;
8401                 return result;
8402         }
8403
8404         *info_p = info;
8405
8406         return WERR_OK;
8407 }
8408
8409 /****************************************************************
8410  _spoolss_EnumPrintProcDataTypes
8411 ****************************************************************/
8412
8413 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8414                                        struct spoolss_EnumPrintProcDataTypes *r)
8415 {
8416         WERROR result;
8417
8418         /* that's an [in out] buffer */
8419
8420         if (!r->in.buffer && (r->in.offered != 0)) {
8421                 return WERR_INVALID_PARAM;
8422         }
8423
8424         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8425
8426         *r->out.count = 0;
8427         *r->out.needed = 0;
8428         *r->out.info = NULL;
8429
8430         switch (r->in.level) {
8431         case 1:
8432                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8433                                                         r->out.count);
8434                 break;
8435         default:
8436                 return WERR_UNKNOWN_LEVEL;
8437         }
8438
8439         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8440                                                      spoolss_EnumPrintProcDataTypes, NULL,
8441                                                      *r->out.info, r->in.level,
8442                                                      *r->out.count);
8443         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8444         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8445
8446         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8447 }
8448
8449 /****************************************************************************
8450  fill_monitor_1
8451 ****************************************************************************/
8452
8453 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8454                              struct spoolss_MonitorInfo1 *r,
8455                              const char *monitor_name)
8456 {
8457         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8458         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8459
8460         return WERR_OK;
8461 }
8462
8463 /****************************************************************************
8464  fill_monitor_2
8465 ****************************************************************************/
8466
8467 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8468                              struct spoolss_MonitorInfo2 *r,
8469                              const char *monitor_name,
8470                              const char *environment,
8471                              const char *dll_name)
8472 {
8473         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8474         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8475         r->environment                  = talloc_strdup(mem_ctx, environment);
8476         W_ERROR_HAVE_NO_MEMORY(r->environment);
8477         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8478         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8479
8480         return WERR_OK;
8481 }
8482
8483 /****************************************************************************
8484  enumprintmonitors level 1.
8485 ****************************************************************************/
8486
8487 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8488                                         union spoolss_MonitorInfo **info_p,
8489                                         uint32_t *count)
8490 {
8491         union spoolss_MonitorInfo *info;
8492         WERROR result = WERR_OK;
8493
8494         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8495         W_ERROR_HAVE_NO_MEMORY(info);
8496
8497         *count = 2;
8498
8499         result = fill_monitor_1(info, &info[0].info1,
8500                                 SPL_LOCAL_PORT);
8501         if (!W_ERROR_IS_OK(result)) {
8502                 goto out;
8503         }
8504
8505         result = fill_monitor_1(info, &info[1].info1,
8506                                 SPL_TCPIP_PORT);
8507         if (!W_ERROR_IS_OK(result)) {
8508                 goto out;
8509         }
8510
8511 out:
8512         if (!W_ERROR_IS_OK(result)) {
8513                 TALLOC_FREE(info);
8514                 *count = 0;
8515                 return result;
8516         }
8517
8518         *info_p = info;
8519
8520         return WERR_OK;
8521 }
8522
8523 /****************************************************************************
8524  enumprintmonitors level 2.
8525 ****************************************************************************/
8526
8527 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8528                                         union spoolss_MonitorInfo **info_p,
8529                                         uint32_t *count)
8530 {
8531         union spoolss_MonitorInfo *info;
8532         WERROR result = WERR_OK;
8533
8534         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8535         W_ERROR_HAVE_NO_MEMORY(info);
8536
8537         *count = 2;
8538
8539         result = fill_monitor_2(info, &info[0].info2,
8540                                 SPL_LOCAL_PORT,
8541                                 "Windows NT X86", /* FIXME */
8542                                 "localmon.dll");
8543         if (!W_ERROR_IS_OK(result)) {
8544                 goto out;
8545         }
8546
8547         result = fill_monitor_2(info, &info[1].info2,
8548                                 SPL_TCPIP_PORT,
8549                                 "Windows NT X86", /* FIXME */
8550                                 "tcpmon.dll");
8551         if (!W_ERROR_IS_OK(result)) {
8552                 goto out;
8553         }
8554
8555 out:
8556         if (!W_ERROR_IS_OK(result)) {
8557                 TALLOC_FREE(info);
8558                 *count = 0;
8559                 return result;
8560         }
8561
8562         *info_p = info;
8563
8564         return WERR_OK;
8565 }
8566
8567 /****************************************************************
8568  _spoolss_EnumMonitors
8569 ****************************************************************/
8570
8571 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8572                              struct spoolss_EnumMonitors *r)
8573 {
8574         WERROR result;
8575
8576         /* that's an [in out] buffer */
8577
8578         if (!r->in.buffer && (r->in.offered != 0)) {
8579                 return WERR_INVALID_PARAM;
8580         }
8581
8582         DEBUG(5,("_spoolss_EnumMonitors\n"));
8583
8584         /*
8585          * Enumerate the print monitors ...
8586          *
8587          * Just reply with "Local Port", to keep NT happy
8588          * and I can use my nice printer checker.
8589          */
8590
8591         *r->out.count = 0;
8592         *r->out.needed = 0;
8593         *r->out.info = NULL;
8594
8595         switch (r->in.level) {
8596         case 1:
8597                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8598                                                    r->out.count);
8599                 break;
8600         case 2:
8601                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8602                                                    r->out.count);
8603                 break;
8604         default:
8605                 return WERR_UNKNOWN_LEVEL;
8606         }
8607
8608         if (!W_ERROR_IS_OK(result)) {
8609                 return result;
8610         }
8611
8612         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8613                                                      spoolss_EnumMonitors, NULL,
8614                                                      *r->out.info, r->in.level,
8615                                                      *r->out.count);
8616         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8617         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8618
8619         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8620 }
8621
8622 /****************************************************************************
8623 ****************************************************************************/
8624
8625 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8626                              const print_queue_struct *queue,
8627                              int count, int snum,
8628                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8629                              uint32_t jobid,
8630                              struct spoolss_JobInfo1 *r)
8631 {
8632         int i = 0;
8633         bool found = false;
8634
8635         for (i=0; i<count && found == false; i++) {
8636                 if (queue[i].job == (int)jobid) {
8637                         found = true;
8638                 }
8639         }
8640
8641         if (found == false) {
8642                 /* NT treats not found as bad param... yet another bad choice */
8643                 return WERR_INVALID_PARAM;
8644         }
8645
8646         return fill_job_info1(mem_ctx,
8647                               r,
8648                               &queue[i-1],
8649                               i,
8650                               snum,
8651                               ntprinter);
8652 }
8653
8654 /****************************************************************************
8655 ****************************************************************************/
8656
8657 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8658                              const print_queue_struct *queue,
8659                              int count, int snum,
8660                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8661                              uint32_t jobid,
8662                              struct spoolss_JobInfo2 *r)
8663 {
8664         int i = 0;
8665         bool found = false;
8666         struct spoolss_DeviceMode *devmode;
8667         NT_DEVICEMODE *nt_devmode;
8668         WERROR result;
8669
8670         for (i=0; i<count && found == false; i++) {
8671                 if (queue[i].job == (int)jobid) {
8672                         found = true;
8673                 }
8674         }
8675
8676         if (found == false) {
8677                 /* NT treats not found as bad param... yet another bad
8678                    choice */
8679                 return WERR_INVALID_PARAM;
8680         }
8681
8682         /*
8683          * if the print job does not have a DEVMODE associated with it,
8684          * just use the one for the printer. A NULL devicemode is not
8685          *  a failure condition
8686          */
8687
8688         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8689         if (nt_devmode) {
8690                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8691                 W_ERROR_HAVE_NO_MEMORY(devmode);
8692                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8693                 if (!W_ERROR_IS_OK(result)) {
8694                         return result;
8695                 }
8696         } else {
8697                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8698                 W_ERROR_HAVE_NO_MEMORY(devmode);
8699         }
8700
8701         return fill_job_info2(mem_ctx,
8702                               r,
8703                               &queue[i-1],
8704                               i,
8705                               snum,
8706                               ntprinter,
8707                               devmode);
8708 }
8709
8710 /****************************************************************
8711  _spoolss_GetJob
8712 ****************************************************************/
8713
8714 WERROR _spoolss_GetJob(pipes_struct *p,
8715                        struct spoolss_GetJob *r)
8716 {
8717         WERROR result = WERR_OK;
8718         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8719         int snum;
8720         int count;
8721         print_queue_struct      *queue = NULL;
8722         print_status_struct prt_status;
8723
8724         /* that's an [in out] buffer */
8725
8726         if (!r->in.buffer && (r->in.offered != 0)) {
8727                 return WERR_INVALID_PARAM;
8728         }
8729
8730         DEBUG(5,("_spoolss_GetJob\n"));
8731
8732         *r->out.needed = 0;
8733
8734         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8735                 return WERR_BADFID;
8736         }
8737
8738         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8739         if (!W_ERROR_IS_OK(result)) {
8740                 return result;
8741         }
8742
8743         count = print_queue_status(snum, &queue, &prt_status);
8744
8745         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8746                      count, prt_status.status, prt_status.message));
8747
8748         switch (r->in.level) {
8749         case 1:
8750                 result = getjob_level_1(p->mem_ctx,
8751                                         queue, count, snum, ntprinter,
8752                                         r->in.job_id, &r->out.info->info1);
8753                 break;
8754         case 2:
8755                 result = getjob_level_2(p->mem_ctx,
8756                                         queue, count, snum, ntprinter,
8757                                         r->in.job_id, &r->out.info->info2);
8758                 break;
8759         default:
8760                 result = WERR_UNKNOWN_LEVEL;
8761                 break;
8762         }
8763
8764         SAFE_FREE(queue);
8765         free_a_printer(&ntprinter, 2);
8766
8767         if (!W_ERROR_IS_OK(result)) {
8768                 TALLOC_FREE(r->out.info);
8769                 return result;
8770         }
8771
8772         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8773                                                r->out.info, r->in.level);
8774         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8775
8776         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8777 }
8778
8779 /****************************************************************
8780  _spoolss_GetPrinterDataEx
8781 ****************************************************************/
8782
8783 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8784                                  struct spoolss_GetPrinterDataEx *r)
8785 {
8786
8787         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8788         struct regval_blob              *val = NULL;
8789         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8790         int                     snum = 0;
8791         WERROR result = WERR_OK;
8792         DATA_BLOB blob;
8793
8794         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8795
8796         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8797                 r->in.key_name, r->in.value_name));
8798
8799         /* in case of problem, return some default values */
8800
8801         *r->out.needed  = 0;
8802         *r->out.type    = REG_NONE;
8803
8804         if (!Printer) {
8805                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8806                         OUR_HANDLE(r->in.handle)));
8807                 result = WERR_BADFID;
8808                 goto done;
8809         }
8810
8811         /* Is the handle to a printer or to the server? */
8812
8813         if (Printer->printer_type == SPLHND_SERVER) {
8814
8815                 result = getprinterdata_printer_server(p->mem_ctx,
8816                                                        r->in.value_name,
8817                                                        r->out.type,
8818                                                        r->out.data);
8819                 goto done;
8820         }
8821
8822         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8823                 result = WERR_BADFID;
8824                 goto done;
8825         }
8826
8827         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8828         if (!W_ERROR_IS_OK(result)) {
8829                 goto done;
8830         }
8831
8832         /* check to see if the keyname is valid */
8833         if (!strlen(r->in.key_name)) {
8834                 result = WERR_INVALID_PARAM;
8835                 goto done;
8836         }
8837
8838         /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8839
8840         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8841             strequal(r->in.value_name, "ChangeId")) {
8842                 *r->out.type = REG_DWORD;
8843                 *r->out.needed = 4;
8844                 r->out.data->value = printer->info_2->changeid;
8845                 result = WERR_OK;
8846                 goto done;
8847         }
8848
8849         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8850                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8851                         "Invalid keyname [%s]\n", r->in.key_name ));
8852                 result = WERR_BADFILE;
8853                 goto done;
8854         }
8855
8856         val = get_printer_data(printer->info_2,
8857                                r->in.key_name, r->in.value_name);
8858         if (!val) {
8859                 result = WERR_BADFILE;
8860                 goto done;
8861         }
8862
8863         *r->out.needed = regval_size(val);
8864         *r->out.type = regval_type(val);
8865
8866         blob = data_blob_const(regval_data_p(val), regval_size(val));
8867
8868         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
8869                                           r->out.data,
8870                                           *r->out.type);
8871
8872  done:
8873         if (printer) {
8874                 free_a_printer(&printer, 2);
8875         }
8876
8877         if (!W_ERROR_IS_OK(result)) {
8878                 return result;
8879         }
8880
8881         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
8882         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8883         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8884
8885         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8886 }
8887
8888 /****************************************************************
8889  _spoolss_SetPrinterDataEx
8890 ****************************************************************/
8891
8892 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8893                                  struct spoolss_SetPrinterDataEx *r)
8894 {
8895         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8896         int                     snum = 0;
8897         WERROR                  result = WERR_OK;
8898         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8899         char                    *oid_string;
8900
8901         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8902
8903         /* From MSDN documentation of SetPrinterDataEx: pass request to
8904            SetPrinterData if key is "PrinterDriverData" */
8905
8906         if (!Printer) {
8907                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8908                         OUR_HANDLE(r->in.handle)));
8909                 return WERR_BADFID;
8910         }
8911
8912         if (Printer->printer_type == SPLHND_SERVER) {
8913                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8914                         "Not implemented for server handles yet\n"));
8915                 return WERR_INVALID_PARAM;
8916         }
8917
8918         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8919                 return WERR_BADFID;
8920         }
8921
8922         /*
8923          * Access check : NT returns "access denied" if you make a
8924          * SetPrinterData call without the necessary privildge.
8925          * we were originally returning OK if nothing changed
8926          * which made Win2k issue **a lot** of SetPrinterData
8927          * when connecting to a printer  --jerry
8928          */
8929
8930         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8931                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8932                         "change denied by handle access permissions\n"));
8933                 return WERR_ACCESS_DENIED;
8934         }
8935
8936         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8937         if (!W_ERROR_IS_OK(result)) {
8938                 return result;
8939         }
8940
8941         /* check for OID in valuename */
8942
8943         oid_string = strchr(r->in.value_name, ',');
8944         if (oid_string) {
8945                 *oid_string = '\0';
8946                 oid_string++;
8947         }
8948
8949         /* save the registry data */
8950
8951         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8952                                     r->in.type, r->in.buffer, r->in.offered);
8953
8954         if (W_ERROR_IS_OK(result)) {
8955                 /* save the OID if one was specified */
8956                 if (oid_string) {
8957                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8958                                 r->in.key_name, SPOOL_OID_KEY);
8959                         if (!str) {
8960                                 result = WERR_NOMEM;
8961                                 goto done;
8962                         }
8963
8964                         /*
8965                          * I'm not checking the status here on purpose.  Don't know
8966                          * if this is right, but I'm returning the status from the
8967                          * previous set_printer_dataex() call.  I have no idea if
8968                          * this is right.    --jerry
8969                          */
8970
8971                         set_printer_dataex(printer, str, r->in.value_name,
8972                                            REG_SZ, (uint8_t *)oid_string,
8973                                            strlen(oid_string)+1);
8974                 }
8975
8976                 result = mod_a_printer(printer, 2);
8977         }
8978
8979  done:
8980         free_a_printer(&printer, 2);
8981
8982         return result;
8983 }
8984
8985 /****************************************************************
8986  _spoolss_DeletePrinterDataEx
8987 ****************************************************************/
8988
8989 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8990                                     struct spoolss_DeletePrinterDataEx *r)
8991 {
8992         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8993         int             snum=0;
8994         WERROR          status = WERR_OK;
8995         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8996
8997         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8998
8999         if (!Printer) {
9000                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9001                         "Invalid handle (%s:%u:%u).\n",
9002                         OUR_HANDLE(r->in.handle)));
9003                 return WERR_BADFID;
9004         }
9005
9006         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9007                 return WERR_BADFID;
9008
9009         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9010                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9011                         "printer properties change denied by handle\n"));
9012                 return WERR_ACCESS_DENIED;
9013         }
9014
9015         if (!r->in.value_name || !r->in.key_name) {
9016                 return WERR_NOMEM;
9017         }
9018
9019         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9020         if (!W_ERROR_IS_OK(status))
9021                 return status;
9022
9023         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9024
9025         if ( W_ERROR_IS_OK(status) )
9026                 mod_a_printer( printer, 2 );
9027
9028         free_a_printer(&printer, 2);
9029
9030         return status;
9031 }
9032
9033 /****************************************************************
9034  _spoolss_EnumPrinterKey
9035 ****************************************************************/
9036
9037 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9038                                struct spoolss_EnumPrinterKey *r)
9039 {
9040         fstring         *keynames = NULL;
9041         int             num_keys;
9042         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9043         NT_PRINTER_DATA *data;
9044         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9045         int             snum = 0;
9046         WERROR          result = WERR_BADFILE;
9047         int i;
9048         const char **array = NULL;
9049         DATA_BLOB blob;
9050
9051         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9052
9053         if (!Printer) {
9054                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9055                         OUR_HANDLE(r->in.handle)));
9056                 return WERR_BADFID;
9057         }
9058
9059         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9060                 return WERR_BADFID;
9061         }
9062
9063         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9064         if (!W_ERROR_IS_OK(result)) {
9065                 return result;
9066         }
9067
9068         /* get the list of subkey names */
9069
9070         data = printer->info_2->data;
9071
9072         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9073         if (num_keys == -1) {
9074                 result = WERR_BADFILE;
9075                 goto done;
9076         }
9077
9078         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9079         if (!array) {
9080                 result = WERR_NOMEM;
9081                 goto done;
9082         }
9083
9084         for (i=0; i < num_keys; i++) {
9085
9086                 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
9087                         keynames[i]));
9088
9089                 array[i] = talloc_strdup(array, keynames[i]);
9090                 if (!array[i]) {
9091                         result = WERR_NOMEM;
9092                         goto done;
9093                 }
9094         }
9095
9096         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9097                 result = WERR_NOMEM;
9098                 goto done;
9099         }
9100
9101         *r->out.needed = blob.length;
9102
9103         if (r->in.offered < *r->out.needed) {
9104                 result = WERR_MORE_DATA;
9105         } else {
9106                 result = WERR_OK;
9107                 r->out.key_buffer->string = array;
9108         }
9109
9110  done:
9111         if (!W_ERROR_IS_OK(result)) {
9112                 TALLOC_FREE(array);
9113                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9114                         *r->out.needed = 0;
9115                 }
9116         }
9117
9118         free_a_printer(&printer, 2);
9119         SAFE_FREE(keynames);
9120
9121         return result;
9122 }
9123
9124 /****************************************************************
9125  _spoolss_DeletePrinterKey
9126 ****************************************************************/
9127
9128 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9129                                  struct spoolss_DeletePrinterKey *r)
9130 {
9131         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9132         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9133         int                     snum=0;
9134         WERROR                  status;
9135
9136         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9137
9138         if (!Printer) {
9139                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9140                         OUR_HANDLE(r->in.handle)));
9141                 return WERR_BADFID;
9142         }
9143
9144         /* if keyname == NULL, return error */
9145
9146         if ( !r->in.key_name )
9147                 return WERR_INVALID_PARAM;
9148
9149         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9150                 return WERR_BADFID;
9151
9152         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9153                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9154                         "printer properties change denied by handle\n"));
9155                 return WERR_ACCESS_DENIED;
9156         }
9157
9158         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9159         if (!W_ERROR_IS_OK(status))
9160                 return status;
9161
9162         /* delete the key and all subneys */
9163
9164         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9165
9166         if ( W_ERROR_IS_OK(status) )
9167                 status = mod_a_printer(printer, 2);
9168
9169         free_a_printer( &printer, 2 );
9170
9171         return status;
9172 }
9173
9174 /****************************************************************
9175 ****************************************************************/
9176
9177 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9178                                                    struct regval_blob *v,
9179                                                    struct spoolss_PrinterEnumValues *r)
9180 {
9181         WERROR result;
9182
9183         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9184         W_ERROR_HAVE_NO_MEMORY(r->data);
9185
9186         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9187         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9188
9189         r->type         = regval_type(v);
9190         r->data_length  = regval_size(v);
9191
9192         if (r->data_length) {
9193                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9194                                                  regval_size(v));
9195                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9196                                                   r->data,
9197                                                   r->type);
9198                 if (!W_ERROR_IS_OK(result)) {
9199                         return result;
9200                 }
9201         }
9202
9203         return WERR_OK;
9204 }
9205
9206 /****************************************************************
9207  _spoolss_EnumPrinterDataEx
9208 ****************************************************************/
9209
9210 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9211                                   struct spoolss_EnumPrinterDataEx *r)
9212 {
9213         uint32_t        count = 0;
9214         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9215         struct spoolss_PrinterEnumValues *info = NULL;
9216         NT_PRINTER_DATA         *p_data;
9217         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9218         int             snum;
9219         WERROR          result;
9220         int             key_index;
9221         int             i;
9222
9223         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9224
9225         *r->out.count = 0;
9226         *r->out.needed = 0;
9227         *r->out.info = NULL;
9228
9229         if (!Printer) {
9230                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9231                         OUR_HANDLE(r->in.handle)));
9232                 return WERR_BADFID;
9233         }
9234
9235         /*
9236          * first check for a keyname of NULL or "".  Win2k seems to send
9237          * this a lot and we should send back WERR_INVALID_PARAM
9238          * no need to spend time looking up the printer in this case.
9239          * --jerry
9240          */
9241
9242         if (!strlen(r->in.key_name)) {
9243                 result = WERR_INVALID_PARAM;
9244                 goto done;
9245         }
9246
9247         /* get the printer off of disk */
9248
9249         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9250                 return WERR_BADFID;
9251         }
9252
9253         ZERO_STRUCT(printer);
9254         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9255         if (!W_ERROR_IS_OK(result)) {
9256                 return result;
9257         }
9258
9259         /* now look for a match on the key name */
9260
9261         p_data = printer->info_2->data;
9262
9263         key_index = lookup_printerkey(p_data, r->in.key_name);
9264         if (key_index == -1) {
9265                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9266                         r->in.key_name));
9267                 result = WERR_INVALID_PARAM;
9268                 goto done;
9269         }
9270
9271         /* allocate the memory for the array of pointers -- if necessary */
9272
9273         count = regval_ctr_numvals(p_data->keys[key_index].values);
9274         if (!count) {
9275                 result = WERR_OK; /* ??? */
9276                 goto done;
9277         }
9278
9279         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9280                                  struct spoolss_PrinterEnumValues,
9281                                  count);
9282         if (!info) {
9283                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9284                 result = WERR_NOMEM;
9285                 goto done;
9286         }
9287
9288         /*
9289          * loop through all params and build the array to pass
9290          * back to the  client
9291          */
9292
9293         for (i=0; i < count; i++) {
9294
9295                 struct regval_blob      *val;
9296
9297                 /* lookup the registry value */
9298
9299                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9300
9301                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9302
9303                 /* copy the data */
9304
9305                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9306                 if (!W_ERROR_IS_OK(result)) {
9307                         goto done;
9308                 }
9309         }
9310
9311 #if 0 /* FIXME - gd */
9312         /* housekeeping information in the reply */
9313
9314         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9315          * the hand marshalled container size is a multiple
9316          * of 4 bytes for RPC alignment.
9317          */
9318
9319         if (needed % 4) {
9320                 needed += 4-(needed % 4);
9321         }
9322 #endif
9323         *r->out.count   = count;
9324         *r->out.info    = info;
9325
9326  done:
9327
9328         if (printer) {
9329                 free_a_printer(&printer, 2);
9330         }
9331
9332         if (!W_ERROR_IS_OK(result)) {
9333                 return result;
9334         }
9335
9336         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9337                                                spoolss_EnumPrinterDataEx, NULL,
9338                                                *r->out.info,
9339                                                *r->out.count);
9340         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9341         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9342
9343         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9344 }
9345
9346 /****************************************************************************
9347 ****************************************************************************/
9348
9349 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9350                                                  const char *servername,
9351                                                  const char *environment,
9352                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9353 {
9354         WERROR werr;
9355         char *path = NULL;
9356
9357         werr = compose_spoolss_server_path(mem_ctx,
9358                                            servername,
9359                                            environment,
9360                                            SPOOLSS_PRTPROCS_PATH,
9361                                            &path);
9362         if (!W_ERROR_IS_OK(werr)) {
9363                 return werr;
9364         }
9365
9366         DEBUG(4,("print processor directory: [%s]\n", path));
9367
9368         r->directory_name = path;
9369
9370         return WERR_OK;
9371 }
9372
9373 /****************************************************************
9374  _spoolss_GetPrintProcessorDirectory
9375 ****************************************************************/
9376
9377 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9378                                            struct spoolss_GetPrintProcessorDirectory *r)
9379 {
9380         WERROR result;
9381
9382         /* that's an [in out] buffer */
9383
9384         if (!r->in.buffer && (r->in.offered != 0)) {
9385                 return WERR_INVALID_PARAM;
9386         }
9387
9388         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9389                 r->in.level));
9390
9391         *r->out.needed = 0;
9392
9393         /* r->in.level is ignored */
9394
9395         /* We always should reply with a local print processor directory so that
9396          * users are not forced to have a [prnproc$] share on the Samba spoolss
9397          * server - Guenther */
9398
9399         result = getprintprocessordirectory_level_1(p->mem_ctx,
9400                                                     NULL, /* r->in.server */
9401                                                     r->in.environment,
9402                                                     &r->out.info->info1);
9403         if (!W_ERROR_IS_OK(result)) {
9404                 TALLOC_FREE(r->out.info);
9405                 return result;
9406         }
9407
9408         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9409                                                r->out.info, r->in.level);
9410         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9411
9412         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9413 }
9414
9415 /*******************************************************************
9416  ********************************************************************/
9417
9418 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9419                                const char *dllname)
9420 {
9421         enum ndr_err_code ndr_err;
9422         struct spoolss_MonitorUi ui;
9423
9424         ui.dll_name = dllname;
9425
9426         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9427                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9428         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9429                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9430         }
9431         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9432 }
9433
9434 /*******************************************************************
9435  Streams the monitor UI DLL name in UNICODE
9436 *******************************************************************/
9437
9438 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9439                                NT_USER_TOKEN *token, DATA_BLOB *in,
9440                                DATA_BLOB *out, uint32_t *needed)
9441 {
9442         const char *dllname = "tcpmonui.dll";
9443
9444         *needed = (strlen(dllname)+1) * 2;
9445
9446         if (out->length < *needed) {
9447                 return WERR_INSUFFICIENT_BUFFER;
9448         }
9449
9450         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9451                 return WERR_NOMEM;
9452         }
9453
9454         return WERR_OK;
9455 }
9456
9457 /*******************************************************************
9458  ********************************************************************/
9459
9460 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9461                              struct spoolss_PortData1 *port1,
9462                              const DATA_BLOB *buf)
9463 {
9464         enum ndr_err_code ndr_err;
9465         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9466                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9467         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9468                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9469         }
9470         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9471 }
9472
9473 /*******************************************************************
9474  ********************************************************************/
9475
9476 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9477                              struct spoolss_PortData2 *port2,
9478                              const DATA_BLOB *buf)
9479 {
9480         enum ndr_err_code ndr_err;
9481         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9482                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9483         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9484                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9485         }
9486         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9487 }
9488
9489 /*******************************************************************
9490  Create a new TCP/IP port
9491 *******************************************************************/
9492
9493 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9494                              NT_USER_TOKEN *token, DATA_BLOB *in,
9495                              DATA_BLOB *out, uint32_t *needed)
9496 {
9497         struct spoolss_PortData1 port1;
9498         struct spoolss_PortData2 port2;
9499         char *device_uri = NULL;
9500         uint32_t version;
9501
9502         const char *portname;
9503         const char *hostaddress;
9504         const char *queue;
9505         uint32_t port_number;
9506         uint32_t protocol;
9507
9508         /* peek for spoolss_PortData version */
9509
9510         if (!in || (in->length < (128 + 4))) {
9511                 return WERR_GENERAL_FAILURE;
9512         }
9513
9514         version = IVAL(in->data, 128);
9515
9516         switch (version) {
9517                 case 1:
9518                         ZERO_STRUCT(port1);
9519
9520                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9521                                 return WERR_NOMEM;
9522                         }
9523
9524                         portname        = port1.portname;
9525                         hostaddress     = port1.hostaddress;
9526                         queue           = port1.queue;
9527                         protocol        = port1.protocol;
9528                         port_number     = port1.port_number;
9529
9530                         break;
9531                 case 2:
9532                         ZERO_STRUCT(port2);
9533
9534                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9535                                 return WERR_NOMEM;
9536                         }
9537
9538                         portname        = port2.portname;
9539                         hostaddress     = port2.hostaddress;
9540                         queue           = port2.queue;
9541                         protocol        = port2.protocol;
9542                         port_number     = port2.port_number;
9543
9544                         break;
9545                 default:
9546                         DEBUG(1,("xcvtcp_addport: "
9547                                 "unknown version of port_data: %d\n", version));
9548                         return WERR_UNKNOWN_PORT;
9549         }
9550
9551         /* create the device URI and call the add_port_hook() */
9552
9553         switch (protocol) {
9554         case PROTOCOL_RAWTCP_TYPE:
9555                 device_uri = talloc_asprintf(mem_ctx,
9556                                 "socket://%s:%d/", hostaddress,
9557                                 port_number);
9558                 break;
9559
9560         case PROTOCOL_LPR_TYPE:
9561                 device_uri = talloc_asprintf(mem_ctx,
9562                         "lpr://%s/%s", hostaddress, queue );
9563                 break;
9564
9565         default:
9566                 return WERR_UNKNOWN_PORT;
9567         }
9568
9569         if (!device_uri) {
9570                 return WERR_NOMEM;
9571         }
9572
9573         return add_port_hook(mem_ctx, token, portname, device_uri);
9574 }
9575
9576 /*******************************************************************
9577 *******************************************************************/
9578
9579 struct xcv_api_table xcvtcp_cmds[] = {
9580         { "MonitorUI",  xcvtcp_monitorui },
9581         { "AddPort",    xcvtcp_addport},
9582         { NULL,         NULL }
9583 };
9584
9585 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9586                                      NT_USER_TOKEN *token, const char *command,
9587                                      DATA_BLOB *inbuf,
9588                                      DATA_BLOB *outbuf,
9589                                      uint32_t *needed )
9590 {
9591         int i;
9592
9593         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9594
9595         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9596                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9597                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9598         }
9599
9600         return WERR_BADFUNC;
9601 }
9602
9603 /*******************************************************************
9604 *******************************************************************/
9605 #if 0   /* don't support management using the "Local Port" monitor */
9606
9607 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9608                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9609                                  DATA_BLOB *out, uint32_t *needed)
9610 {
9611         const char *dllname = "localui.dll";
9612
9613         *needed = (strlen(dllname)+1) * 2;
9614
9615         if (out->length < *needed) {
9616                 return WERR_INSUFFICIENT_BUFFER;
9617         }
9618
9619         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9620                 return WERR_NOMEM;
9621         }
9622
9623         return WERR_OK;
9624 }
9625
9626 /*******************************************************************
9627 *******************************************************************/
9628
9629 struct xcv_api_table xcvlocal_cmds[] = {
9630         { "MonitorUI",  xcvlocal_monitorui },
9631         { NULL,         NULL }
9632 };
9633 #else
9634 struct xcv_api_table xcvlocal_cmds[] = {
9635         { NULL,         NULL }
9636 };
9637 #endif
9638
9639
9640
9641 /*******************************************************************
9642 *******************************************************************/
9643
9644 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9645                                        NT_USER_TOKEN *token, const char *command,
9646                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9647                                        uint32_t *needed)
9648 {
9649         int i;
9650
9651         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9652
9653         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9654                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9655                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9656         }
9657         return WERR_BADFUNC;
9658 }
9659
9660 /****************************************************************
9661  _spoolss_XcvData
9662 ****************************************************************/
9663
9664 WERROR _spoolss_XcvData(pipes_struct *p,
9665                         struct spoolss_XcvData *r)
9666 {
9667         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9668         DATA_BLOB out_data = data_blob_null;
9669         WERROR werror;
9670
9671         if (!Printer) {
9672                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9673                         OUR_HANDLE(r->in.handle)));
9674                 return WERR_BADFID;
9675         }
9676
9677         /* Has to be a handle to the TCP/IP port monitor */
9678
9679         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9680                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9681                 return WERR_BADFID;
9682         }
9683
9684         /* requires administrative access to the server */
9685
9686         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9687                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9688                 return WERR_ACCESS_DENIED;
9689         }
9690
9691         /* Allocate the outgoing buffer */
9692
9693         if (r->in.out_data_size) {
9694                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9695                 if (out_data.data == NULL) {
9696                         return WERR_NOMEM;
9697                 }
9698         }
9699
9700         switch ( Printer->printer_type ) {
9701         case SPLHND_PORTMON_TCP:
9702                 werror = process_xcvtcp_command(p->mem_ctx,
9703                                                 p->server_info->ptok,
9704                                                 r->in.function_name,
9705                                                 &r->in.in_data, &out_data,
9706                                                 r->out.needed);
9707                 break;
9708         case SPLHND_PORTMON_LOCAL:
9709                 werror = process_xcvlocal_command(p->mem_ctx,
9710                                                   p->server_info->ptok,
9711                                                   r->in.function_name,
9712                                                   &r->in.in_data, &out_data,
9713                                                   r->out.needed);
9714                 break;
9715         default:
9716                 werror = WERR_INVALID_PRINT_MONITOR;
9717         }
9718
9719         if (!W_ERROR_IS_OK(werror)) {
9720                 return werror;
9721         }
9722
9723         *r->out.status_code = 0;
9724
9725         memcpy(r->out.out_data, out_data.data, out_data.length);
9726
9727         return WERR_OK;
9728 }
9729
9730 /****************************************************************
9731  _spoolss_AddPrintProcessor
9732 ****************************************************************/
9733
9734 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9735                                   struct spoolss_AddPrintProcessor *r)
9736 {
9737         /* for now, just indicate success and ignore the add.  We'll
9738            automatically set the winprint processor for printer
9739            entries later.  Used to debug the LexMark Optra S 1855 PCL
9740            driver --jerry */
9741
9742         return WERR_OK;
9743 }
9744
9745 /****************************************************************
9746  _spoolss_AddPort
9747 ****************************************************************/
9748
9749 WERROR _spoolss_AddPort(pipes_struct *p,
9750                         struct spoolss_AddPort *r)
9751 {
9752         /* do what w2k3 does */
9753
9754         return WERR_NOT_SUPPORTED;
9755 }
9756
9757 /****************************************************************
9758  _spoolss_GetPrinterDriver
9759 ****************************************************************/
9760
9761 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9762                                  struct spoolss_GetPrinterDriver *r)
9763 {
9764         p->rng_fault_state = true;
9765         return WERR_NOT_SUPPORTED;
9766 }
9767
9768 /****************************************************************
9769  _spoolss_ReadPrinter
9770 ****************************************************************/
9771
9772 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9773                             struct spoolss_ReadPrinter *r)
9774 {
9775         p->rng_fault_state = true;
9776         return WERR_NOT_SUPPORTED;
9777 }
9778
9779 /****************************************************************
9780  _spoolss_WaitForPrinterChange
9781 ****************************************************************/
9782
9783 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9784                                      struct spoolss_WaitForPrinterChange *r)
9785 {
9786         p->rng_fault_state = true;
9787         return WERR_NOT_SUPPORTED;
9788 }
9789
9790 /****************************************************************
9791  _spoolss_ConfigurePort
9792 ****************************************************************/
9793
9794 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9795                               struct spoolss_ConfigurePort *r)
9796 {
9797         p->rng_fault_state = true;
9798         return WERR_NOT_SUPPORTED;
9799 }
9800
9801 /****************************************************************
9802  _spoolss_DeletePort
9803 ****************************************************************/
9804
9805 WERROR _spoolss_DeletePort(pipes_struct *p,
9806                            struct spoolss_DeletePort *r)
9807 {
9808         p->rng_fault_state = true;
9809         return WERR_NOT_SUPPORTED;
9810 }
9811
9812 /****************************************************************
9813  _spoolss_CreatePrinterIC
9814 ****************************************************************/
9815
9816 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9817                                 struct spoolss_CreatePrinterIC *r)
9818 {
9819         p->rng_fault_state = true;
9820         return WERR_NOT_SUPPORTED;
9821 }
9822
9823 /****************************************************************
9824  _spoolss_PlayGDIScriptOnPrinterIC
9825 ****************************************************************/
9826
9827 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9828                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9829 {
9830         p->rng_fault_state = true;
9831         return WERR_NOT_SUPPORTED;
9832 }
9833
9834 /****************************************************************
9835  _spoolss_DeletePrinterIC
9836 ****************************************************************/
9837
9838 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9839                                 struct spoolss_DeletePrinterIC *r)
9840 {
9841         p->rng_fault_state = true;
9842         return WERR_NOT_SUPPORTED;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_AddPrinterConnection
9847 ****************************************************************/
9848
9849 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9850                                      struct spoolss_AddPrinterConnection *r)
9851 {
9852         p->rng_fault_state = true;
9853         return WERR_NOT_SUPPORTED;
9854 }
9855
9856 /****************************************************************
9857  _spoolss_DeletePrinterConnection
9858 ****************************************************************/
9859
9860 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9861                                         struct spoolss_DeletePrinterConnection *r)
9862 {
9863         p->rng_fault_state = true;
9864         return WERR_NOT_SUPPORTED;
9865 }
9866
9867 /****************************************************************
9868  _spoolss_PrinterMessageBox
9869 ****************************************************************/
9870
9871 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9872                                   struct spoolss_PrinterMessageBox *r)
9873 {
9874         p->rng_fault_state = true;
9875         return WERR_NOT_SUPPORTED;
9876 }
9877
9878 /****************************************************************
9879  _spoolss_AddMonitor
9880 ****************************************************************/
9881
9882 WERROR _spoolss_AddMonitor(pipes_struct *p,
9883                            struct spoolss_AddMonitor *r)
9884 {
9885         p->rng_fault_state = true;
9886         return WERR_NOT_SUPPORTED;
9887 }
9888
9889 /****************************************************************
9890  _spoolss_DeleteMonitor
9891 ****************************************************************/
9892
9893 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9894                               struct spoolss_DeleteMonitor *r)
9895 {
9896         p->rng_fault_state = true;
9897         return WERR_NOT_SUPPORTED;
9898 }
9899
9900 /****************************************************************
9901  _spoolss_DeletePrintProcessor
9902 ****************************************************************/
9903
9904 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9905                                      struct spoolss_DeletePrintProcessor *r)
9906 {
9907         p->rng_fault_state = true;
9908         return WERR_NOT_SUPPORTED;
9909 }
9910
9911 /****************************************************************
9912  _spoolss_AddPrintProvidor
9913 ****************************************************************/
9914
9915 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9916                                  struct spoolss_AddPrintProvidor *r)
9917 {
9918         p->rng_fault_state = true;
9919         return WERR_NOT_SUPPORTED;
9920 }
9921
9922 /****************************************************************
9923  _spoolss_DeletePrintProvidor
9924 ****************************************************************/
9925
9926 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9927                                     struct spoolss_DeletePrintProvidor *r)
9928 {
9929         p->rng_fault_state = true;
9930         return WERR_NOT_SUPPORTED;
9931 }
9932
9933 /****************************************************************
9934  _spoolss_FindFirstPrinterChangeNotification
9935 ****************************************************************/
9936
9937 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9938                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9939 {
9940         p->rng_fault_state = true;
9941         return WERR_NOT_SUPPORTED;
9942 }
9943
9944 /****************************************************************
9945  _spoolss_FindNextPrinterChangeNotification
9946 ****************************************************************/
9947
9948 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9949                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9950 {
9951         p->rng_fault_state = true;
9952         return WERR_NOT_SUPPORTED;
9953 }
9954
9955 /****************************************************************
9956  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9957 ****************************************************************/
9958
9959 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9960                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9961 {
9962         p->rng_fault_state = true;
9963         return WERR_NOT_SUPPORTED;
9964 }
9965
9966 /****************************************************************
9967  _spoolss_ReplyOpenPrinter
9968 ****************************************************************/
9969
9970 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9971                                  struct spoolss_ReplyOpenPrinter *r)
9972 {
9973         p->rng_fault_state = true;
9974         return WERR_NOT_SUPPORTED;
9975 }
9976
9977 /****************************************************************
9978  _spoolss_RouterReplyPrinter
9979 ****************************************************************/
9980
9981 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9982                                    struct spoolss_RouterReplyPrinter *r)
9983 {
9984         p->rng_fault_state = true;
9985         return WERR_NOT_SUPPORTED;
9986 }
9987
9988 /****************************************************************
9989  _spoolss_ReplyClosePrinter
9990 ****************************************************************/
9991
9992 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9993                                   struct spoolss_ReplyClosePrinter *r)
9994 {
9995         p->rng_fault_state = true;
9996         return WERR_NOT_SUPPORTED;
9997 }
9998
9999 /****************************************************************
10000  _spoolss_AddPortEx
10001 ****************************************************************/
10002
10003 WERROR _spoolss_AddPortEx(pipes_struct *p,
10004                           struct spoolss_AddPortEx *r)
10005 {
10006         p->rng_fault_state = true;
10007         return WERR_NOT_SUPPORTED;
10008 }
10009
10010 /****************************************************************
10011  _spoolss_RouterFindFirstPrinterChangeNotification
10012 ****************************************************************/
10013
10014 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10015                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10016 {
10017         p->rng_fault_state = true;
10018         return WERR_NOT_SUPPORTED;
10019 }
10020
10021 /****************************************************************
10022  _spoolss_SpoolerInit
10023 ****************************************************************/
10024
10025 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10026                             struct spoolss_SpoolerInit *r)
10027 {
10028         p->rng_fault_state = true;
10029         return WERR_NOT_SUPPORTED;
10030 }
10031
10032 /****************************************************************
10033  _spoolss_ResetPrinterEx
10034 ****************************************************************/
10035
10036 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10037                                struct spoolss_ResetPrinterEx *r)
10038 {
10039         p->rng_fault_state = true;
10040         return WERR_NOT_SUPPORTED;
10041 }
10042
10043 /****************************************************************
10044  _spoolss_RouterReplyPrinterEx
10045 ****************************************************************/
10046
10047 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10048                                      struct spoolss_RouterReplyPrinterEx *r)
10049 {
10050         p->rng_fault_state = true;
10051         return WERR_NOT_SUPPORTED;
10052 }
10053
10054 /****************************************************************
10055  _spoolss_44
10056 ****************************************************************/
10057
10058 WERROR _spoolss_44(pipes_struct *p,
10059                    struct spoolss_44 *r)
10060 {
10061         p->rng_fault_state = true;
10062         return WERR_NOT_SUPPORTED;
10063 }
10064
10065 /****************************************************************
10066  _spoolss_47
10067 ****************************************************************/
10068
10069 WERROR _spoolss_47(pipes_struct *p,
10070                    struct spoolss_47 *r)
10071 {
10072         p->rng_fault_state = true;
10073         return WERR_NOT_SUPPORTED;
10074 }
10075
10076 /****************************************************************
10077  _spoolss_4a
10078 ****************************************************************/
10079
10080 WERROR _spoolss_4a(pipes_struct *p,
10081                    struct spoolss_4a *r)
10082 {
10083         p->rng_fault_state = true;
10084         return WERR_NOT_SUPPORTED;
10085 }
10086
10087 /****************************************************************
10088  _spoolss_4b
10089 ****************************************************************/
10090
10091 WERROR _spoolss_4b(pipes_struct *p,
10092                    struct spoolss_4b *r)
10093 {
10094         p->rng_fault_state = true;
10095         return WERR_NOT_SUPPORTED;
10096 }
10097
10098 /****************************************************************
10099  _spoolss_4c
10100 ****************************************************************/
10101
10102 WERROR _spoolss_4c(pipes_struct *p,
10103                    struct spoolss_4c *r)
10104 {
10105         p->rng_fault_state = true;
10106         return WERR_NOT_SUPPORTED;
10107 }
10108
10109 /****************************************************************
10110  _spoolss_53
10111 ****************************************************************/
10112
10113 WERROR _spoolss_53(pipes_struct *p,
10114                    struct spoolss_53 *r)
10115 {
10116         p->rng_fault_state = true;
10117         return WERR_NOT_SUPPORTED;
10118 }
10119
10120 /****************************************************************
10121  _spoolss_55
10122 ****************************************************************/
10123
10124 WERROR _spoolss_55(pipes_struct *p,
10125                    struct spoolss_55 *r)
10126 {
10127         p->rng_fault_state = true;
10128         return WERR_NOT_SUPPORTED;
10129 }
10130
10131 /****************************************************************
10132  _spoolss_56
10133 ****************************************************************/
10134
10135 WERROR _spoolss_56(pipes_struct *p,
10136                    struct spoolss_56 *r)
10137 {
10138         p->rng_fault_state = true;
10139         return WERR_NOT_SUPPORTED;
10140 }
10141
10142 /****************************************************************
10143  _spoolss_57
10144 ****************************************************************/
10145
10146 WERROR _spoolss_57(pipes_struct *p,
10147                    struct spoolss_57 *r)
10148 {
10149         p->rng_fault_state = true;
10150         return WERR_NOT_SUPPORTED;
10151 }
10152
10153 /****************************************************************
10154  _spoolss_5a
10155 ****************************************************************/
10156
10157 WERROR _spoolss_5a(pipes_struct *p,
10158                    struct spoolss_5a *r)
10159 {
10160         p->rng_fault_state = true;
10161         return WERR_NOT_SUPPORTED;
10162 }
10163
10164 /****************************************************************
10165  _spoolss_5b
10166 ****************************************************************/
10167
10168 WERROR _spoolss_5b(pipes_struct *p,
10169                    struct spoolss_5b *r)
10170 {
10171         p->rng_fault_state = true;
10172         return WERR_NOT_SUPPORTED;
10173 }
10174
10175 /****************************************************************
10176  _spoolss_5c
10177 ****************************************************************/
10178
10179 WERROR _spoolss_5c(pipes_struct *p,
10180                    struct spoolss_5c *r)
10181 {
10182         p->rng_fault_state = true;
10183         return WERR_NOT_SUPPORTED;
10184 }
10185
10186 /****************************************************************
10187  _spoolss_5d
10188 ****************************************************************/
10189
10190 WERROR _spoolss_5d(pipes_struct *p,
10191                    struct spoolss_5d *r)
10192 {
10193         p->rng_fault_state = true;
10194         return WERR_NOT_SUPPORTED;
10195 }
10196
10197 /****************************************************************
10198  _spoolss_5e
10199 ****************************************************************/
10200
10201 WERROR _spoolss_5e(pipes_struct *p,
10202                    struct spoolss_5e *r)
10203 {
10204         p->rng_fault_state = true;
10205         return WERR_NOT_SUPPORTED;
10206 }
10207
10208 /****************************************************************
10209  _spoolss_5f
10210 ****************************************************************/
10211
10212 WERROR _spoolss_5f(pipes_struct *p,
10213                    struct spoolss_5f *r)
10214 {
10215         p->rng_fault_state = true;
10216         return WERR_NOT_SUPPORTED;
10217 }
10218
10219 /****************************************************************
10220  _spoolss_60
10221 ****************************************************************/
10222
10223 WERROR _spoolss_60(pipes_struct *p,
10224                    struct spoolss_60 *r)
10225 {
10226         p->rng_fault_state = true;
10227         return WERR_NOT_SUPPORTED;
10228 }
10229
10230 /****************************************************************
10231  _spoolss_61
10232 ****************************************************************/
10233
10234 WERROR _spoolss_61(pipes_struct *p,
10235                    struct spoolss_61 *r)
10236 {
10237         p->rng_fault_state = true;
10238         return WERR_NOT_SUPPORTED;
10239 }
10240
10241 /****************************************************************
10242  _spoolss_62
10243 ****************************************************************/
10244
10245 WERROR _spoolss_62(pipes_struct *p,
10246                    struct spoolss_62 *r)
10247 {
10248         p->rng_fault_state = true;
10249         return WERR_NOT_SUPPORTED;
10250 }
10251
10252 /****************************************************************
10253  _spoolss_63
10254 ****************************************************************/
10255
10256 WERROR _spoolss_63(pipes_struct *p,
10257                    struct spoolss_63 *r)
10258 {
10259         p->rng_fault_state = true;
10260         return WERR_NOT_SUPPORTED;
10261 }
10262
10263 /****************************************************************
10264  _spoolss_64
10265 ****************************************************************/
10266
10267 WERROR _spoolss_64(pipes_struct *p,
10268                    struct spoolss_64 *r)
10269 {
10270         p->rng_fault_state = true;
10271         return WERR_NOT_SUPPORTED;
10272 }
10273
10274 /****************************************************************
10275  _spoolss_65
10276 ****************************************************************/
10277
10278 WERROR _spoolss_65(pipes_struct *p,
10279                    struct spoolss_65 *r)
10280 {
10281         p->rng_fault_state = true;
10282         return WERR_NOT_SUPPORTED;
10283 }
10284
10285 /****************************************************************
10286  _spoolss_GetCorePrinterDrivers
10287 ****************************************************************/
10288
10289 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
10290                                       struct spoolss_GetCorePrinterDrivers *r)
10291 {
10292         p->rng_fault_state = true;
10293         return WERR_NOT_SUPPORTED;
10294 }
10295
10296 /****************************************************************
10297  _spoolss_67
10298 ****************************************************************/
10299
10300 WERROR _spoolss_67(pipes_struct *p,
10301                    struct spoolss_67 *r)
10302 {
10303         p->rng_fault_state = true;
10304         return WERR_NOT_SUPPORTED;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_GetPrinterDriverPackagePath
10309 ****************************************************************/
10310
10311 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10312                                             struct spoolss_GetPrinterDriverPackagePath *r)
10313 {
10314         p->rng_fault_state = true;
10315         return WERR_NOT_SUPPORTED;
10316 }
10317
10318 /****************************************************************
10319  _spoolss_69
10320 ****************************************************************/
10321
10322 WERROR _spoolss_69(pipes_struct *p,
10323                    struct spoolss_69 *r)
10324 {
10325         p->rng_fault_state = true;
10326         return WERR_NOT_SUPPORTED;
10327 }
10328
10329 /****************************************************************
10330  _spoolss_6a
10331 ****************************************************************/
10332
10333 WERROR _spoolss_6a(pipes_struct *p,
10334                    struct spoolss_6a *r)
10335 {
10336         p->rng_fault_state = true;
10337         return WERR_NOT_SUPPORTED;
10338 }
10339
10340 /****************************************************************
10341  _spoolss_6b
10342 ****************************************************************/
10343
10344 WERROR _spoolss_6b(pipes_struct *p,
10345                    struct spoolss_6b *r)
10346 {
10347         p->rng_fault_state = true;
10348         return WERR_NOT_SUPPORTED;
10349 }
10350
10351 /****************************************************************
10352  _spoolss_6c
10353 ****************************************************************/
10354
10355 WERROR _spoolss_6c(pipes_struct *p,
10356                    struct spoolss_6c *r)
10357 {
10358         p->rng_fault_state = true;
10359         return WERR_NOT_SUPPORTED;
10360 }
10361
10362 /****************************************************************
10363  _spoolss_6d
10364 ****************************************************************/
10365
10366 WERROR _spoolss_6d(pipes_struct *p,
10367                    struct spoolss_6d *r)
10368 {
10369         p->rng_fault_state = true;
10370         return WERR_NOT_SUPPORTED;
10371 }