s3-spoolss: remove unused get_printer_dataex().
[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  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 3 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
23  */
24
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26    up, all the errors returned are DOS errors, not NT status codes. */
27
28 #include "includes.h"
29
30 /* macros stolen from s4 spoolss server */
31 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
32         ((info)?ndr_size_##fn(info, level, ic, 0):0)
33
34 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
35         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
36
37 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
38
39
40 extern userdom_struct current_user_info;
41
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_RPC_SRV
44
45 #ifndef MAX_OPEN_PRINTER_EXS
46 #define MAX_OPEN_PRINTER_EXS 50
47 #endif
48
49 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
50 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
51
52 struct table_node {
53         const char    *long_archi;
54         const char    *short_archi;
55         int     version;
56 };
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 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 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, POLICY_HND *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, POLICY_HND *hnd)
231 {
232         Printer_entry *find_printer = NULL;
233
234         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
235                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
236                 return NULL;
237         }
238
239         return find_printer;
240 }
241
242 /****************************************************************************
243  Close printer index by handle.
244 ****************************************************************************/
245
246 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
247 {
248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
249
250         if (!Printer) {
251                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
252                 return False;
253         }
254
255         close_policy_hnd(p, hnd);
256
257         return True;
258 }
259
260 /****************************************************************************
261  Delete a printer given a handle.
262 ****************************************************************************/
263
264 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
265 {
266         char *cmd = lp_deleteprinter_cmd();
267         char *command = NULL;
268         int ret;
269         SE_PRIV se_printop = SE_PRINT_OPERATOR;
270         bool is_print_op = False;
271
272         /* can't fail if we don't try */
273
274         if ( !*cmd )
275                 return WERR_OK;
276
277         command = talloc_asprintf(ctx,
278                         "%s \"%s\"",
279                         cmd, sharename);
280         if (!command) {
281                 return WERR_NOMEM;
282         }
283         if ( token )
284                 is_print_op = user_has_privileges( token, &se_printop );
285
286         DEBUG(10,("Running [%s]\n", command));
287
288         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
289
290         if ( is_print_op )
291                 become_root();
292
293         if ( (ret = smbrun(command, NULL)) == 0 ) {
294                 /* Tell everyone we updated smb.conf. */
295                 message_send_all(smbd_messaging_context(),
296                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
297         }
298
299         if ( is_print_op )
300                 unbecome_root();
301
302         /********** END SePrintOperatorPrivlege BLOCK **********/
303
304         DEBUGADD(10,("returned [%d]\n", ret));
305
306         TALLOC_FREE(command);
307
308         if (ret != 0)
309                 return WERR_BADFID; /* What to return here? */
310
311         /* go ahead and re-read the services immediately */
312         reload_services( False );
313
314         if ( lp_servicenumber( sharename )  < 0 )
315                 return WERR_ACCESS_DENIED;
316
317         return WERR_OK;
318 }
319
320 /****************************************************************************
321  Delete a printer given a handle.
322 ****************************************************************************/
323
324 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
325 {
326         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
327
328         if (!Printer) {
329                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
330                 return WERR_BADFID;
331         }
332
333         /*
334          * It turns out that Windows allows delete printer on a handle
335          * opened by an admin user, then used on a pipe handle created
336          * by an anonymous user..... but they're working on security.... riiight !
337          * JRA.
338          */
339
340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
341                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
342                 return WERR_ACCESS_DENIED;
343         }
344
345         /* this does not need a become root since the access check has been
346            done on the handle already */
347
348         if (del_a_printer( Printer->sharename ) != 0) {
349                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
350                 return WERR_BADFID;
351         }
352
353         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
354                                    Printer->sharename );
355 }
356
357 /****************************************************************************
358  Return the snum of a printer corresponding to an handle.
359 ****************************************************************************/
360
361 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
362                              struct share_params **params)
363 {
364         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
368                 return False;
369         }
370
371         switch (Printer->printer_type) {
372                 case SPLHND_PRINTER:
373                         DEBUG(4,("short name:%s\n", Printer->sharename));
374                         *number = print_queue_snum(Printer->sharename);
375                         return (*number != -1);
376                 case SPLHND_SERVER:
377                         return False;
378                 default:
379                         return False;
380         }
381 }
382
383 /****************************************************************************
384  Set printer handle type.
385  Check if it's \\server or \\server\printer
386 ****************************************************************************/
387
388 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
389 {
390         DEBUG(3,("Setting printer type=%s\n", handlename));
391
392         if ( strlen(handlename) < 3 ) {
393                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
394                 return False;
395         }
396
397         /* it's a print server */
398         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
399                 DEBUGADD(4,("Printer is a print server\n"));
400                 Printer->printer_type = SPLHND_SERVER;
401         }
402         /* it's a printer (set_printer_hnd_name() will handle port monitors */
403         else {
404                 DEBUGADD(4,("Printer is a printer\n"));
405                 Printer->printer_type = SPLHND_PRINTER;
406         }
407
408         return True;
409 }
410
411 /****************************************************************************
412  Set printer handle name..  Accept names like \\server, \\server\printer,
413  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
414  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
415  XcvDataPort() interface.
416 ****************************************************************************/
417
418 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
419 {
420         int snum;
421         int n_services=lp_numservices();
422         char *aprinter, *printername;
423         const char *servername;
424         fstring sname;
425         bool found=False;
426         NT_PRINTER_INFO_LEVEL *printer = NULL;
427         WERROR result;
428
429         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
430
431         aprinter = handlename;
432         if ( *handlename == '\\' ) {
433                 servername = canon_servername(handlename);
434                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
435                         *aprinter = '\0';
436                         aprinter++;
437                 }
438         } else {
439                 servername = "";
440         }
441
442         /* save the servername to fill in replies on this handle */
443
444         if ( !is_myname_or_ipaddr( servername ) )
445                 return False;
446
447         fstrcpy( Printer->servername, servername );
448
449         if ( Printer->printer_type == SPLHND_SERVER )
450                 return True;
451
452         if ( Printer->printer_type != SPLHND_PRINTER )
453                 return False;
454
455         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
456
457         /* check for the Port Monitor Interface */
458
459         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
460                 Printer->printer_type = SPLHND_PORTMON_TCP;
461                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
462                 found = True;
463         }
464         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
465                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
466                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
467                 found = True;
468         }
469
470         /* Search all sharenames first as this is easier than pulling
471            the printer_info_2 off of disk. Don't use find_service() since
472            that calls out to map_username() */
473
474         /* do another loop to look for printernames */
475
476         for (snum=0; !found && snum<n_services; snum++) {
477
478                 /* no point going on if this is not a printer */
479
480                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
481                         continue;
482
483                 fstrcpy(sname, lp_servicename(snum));
484                 if ( strequal( aprinter, sname ) ) {
485                         found = True;
486                         break;
487                 }
488
489                 /* no point looking up the printer object if
490                    we aren't allowing printername != sharename */
491
492                 if ( lp_force_printername(snum) )
493                         continue;
494
495                 fstrcpy(sname, lp_servicename(snum));
496
497                 printer = NULL;
498
499                 /* This call doesn't fill in the location or comment from
500                  * a CUPS server for efficiency with large numbers of printers.
501                  * JRA.
502                  */
503
504                 result = get_a_printer_search( NULL, &printer, 2, sname );
505                 if ( !W_ERROR_IS_OK(result) ) {
506                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
507                                 sname, win_errstr(result)));
508                         continue;
509                 }
510
511                 /* printername is always returned as \\server\printername */
512                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
513                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
514                                 printer->info_2->printername));
515                         free_a_printer( &printer, 2);
516                         continue;
517                 }
518
519                 printername++;
520
521                 if ( strequal(printername, aprinter) ) {
522                         free_a_printer( &printer, 2);
523                         found = True;
524                         break;
525                 }
526
527                 DEBUGADD(10, ("printername: %s\n", printername));
528
529                 free_a_printer( &printer, 2);
530         }
531
532         free_a_printer( &printer, 2);
533
534         if ( !found ) {
535                 DEBUGADD(4,("Printer not found\n"));
536                 return False;
537         }
538
539         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
540
541         fstrcpy(Printer->sharename, sname);
542
543         return True;
544 }
545
546 /****************************************************************************
547  Find first available printer slot. creates a printer handle for you.
548  ****************************************************************************/
549
550 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
551 {
552         Printer_entry *new_printer;
553
554         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
555
556         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
557         if (new_printer == NULL) {
558                 return false;
559         }
560         talloc_set_destructor(new_printer, printer_entry_destructor);
561
562         if (!create_policy_hnd(p, hnd, new_printer)) {
563                 TALLOC_FREE(new_printer);
564                 return False;
565         }
566
567         /* Add to the internal list. */
568         DLIST_ADD(printers_list, new_printer);
569
570         new_printer->notify.option=NULL;
571
572         if (!set_printer_hnd_printertype(new_printer, name)) {
573                 close_printer_handle(p, hnd);
574                 return False;
575         }
576
577         if (!set_printer_hnd_name(new_printer, name)) {
578                 close_printer_handle(p, hnd);
579                 return False;
580         }
581
582         new_printer->access_granted = access_granted;
583
584         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
585
586         return True;
587 }
588
589 /***************************************************************************
590  check to see if the client motify handle is monitoring the notification
591  given by (notify_type, notify_field).
592  **************************************************************************/
593
594 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
595                                       uint16 notify_field)
596 {
597         return True;
598 }
599
600 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
601                                 uint16 notify_field)
602 {
603         struct spoolss_NotifyOption *option = p->notify.option;
604         uint32 i, j;
605
606         /*
607          * Flags should always be zero when the change notify
608          * is registered by the client's spooler.  A user Win32 app
609          * might use the flags though instead of the NOTIFY_OPTION_INFO
610          * --jerry
611          */
612
613         if (!option) {
614                 return False;
615         }
616
617         if (p->notify.flags)
618                 return is_monitoring_event_flags(
619                         p->notify.flags, notify_type, notify_field);
620
621         for (i = 0; i < option->count; i++) {
622
623                 /* Check match for notify_type */
624
625                 if (option->types[i].type != notify_type)
626                         continue;
627
628                 /* Check match for field */
629
630                 for (j = 0; j < option->types[i].count; j++) {
631                         if (option->types[i].fields[j] == notify_field) {
632                                 return True;
633                         }
634                 }
635         }
636
637         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
638                    p->servername, p->sharename, notify_type, notify_field));
639
640         return False;
641 }
642
643 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
644         _data->data.integer[0] = _integer; \
645         _data->data.integer[1] = 0;
646
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
649         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
650         if (!_data->data.string.string) {\
651                 _data->data.string.size = 0; \
652         } \
653         _data->data.string.size = strlen_m_term(_p) * 2;
654
655 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
656         _data->data.devmode.devmode = _devmode;
657
658 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
659         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
660         if (!_data->data.sd.sd) { \
661                 _data->data.sd.sd_size = 0; \
662         } \
663         _data->data.sd.sd_size = _size;
664
665 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
666                                    struct tm *t,
667                                    const char **pp,
668                                    uint32_t *plen)
669 {
670         struct spoolss_Time st;
671         uint32_t len = 16;
672         char *p;
673
674         if (!init_systemtime(&st, t)) {
675                 return;
676         }
677
678         p = talloc_array(mem_ctx, char, len);
679         if (!p) {
680                 return;
681         }
682
683         /*
684          * Systemtime must be linearized as a set of UINT16's.
685          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
686          */
687
688         SSVAL(p, 0, st.year);
689         SSVAL(p, 2, st.month);
690         SSVAL(p, 4, st.day_of_week);
691         SSVAL(p, 6, st.day);
692         SSVAL(p, 8, st.hour);
693         SSVAL(p, 10, st.minute);
694         SSVAL(p, 12, st.second);
695         SSVAL(p, 14, st.millisecond);
696
697         *pp = p;
698         *plen = len;
699 }
700
701 /* Convert a notification message to a struct spoolss_Notify */
702
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704                              struct spoolss_Notify *data,
705                              TALLOC_CTX *mem_ctx)
706 {
707         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
708 }
709
710 static void notify_string(struct spoolss_notify_msg *msg,
711                           struct spoolss_Notify *data,
712                           TALLOC_CTX *mem_ctx)
713 {
714         /* The length of the message includes the trailing \0 */
715
716         data->data.string.size = msg->len * 2;
717         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
718         if (!data->data.string.string) {
719                 data->data.string.size = 0;
720                 return;
721         }
722 }
723
724 static void notify_system_time(struct spoolss_notify_msg *msg,
725                                struct spoolss_Notify *data,
726                                TALLOC_CTX *mem_ctx)
727 {
728         data->data.string.string = NULL;
729         data->data.string.size = 0;
730
731         if (msg->len != sizeof(time_t)) {
732                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
733                           msg->len));
734                 return;
735         }
736
737         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
738                                &data->data.string.string,
739                                &data->data.string.size);
740 }
741
742 struct notify2_message_table {
743         const char *name;
744         void (*fn)(struct spoolss_notify_msg *msg,
745                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
746 };
747
748 static struct notify2_message_table printer_notify_table[] = {
749         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
750         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
751         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
752         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
753         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
754         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
755         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
756         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
757         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
758         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
759         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
760         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
761         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
762         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
763         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
764         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
765         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
766         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
767         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
768 };
769
770 static struct notify2_message_table job_notify_table[] = {
771         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
772         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
773         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
774         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
775         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
776         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
777         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
778         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
779         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
780         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
781         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
782         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
783         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
784         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
785         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
786         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
787         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
788         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
789         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
790         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
791         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
792         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
793         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
794         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
795 };
796
797
798 /***********************************************************************
799  Allocate talloc context for container object
800  **********************************************************************/
801
802 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
803 {
804         if ( !ctr )
805                 return;
806
807         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
808
809         return;
810 }
811
812 /***********************************************************************
813  release all allocated memory and zero out structure
814  **********************************************************************/
815
816 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
817 {
818         if ( !ctr )
819                 return;
820
821         if ( ctr->ctx )
822                 talloc_destroy(ctr->ctx);
823
824         ZERO_STRUCTP(ctr);
825
826         return;
827 }
828
829 /***********************************************************************
830  **********************************************************************/
831
832 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
833 {
834         if ( !ctr )
835                 return NULL;
836
837         return ctr->ctx;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
844 {
845         if ( !ctr || !ctr->msg_groups )
846                 return NULL;
847
848         if ( idx >= ctr->num_groups )
849                 return NULL;
850
851         return &ctr->msg_groups[idx];
852
853 }
854
855 /***********************************************************************
856  How many groups of change messages do we have ?
857  **********************************************************************/
858
859 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
860 {
861         if ( !ctr )
862                 return 0;
863
864         return ctr->num_groups;
865 }
866
867 /***********************************************************************
868  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
869  **********************************************************************/
870
871 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
872 {
873         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
874         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
875         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
876         int                             i, new_slot;
877
878         if ( !ctr || !msg )
879                 return 0;
880
881         /* loop over all groups looking for a matching printer name */
882
883         for ( i=0; i<ctr->num_groups; i++ ) {
884                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
885                         break;
886         }
887
888         /* add a new group? */
889
890         if ( i == ctr->num_groups ) {
891                 ctr->num_groups++;
892
893                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
894                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895                         return 0;
896                 }
897                 ctr->msg_groups = groups;
898
899                 /* clear the new entry and set the printer name */
900
901                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
902                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
903         }
904
905         /* add the change messages; 'i' is the correct index now regardless */
906
907         msg_grp = &ctr->msg_groups[i];
908
909         msg_grp->num_msgs++;
910
911         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
912                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
913                 return 0;
914         }
915         msg_grp->msgs = msg_list;
916
917         new_slot = msg_grp->num_msgs-1;
918         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
919
920         /* need to allocate own copy of data */
921
922         if ( msg->len != 0 )
923                 msg_grp->msgs[new_slot].notify.data = (char *)
924                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
925
926         return ctr->num_groups;
927 }
928
929 /***********************************************************************
930  Send a change notication message on all handles which have a call
931  back registered
932  **********************************************************************/
933
934 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
935 {
936         Printer_entry            *p;
937         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
938         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
939         SPOOLSS_NOTIFY_MSG       *messages;
940         int                      sending_msg_count;
941
942         if ( !msg_group ) {
943                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944                 return;
945         }
946
947         messages = msg_group->msgs;
948
949         if ( !messages ) {
950                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951                 return;
952         }
953
954         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
955
956         /* loop over all printers */
957
958         for (p = printers_list; p; p = p->next) {
959                 struct spoolss_Notify *notifies;
960                 uint32_t count = 0;
961                 uint32_t id;
962                 int     i;
963
964                 /* Is there notification on this handle? */
965
966                 if ( !p->notify.client_connected )
967                         continue;
968
969                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
970
971                 /* For this printer?  Print servers always receive
972                    notifications. */
973
974                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
975                     ( !strequal(msg_group->printername, p->sharename) ) )
976                         continue;
977
978                 DEBUG(10,("Our printer\n"));
979
980                 /* allocate the max entries possible */
981
982                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
983                 if (!notifies) {
984                         return;
985                 }
986
987                 /* build the array of change notifications */
988
989                 sending_msg_count = 0;
990
991                 for ( i=0; i<msg_group->num_msgs; i++ ) {
992                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
993
994                         /* Are we monitoring this event? */
995
996                         if (!is_monitoring_event(p, msg->type, msg->field))
997                                 continue;
998
999                         sending_msg_count++;
1000
1001
1002                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1003                                 msg->type, msg->field, p->sharename));
1004
1005                         /*
1006                          * if the is a printer notification handle and not a job notification
1007                          * type, then set the id to 0.  Other wise just use what was specified
1008                          * in the message.
1009                          *
1010                          * When registering change notification on a print server handle
1011                          * we always need to send back the id (snum) matching the printer
1012                          * for which the change took place.  For change notify registered
1013                          * on a printer handle, this does not matter and the id should be 0.
1014                          *
1015                          * --jerry
1016                          */
1017
1018                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1019                                 id = 0;
1020                         else
1021                                 id = msg->id;
1022
1023
1024                         /* Convert unix jobid to smb jobid */
1025
1026                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1027                                 id = sysjob_to_jobid(msg->id);
1028
1029                                 if (id == -1) {
1030                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1031                                         goto done;
1032                                 }
1033                         }
1034
1035                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1036
1037                         switch(msg->type) {
1038                         case PRINTER_NOTIFY_TYPE:
1039                                 if ( printer_notify_table[msg->field].fn )
1040                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1041                                 break;
1042
1043                         case JOB_NOTIFY_TYPE:
1044                                 if ( job_notify_table[msg->field].fn )
1045                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1046                                 break;
1047
1048                         default:
1049                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1050                                 goto done;
1051                         }
1052
1053                         count++;
1054                 }
1055
1056                 if ( sending_msg_count ) {
1057                         NTSTATUS status;
1058                         WERROR werr;
1059                         union spoolss_ReplyPrinterInfo info;
1060                         struct spoolss_NotifyInfo info0;
1061                         uint32_t reply_result;
1062
1063                         info0.version   = 0x2;
1064                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1065                         info0.count     = count;
1066                         info0.notifies  = notifies;
1067
1068                         info.info0 = &info0;
1069
1070                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1071                                                                      &p->notify.client_hnd,
1072                                                                      p->notify.change, /* color */
1073                                                                      p->notify.flags,
1074                                                                      &reply_result,
1075                                                                      0, /* reply_type, must be 0 */
1076                                                                      info,
1077                                                                      &werr);
1078                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1079                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1080                                         notify_cli_pipe->srv_name_slash,
1081                                         win_errstr(werr)));
1082                         }
1083                         switch (reply_result) {
1084                                 case 0:
1085                                         break;
1086                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1087                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1088                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1089                                         break;
1090                                 default:
1091                                         break;
1092                         }
1093                 }
1094         }
1095
1096 done:
1097         DEBUG(8,("send_notify2_changes: Exit...\n"));
1098         return;
1099 }
1100
1101 /***********************************************************************
1102  **********************************************************************/
1103
1104 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1105 {
1106
1107         uint32 tv_sec, tv_usec;
1108         size_t offset = 0;
1109
1110         /* Unpack message */
1111
1112         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1113                              msg->printer);
1114
1115         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1116                                 &tv_sec, &tv_usec,
1117                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1118
1119         if (msg->len == 0)
1120                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1121                            &msg->notify.value[0], &msg->notify.value[1]);
1122         else
1123                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1124                            &msg->len, &msg->notify.data);
1125
1126         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1127                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1128
1129         tv->tv_sec = tv_sec;
1130         tv->tv_usec = tv_usec;
1131
1132         if (msg->len == 0)
1133                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1134                           msg->notify.value[1]));
1135         else
1136                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1137
1138         return True;
1139 }
1140
1141 /********************************************************************
1142  Receive a notify2 message list
1143  ********************************************************************/
1144
1145 static void receive_notify2_message_list(struct messaging_context *msg,
1146                                          void *private_data,
1147                                          uint32_t msg_type,
1148                                          struct server_id server_id,
1149                                          DATA_BLOB *data)
1150 {
1151         size_t                  msg_count, i;
1152         char                    *buf = (char *)data->data;
1153         char                    *msg_ptr;
1154         size_t                  msg_len;
1155         SPOOLSS_NOTIFY_MSG      notify;
1156         SPOOLSS_NOTIFY_MSG_CTR  messages;
1157         int                     num_groups;
1158
1159         if (data->length < 4) {
1160                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1161                 return;
1162         }
1163
1164         msg_count = IVAL(buf, 0);
1165         msg_ptr = buf + 4;
1166
1167         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1168
1169         if (msg_count == 0) {
1170                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1171                 return;
1172         }
1173
1174         /* initialize the container */
1175
1176         ZERO_STRUCT( messages );
1177         notify_msg_ctr_init( &messages );
1178
1179         /*
1180          * build message groups for each printer identified
1181          * in a change_notify msg.  Remember that a PCN message
1182          * includes the handle returned for the srv_spoolss_replyopenprinter()
1183          * call.  Therefore messages are grouped according to printer handle.
1184          */
1185
1186         for ( i=0; i<msg_count; i++ ) {
1187                 struct timeval msg_tv;
1188
1189                 if (msg_ptr + 4 - buf > data->length) {
1190                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1191                         return;
1192                 }
1193
1194                 msg_len = IVAL(msg_ptr,0);
1195                 msg_ptr += 4;
1196
1197                 if (msg_ptr + msg_len - buf > data->length) {
1198                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1199                         return;
1200                 }
1201
1202                 /* unpack messages */
1203
1204                 ZERO_STRUCT( notify );
1205                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1206                 msg_ptr += msg_len;
1207
1208                 /* add to correct list in container */
1209
1210                 notify_msg_ctr_addmsg( &messages, &notify );
1211
1212                 /* free memory that might have been allocated by notify2_unpack_msg() */
1213
1214                 if ( notify.len != 0 )
1215                         SAFE_FREE( notify.notify.data );
1216         }
1217
1218         /* process each group of messages */
1219
1220         num_groups = notify_msg_ctr_numgroups( &messages );
1221         for ( i=0; i<num_groups; i++ )
1222                 send_notify2_changes( &messages, i );
1223
1224
1225         /* cleanup */
1226
1227         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1228
1229         notify_msg_ctr_destroy( &messages );
1230
1231         return;
1232 }
1233
1234 /********************************************************************
1235  Send a message to ourself about new driver being installed
1236  so we can upgrade the information for each printer bound to this
1237  driver
1238  ********************************************************************/
1239
1240 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1241 {
1242         int len = strlen(drivername);
1243
1244         if (!len)
1245                 return False;
1246
1247         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1248                 drivername));
1249
1250         messaging_send_buf(smbd_messaging_context(), procid_self(),
1251                            MSG_PRINTER_DRVUPGRADE,
1252                            (uint8 *)drivername, len+1);
1253
1254         return True;
1255 }
1256
1257 /**********************************************************************
1258  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1259  over all printers, upgrading ones as necessary
1260  **********************************************************************/
1261
1262 void do_drv_upgrade_printer(struct messaging_context *msg,
1263                             void *private_data,
1264                             uint32_t msg_type,
1265                             struct server_id server_id,
1266                             DATA_BLOB *data)
1267 {
1268         fstring drivername;
1269         int snum;
1270         int n_services = lp_numservices();
1271         size_t len;
1272
1273         len = MIN(data->length,sizeof(drivername)-1);
1274         strncpy(drivername, (const char *)data->data, len);
1275
1276         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1277
1278         /* Iterate the printer list */
1279
1280         for (snum=0; snum<n_services; snum++)
1281         {
1282                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1283                 {
1284                         WERROR result;
1285                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1286
1287                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1288                         if (!W_ERROR_IS_OK(result))
1289                                 continue;
1290
1291                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1292                         {
1293                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1294
1295                                 /* all we care about currently is the change_id */
1296
1297                                 result = mod_a_printer(printer, 2);
1298                                 if (!W_ERROR_IS_OK(result)) {
1299                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1300                                                 win_errstr(result)));
1301                                 }
1302                         }
1303
1304                         free_a_printer(&printer, 2);
1305                 }
1306         }
1307
1308         /* all done */
1309 }
1310
1311 /********************************************************************
1312  Update the cache for all printq's with a registered client
1313  connection
1314  ********************************************************************/
1315
1316 void update_monitored_printq_cache( void )
1317 {
1318         Printer_entry *printer = printers_list;
1319         int snum;
1320
1321         /* loop through all printers and update the cache where
1322            client_connected == True */
1323         while ( printer )
1324         {
1325                 if ( (printer->printer_type == SPLHND_PRINTER)
1326                         && printer->notify.client_connected )
1327                 {
1328                         snum = print_queue_snum(printer->sharename);
1329                         print_queue_status( snum, NULL, NULL );
1330                 }
1331
1332                 printer = printer->next;
1333         }
1334
1335         return;
1336 }
1337 /********************************************************************
1338  Send a message to ourself about new driver being installed
1339  so we can upgrade the information for each printer bound to this
1340  driver
1341  ********************************************************************/
1342
1343 static bool srv_spoolss_reset_printerdata(char* drivername)
1344 {
1345         int len = strlen(drivername);
1346
1347         if (!len)
1348                 return False;
1349
1350         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1351                 drivername));
1352
1353         messaging_send_buf(smbd_messaging_context(), procid_self(),
1354                            MSG_PRINTERDATA_INIT_RESET,
1355                            (uint8 *)drivername, len+1);
1356
1357         return True;
1358 }
1359
1360 /**********************************************************************
1361  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1362  over all printers, resetting printer data as neessary
1363  **********************************************************************/
1364
1365 void reset_all_printerdata(struct messaging_context *msg,
1366                            void *private_data,
1367                            uint32_t msg_type,
1368                            struct server_id server_id,
1369                            DATA_BLOB *data)
1370 {
1371         fstring drivername;
1372         int snum;
1373         int n_services = lp_numservices();
1374         size_t len;
1375
1376         len = MIN( data->length, sizeof(drivername)-1 );
1377         strncpy( drivername, (const char *)data->data, len );
1378
1379         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1380
1381         /* Iterate the printer list */
1382
1383         for ( snum=0; snum<n_services; snum++ )
1384         {
1385                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1386                 {
1387                         WERROR result;
1388                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1389
1390                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1391                         if ( !W_ERROR_IS_OK(result) )
1392                                 continue;
1393
1394                         /*
1395                          * if the printer is bound to the driver,
1396                          * then reset to the new driver initdata
1397                          */
1398
1399                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1400                         {
1401                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1402
1403                                 if ( !set_driver_init(printer, 2) ) {
1404                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1405                                                 printer->info_2->printername, printer->info_2->drivername));
1406                                 }
1407
1408                                 result = mod_a_printer( printer, 2 );
1409                                 if ( !W_ERROR_IS_OK(result) ) {
1410                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1411                                                 get_dos_error_msg(result)));
1412                                 }
1413                         }
1414
1415                         free_a_printer( &printer, 2 );
1416                 }
1417         }
1418
1419         /* all done */
1420
1421         return;
1422 }
1423
1424 /****************************************************************
1425  _spoolss_OpenPrinter
1426 ****************************************************************/
1427
1428 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1429                             struct spoolss_OpenPrinter *r)
1430 {
1431         struct spoolss_OpenPrinterEx e;
1432         WERROR werr;
1433
1434         ZERO_STRUCT(e.in.userlevel);
1435
1436         e.in.printername        = r->in.printername;
1437         e.in.datatype           = r->in.datatype;
1438         e.in.devmode_ctr        = r->in.devmode_ctr;
1439         e.in.access_mask        = r->in.access_mask;
1440         e.in.level              = 0;
1441
1442         e.out.handle            = r->out.handle;
1443
1444         werr = _spoolss_OpenPrinterEx(p, &e);
1445
1446         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1447                 /* OpenPrinterEx returns this for a bad
1448                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1449                  * instead.
1450                  */
1451                 werr = WERR_INVALID_PRINTER_NAME;
1452         }
1453
1454         return werr;
1455 }
1456
1457 /********************************************************************
1458  FIXME: temporary convert_devicemode_new function
1459  ********************************************************************/
1460
1461 static bool convert_devicemode_new(const char *printername,
1462                                    struct spoolss_DeviceMode *devmode,
1463                                    NT_DEVICEMODE **pp_nt_devmode)
1464 {
1465         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1466
1467         /*
1468          * Ensure nt_devmode is a valid pointer
1469          * as we will be overwriting it.
1470          */
1471
1472         if (nt_devmode == NULL) {
1473                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1474                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1475                         return false;
1476         }
1477
1478         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1479         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1480
1481         nt_devmode->specversion         = devmode->specversion;
1482         nt_devmode->driverversion       = devmode->driverversion;
1483         nt_devmode->size                = devmode->size;
1484         nt_devmode->fields              = devmode->fields;
1485         nt_devmode->orientation         = devmode->orientation;
1486         nt_devmode->papersize           = devmode->papersize;
1487         nt_devmode->paperlength         = devmode->paperlength;
1488         nt_devmode->paperwidth          = devmode->paperwidth;
1489         nt_devmode->scale               = devmode->scale;
1490         nt_devmode->copies              = devmode->copies;
1491         nt_devmode->defaultsource       = devmode->defaultsource;
1492         nt_devmode->printquality        = devmode->printquality;
1493         nt_devmode->color               = devmode->color;
1494         nt_devmode->duplex              = devmode->duplex;
1495         nt_devmode->yresolution         = devmode->yresolution;
1496         nt_devmode->ttoption            = devmode->ttoption;
1497         nt_devmode->collate             = devmode->collate;
1498
1499         nt_devmode->logpixels           = devmode->logpixels;
1500         nt_devmode->bitsperpel          = devmode->bitsperpel;
1501         nt_devmode->pelswidth           = devmode->pelswidth;
1502         nt_devmode->pelsheight          = devmode->pelsheight;
1503         nt_devmode->displayflags        = devmode->displayflags;
1504         nt_devmode->displayfrequency    = devmode->displayfrequency;
1505         nt_devmode->icmmethod           = devmode->icmmethod;
1506         nt_devmode->icmintent           = devmode->icmintent;
1507         nt_devmode->mediatype           = devmode->mediatype;
1508         nt_devmode->dithertype          = devmode->dithertype;
1509         nt_devmode->reserved1           = devmode->reserved1;
1510         nt_devmode->reserved2           = devmode->reserved2;
1511         nt_devmode->panningwidth        = devmode->panningwidth;
1512         nt_devmode->panningheight       = devmode->panningheight;
1513
1514         /*
1515          * Only change private and driverextra if the incoming devmode
1516          * has a new one. JRA.
1517          */
1518
1519         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1520                 SAFE_FREE(nt_devmode->nt_dev_private);
1521                 nt_devmode->driverextra = devmode->__driverextra_length;
1522                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1523                         return false;
1524                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1525         }
1526
1527         *pp_nt_devmode = nt_devmode;
1528
1529         return true;
1530 }
1531
1532 /****************************************************************
1533  _spoolss_OpenPrinterEx
1534 ****************************************************************/
1535
1536 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1537                               struct spoolss_OpenPrinterEx *r)
1538 {
1539         POLICY_HND              *handle = r->out.handle;
1540         char *name = CONST_DISCARD(char *, r->in.printername);
1541         int snum;
1542         Printer_entry *Printer=NULL;
1543
1544         if (!name) {
1545                 return WERR_INVALID_PARAM;
1546         }
1547
1548         /* some sanity check because you can open a printer or a print server */
1549         /* aka: \\server\printer or \\server */
1550
1551         DEBUGADD(3,("checking name: %s\n",name));
1552
1553         if (!open_printer_hnd(p, handle, name, 0)) {
1554                 ZERO_STRUCTP(r->out.handle);
1555                 return WERR_INVALID_PARAM;
1556         }
1557
1558         Printer=find_printer_index_by_hnd(p, handle);
1559         if ( !Printer ) {
1560                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1561                         "handle we created for printer %s\n", name ));
1562                 close_printer_handle(p,handle);
1563                 ZERO_STRUCTP(r->out.handle);
1564                 return WERR_INVALID_PARAM;
1565         }
1566
1567         /*
1568          * First case: the user is opening the print server:
1569          *
1570          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1571          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1572          *
1573          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1574          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1575          * or if the user is listed in the smb.conf printer admin parameter.
1576          *
1577          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1578          * client view printer folder, but does not show the MSAPW.
1579          *
1580          * Note: this test needs code to check access rights here too. Jeremy
1581          * could you look at this?
1582          *
1583          * Second case: the user is opening a printer:
1584          * NT doesn't let us connect to a printer if the connecting user
1585          * doesn't have print permission.
1586          *
1587          * Third case: user is opening a Port Monitor
1588          * access checks same as opening a handle to the print server.
1589          */
1590
1591         switch (Printer->printer_type )
1592         {
1593         case SPLHND_SERVER:
1594         case SPLHND_PORTMON_TCP:
1595         case SPLHND_PORTMON_LOCAL:
1596                 /* Printserver handles use global struct... */
1597
1598                 snum = -1;
1599
1600                 /* Map standard access rights to object specific access rights */
1601
1602                 se_map_standard(&r->in.access_mask,
1603                                 &printserver_std_mapping);
1604
1605                 /* Deny any object specific bits that don't apply to print
1606                    servers (i.e printer and job specific bits) */
1607
1608                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1609
1610                 if (r->in.access_mask &
1611                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1612                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1613                         close_printer_handle(p, handle);
1614                         ZERO_STRUCTP(r->out.handle);
1615                         return WERR_ACCESS_DENIED;
1616                 }
1617
1618                 /* Allow admin access */
1619
1620                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1621                 {
1622                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1623
1624                         if (!lp_ms_add_printer_wizard()) {
1625                                 close_printer_handle(p, handle);
1626                                 ZERO_STRUCTP(r->out.handle);
1627                                 return WERR_ACCESS_DENIED;
1628                         }
1629
1630                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1631                            and not a printer admin, then fail */
1632
1633                         if ((p->server_info->utok.uid != 0) &&
1634                             !user_has_privileges(p->server_info->ptok,
1635                                                  &se_printop ) &&
1636                             !token_contains_name_in_list(
1637                                     uidtoname(p->server_info->utok.uid),
1638                                     NULL, NULL,
1639                                     p->server_info->ptok,
1640                                     lp_printer_admin(snum))) {
1641                                 close_printer_handle(p, handle);
1642                                 ZERO_STRUCTP(r->out.handle);
1643                                 return WERR_ACCESS_DENIED;
1644                         }
1645
1646                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1647                 }
1648                 else
1649                 {
1650                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1651                 }
1652
1653                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1654                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1655
1656                 /* We fall through to return WERR_OK */
1657                 break;
1658
1659         case SPLHND_PRINTER:
1660                 /* NT doesn't let us connect to a printer if the connecting user
1661                    doesn't have print permission.  */
1662
1663                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1664                         close_printer_handle(p, handle);
1665                         ZERO_STRUCTP(r->out.handle);
1666                         return WERR_BADFID;
1667                 }
1668
1669                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1670
1671                 /* map an empty access mask to the minimum access mask */
1672                 if (r->in.access_mask == 0x0)
1673                         r->in.access_mask = PRINTER_ACCESS_USE;
1674
1675                 /*
1676                  * If we are not serving the printer driver for this printer,
1677                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1678                  * will keep NT clients happy  --jerry
1679                  */
1680
1681                 if (lp_use_client_driver(snum)
1682                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1683                 {
1684                         r->in.access_mask = PRINTER_ACCESS_USE;
1685                 }
1686
1687                 /* check smb.conf parameters and the the sec_desc */
1688
1689                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1690                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1691                         ZERO_STRUCTP(r->out.handle);
1692                         return WERR_ACCESS_DENIED;
1693                 }
1694
1695                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1696                                    p->server_info->ptok, snum) ||
1697                     !print_access_check(p->server_info, snum,
1698                                         r->in.access_mask)) {
1699                         DEBUG(3, ("access DENIED for printer open\n"));
1700                         close_printer_handle(p, handle);
1701                         ZERO_STRUCTP(r->out.handle);
1702                         return WERR_ACCESS_DENIED;
1703                 }
1704
1705                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1706                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1707                         close_printer_handle(p, handle);
1708                         ZERO_STRUCTP(r->out.handle);
1709                         return WERR_ACCESS_DENIED;
1710                 }
1711
1712                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1713                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1714                 else
1715                         r->in.access_mask = PRINTER_ACCESS_USE;
1716
1717                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1718                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1719
1720                 break;
1721
1722         default:
1723                 /* sanity check to prevent programmer error */
1724                 ZERO_STRUCTP(r->out.handle);
1725                 return WERR_BADFID;
1726         }
1727
1728         Printer->access_granted = r->in.access_mask;
1729
1730         /*
1731          * If the client sent a devmode in the OpenPrinter() call, then
1732          * save it here in case we get a job submission on this handle
1733          */
1734
1735          if ( (Printer->printer_type != SPLHND_SERVER)
1736                 && r->in.devmode_ctr.devmode )
1737          {
1738                 convert_devicemode_new(Printer->sharename,
1739                                        r->in.devmode_ctr.devmode,
1740                                        &Printer->nt_devmode);
1741          }
1742
1743 #if 0   /* JERRY -- I'm doubtful this is really effective */
1744         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1745            optimization in Windows 2000 clients  --jerry */
1746
1747         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1748                 && (RA_WIN2K == get_remote_arch()) )
1749         {
1750                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1751                 sys_usleep( 500000 );
1752         }
1753 #endif
1754
1755         return WERR_OK;
1756 }
1757
1758 /****************************************************************************
1759 ****************************************************************************/
1760
1761 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1762                                               NT_PRINTER_INFO_LEVEL_2 *d)
1763 {
1764         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1765
1766         if (!r || !d) {
1767                 return false;
1768         }
1769
1770         d->attributes           = r->attributes;
1771         d->priority             = r->priority;
1772         d->default_priority     = r->defaultpriority;
1773         d->starttime            = r->starttime;
1774         d->untiltime            = r->untiltime;
1775         d->status               = r->status;
1776         d->cjobs                = r->cjobs;
1777
1778         fstrcpy(d->servername,  r->servername);
1779         fstrcpy(d->printername, r->printername);
1780         fstrcpy(d->sharename,   r->sharename);
1781         fstrcpy(d->portname,    r->portname);
1782         fstrcpy(d->drivername,  r->drivername);
1783         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1784         fstrcpy(d->location,    r->location);
1785         fstrcpy(d->sepfile,     r->sepfile);
1786         fstrcpy(d->printprocessor, r->printprocessor);
1787         fstrcpy(d->datatype,    r->datatype);
1788         fstrcpy(d->parameters,  r->parameters);
1789
1790         return true;
1791 }
1792
1793 /****************************************************************************
1794 ****************************************************************************/
1795
1796 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1797                                      NT_PRINTER_INFO_LEVEL *printer)
1798 {
1799         bool ret;
1800
1801         switch (info_ctr->level) {
1802         case 2:
1803                 /* allocate memory if needed.  Messy because
1804                    convert_printer_info is used to update an existing
1805                    printer or build a new one */
1806
1807                 if (!printer->info_2) {
1808                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1809                         if (!printer->info_2) {
1810                                 DEBUG(0,("convert_printer_info_new: "
1811                                         "talloc() failed!\n"));
1812                                 return false;
1813                         }
1814                 }
1815
1816                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1817                                                         printer->info_2);
1818                 printer->info_2->setuptime = time(NULL);
1819                 return ret;
1820         }
1821
1822         return false;
1823 }
1824
1825 /*******************************************************************
1826 ********************************************************************/
1827
1828 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1829 {
1830         int i;
1831
1832         if (!sarray) {
1833                 *farray = NULL;
1834                 return true;
1835         }
1836
1837         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1838         if (!*farray) {
1839                 return false;
1840         }
1841
1842         for (i=0; sarray[i] != NULL; i++) {
1843                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1844                 if (!*farray) {
1845                         return false;
1846                 }
1847                 fstrcpy((*farray)[i], sarray[i]);
1848         }
1849
1850         fstrcpy((*farray)[i], "");
1851
1852         return true;
1853 }
1854
1855 /*******************************************************************
1856 ********************************************************************/
1857
1858 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1859                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1860 {
1861         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1862
1863         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1864
1865         if (*p == NULL) {
1866                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1867                 if (*p == NULL) {
1868                         return false;
1869                 }
1870                 ZERO_STRUCTP(*p);
1871         }
1872
1873         d = *p;
1874
1875         d->cversion =                   r->version;
1876
1877         fstrcpy(d->name,                r->driver_name);
1878         fstrcpy(d->environment,         r->architecture);
1879         fstrcpy(d->driverpath,          r->driver_path);
1880         fstrcpy(d->datafile,            r->data_file);
1881         fstrcpy(d->configfile,          r->config_file);
1882         fstrcpy(d->helpfile,            r->help_file);
1883         fstrcpy(d->monitorname,         r->monitor_name);
1884         fstrcpy(d->defaultdatatype,     r->default_datatype);
1885
1886         DEBUGADD(8,( "version:         %d\n", d->cversion));
1887         DEBUGADD(8,( "name:            %s\n", d->name));
1888         DEBUGADD(8,( "environment:     %s\n", d->environment));
1889         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1890         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1891         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1892         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1893         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1894         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1895
1896         if (r->dependent_files) {
1897                 if (!string_array_to_fstring_array(r->dependent_files->string,
1898                                                    &d->dependentfiles)) {
1899                         SAFE_FREE(*p);
1900                         return false;
1901                 }
1902         }
1903
1904         return true;
1905 }
1906
1907 /*******************************************************************
1908 ********************************************************************/
1909
1910 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1911                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1912 {
1913         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1914
1915         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1916
1917         if (*p == NULL) {
1918                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1919                 if (*p == NULL) {
1920                         return false;
1921                 }
1922                 ZERO_STRUCTP(*p);
1923         }
1924
1925         d = *p;
1926
1927         d->version =                    r->version;
1928
1929         fstrcpy(d->name,                r->driver_name);
1930         fstrcpy(d->environment,         r->architecture);
1931         fstrcpy(d->driverpath,          r->driver_path);
1932         fstrcpy(d->datafile,            r->data_file);
1933         fstrcpy(d->configfile,          r->config_file);
1934         fstrcpy(d->helpfile,            r->help_file);
1935         fstrcpy(d->monitorname,         r->monitor_name);
1936         fstrcpy(d->defaultdatatype,     r->default_datatype);
1937
1938         DEBUGADD(8,( "version:         %d\n", d->version));
1939         DEBUGADD(8,( "name:            %s\n", d->name));
1940         DEBUGADD(8,( "environment:     %s\n", d->environment));
1941         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1942         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1943         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1944         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1945         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1946         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1947
1948         if (r->dependent_files) {
1949                 if (!string_array_to_fstring_array(r->dependent_files->string,
1950                                                    &d->dependentfiles)) {
1951                         goto error;
1952                 }
1953         }
1954
1955         if (r->previous_names) {
1956                 if (!string_array_to_fstring_array(r->previous_names->string,
1957                                                    &d->previousnames)) {
1958                         goto error;
1959                 }
1960         }
1961
1962         return true;
1963
1964  error:
1965         SAFE_FREE(*p);
1966         return false;
1967 }
1968
1969 /********************************************************************
1970  ********************************************************************/
1971
1972 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1973                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1974                                         uint32_t level)
1975 {
1976         switch (level) {
1977         case 3:
1978                 printer->info_3 = NULL;
1979                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1980                         return false;
1981                 }
1982                 break;
1983         case 6:
1984                 printer->info_6 = NULL;
1985                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1986                         return false;
1987                 }
1988                 break;
1989         default:
1990                 return false;
1991         }
1992
1993         return true;
1994 }
1995
1996 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1997                                 NT_DEVICEMODE **pp_nt_devmode)
1998 {
1999         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
2000
2001         /*
2002          * Ensure nt_devmode is a valid pointer
2003          * as we will be overwriting it.
2004          */
2005
2006         if (nt_devmode == NULL) {
2007                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2008                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2009                         return False;
2010         }
2011
2012         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2013         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2014
2015         nt_devmode->specversion=devmode->specversion;
2016         nt_devmode->driverversion=devmode->driverversion;
2017         nt_devmode->size=devmode->size;
2018         nt_devmode->fields=devmode->fields;
2019         nt_devmode->orientation=devmode->orientation;
2020         nt_devmode->papersize=devmode->papersize;
2021         nt_devmode->paperlength=devmode->paperlength;
2022         nt_devmode->paperwidth=devmode->paperwidth;
2023         nt_devmode->scale=devmode->scale;
2024         nt_devmode->copies=devmode->copies;
2025         nt_devmode->defaultsource=devmode->defaultsource;
2026         nt_devmode->printquality=devmode->printquality;
2027         nt_devmode->color=devmode->color;
2028         nt_devmode->duplex=devmode->duplex;
2029         nt_devmode->yresolution=devmode->yresolution;
2030         nt_devmode->ttoption=devmode->ttoption;
2031         nt_devmode->collate=devmode->collate;
2032
2033         nt_devmode->logpixels=devmode->logpixels;
2034         nt_devmode->bitsperpel=devmode->bitsperpel;
2035         nt_devmode->pelswidth=devmode->pelswidth;
2036         nt_devmode->pelsheight=devmode->pelsheight;
2037         nt_devmode->displayflags=devmode->displayflags;
2038         nt_devmode->displayfrequency=devmode->displayfrequency;
2039         nt_devmode->icmmethod=devmode->icmmethod;
2040         nt_devmode->icmintent=devmode->icmintent;
2041         nt_devmode->mediatype=devmode->mediatype;
2042         nt_devmode->dithertype=devmode->dithertype;
2043         nt_devmode->reserved1=devmode->reserved1;
2044         nt_devmode->reserved2=devmode->reserved2;
2045         nt_devmode->panningwidth=devmode->panningwidth;
2046         nt_devmode->panningheight=devmode->panningheight;
2047
2048         /*
2049          * Only change private and driverextra if the incoming devmode
2050          * has a new one. JRA.
2051          */
2052
2053         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2054                 SAFE_FREE(nt_devmode->nt_dev_private);
2055                 nt_devmode->driverextra=devmode->driverextra;
2056                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2057                         return False;
2058                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2059         }
2060
2061         *pp_nt_devmode = nt_devmode;
2062
2063         return True;
2064 }
2065
2066 /********************************************************************
2067  * _spoolss_enddocprinter_internal.
2068  ********************************************************************/
2069
2070 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2071 {
2072         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2073         int snum;
2074
2075         if (!Printer) {
2076                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2077                 return WERR_BADFID;
2078         }
2079
2080         if (!get_printer_snum(p, handle, &snum, NULL))
2081                 return WERR_BADFID;
2082
2083         Printer->document_started=False;
2084         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2085         /* error codes unhandled so far ... */
2086
2087         return WERR_OK;
2088 }
2089
2090 /****************************************************************
2091  _spoolss_ClosePrinter
2092 ****************************************************************/
2093
2094 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2095                              struct spoolss_ClosePrinter *r)
2096 {
2097         POLICY_HND *handle = r->in.handle;
2098
2099         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2100
2101         if (Printer && Printer->document_started)
2102                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2103
2104         if (!close_printer_handle(p, handle))
2105                 return WERR_BADFID;
2106
2107         /* clear the returned printer handle.  Observed behavior
2108            from Win2k server.  Don't think this really matters.
2109            Previous code just copied the value of the closed
2110            handle.    --jerry */
2111
2112         ZERO_STRUCTP(r->out.handle);
2113
2114         return WERR_OK;
2115 }
2116
2117 /****************************************************************
2118  _spoolss_DeletePrinter
2119 ****************************************************************/
2120
2121 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2122                               struct spoolss_DeletePrinter *r)
2123 {
2124         POLICY_HND *handle = r->in.handle;
2125         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2126         WERROR result;
2127
2128         if (Printer && Printer->document_started)
2129                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2130
2131         result = delete_printer_handle(p, handle);
2132
2133         update_c_setprinter(False);
2134
2135         return result;
2136 }
2137
2138 /*******************************************************************
2139  * static function to lookup the version id corresponding to an
2140  * long architecture string
2141  ******************************************************************/
2142
2143 static int get_version_id (char * arch)
2144 {
2145         int i;
2146         struct table_node archi_table[]= {
2147
2148                 {"Windows 4.0",          "WIN40",       0 },
2149                 {"Windows NT x86",       "W32X86",      2 },
2150                 {"Windows NT R4000",     "W32MIPS",     2 },
2151                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2152                 {"Windows NT PowerPC",   "W32PPC",      2 },
2153                 {"Windows IA64",         "IA64",        3 },
2154                 {"Windows x64",          "x64",         3 },
2155                 {NULL,                   "",            -1 }
2156         };
2157
2158         for (i=0; archi_table[i].long_archi != NULL; i++)
2159         {
2160                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2161                         return (archi_table[i].version);
2162         }
2163
2164         return -1;
2165 }
2166
2167 /****************************************************************
2168  _spoolss_DeletePrinterDriver
2169 ****************************************************************/
2170
2171 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2172                                     struct spoolss_DeletePrinterDriver *r)
2173 {
2174         char *driver;
2175         char *arch;
2176         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2177         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2178         int                             version;
2179         WERROR                          status;
2180         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2181         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2182
2183         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2184            and not a printer admin, then fail */
2185
2186         if ( (p->server_info->utok.uid != 0)
2187                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2188                 && !token_contains_name_in_list(
2189                         uidtoname(p->server_info->utok.uid), NULL,
2190                         NULL, p->server_info->ptok,
2191                         lp_printer_admin(-1)) )
2192         {
2193                 return WERR_ACCESS_DENIED;
2194         }
2195
2196         driver = CONST_DISCARD(char *, r->in.driver);
2197         arch   = CONST_DISCARD(char *, r->in.architecture);
2198
2199         /* check that we have a valid driver name first */
2200
2201         if ((version=get_version_id(arch)) == -1)
2202                 return WERR_INVALID_ENVIRONMENT;
2203
2204         ZERO_STRUCT(info);
2205         ZERO_STRUCT(info_win2k);
2206
2207         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2208         {
2209                 /* try for Win2k driver if "Windows NT x86" */
2210
2211                 if ( version == 2 ) {
2212                         version = 3;
2213                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2214                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2215                                 goto done;
2216                         }
2217                 }
2218                 /* otherwise it was a failure */
2219                 else {
2220                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2221                         goto done;
2222                 }
2223
2224         }
2225
2226         if (printer_driver_in_use(info.info_3)) {
2227                 status = WERR_PRINTER_DRIVER_IN_USE;
2228                 goto done;
2229         }
2230
2231         if ( version == 2 )
2232         {
2233                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2234                 {
2235                         /* if we get to here, we now have 2 driver info structures to remove */
2236                         /* remove the Win2k driver first*/
2237
2238                         status_win2k = delete_printer_driver(
2239                                 p, info_win2k.info_3, 3, False );
2240                         free_a_printer_driver( info_win2k, 3 );
2241
2242                         /* this should not have failed---if it did, report to client */
2243                         if ( !W_ERROR_IS_OK(status_win2k) )
2244                         {
2245                                 status = status_win2k;
2246                                 goto done;
2247                         }
2248                 }
2249         }
2250
2251         status = delete_printer_driver(p, info.info_3, version, False);
2252
2253         /* if at least one of the deletes succeeded return OK */
2254
2255         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2256                 status = WERR_OK;
2257
2258 done:
2259         free_a_printer_driver( info, 3 );
2260
2261         return status;
2262 }
2263
2264 /****************************************************************
2265  _spoolss_DeletePrinterDriverEx
2266 ****************************************************************/
2267
2268 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2269                                       struct spoolss_DeletePrinterDriverEx *r)
2270 {
2271         char *driver;
2272         char *arch;
2273         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2274         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2275         int                             version;
2276         uint32_t                        flags = r->in.delete_flags;
2277         bool                            delete_files;
2278         WERROR                          status;
2279         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2280         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2281
2282         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2283            and not a printer admin, then fail */
2284
2285         if ( (p->server_info->utok.uid != 0)
2286                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2287                 && !token_contains_name_in_list(
2288                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2289                         p->server_info->ptok, lp_printer_admin(-1)) )
2290         {
2291                 return WERR_ACCESS_DENIED;
2292         }
2293
2294         driver = CONST_DISCARD(char *, r->in.driver);
2295         arch   = CONST_DISCARD(char *, r->in.architecture);
2296
2297         /* check that we have a valid driver name first */
2298         if ((version=get_version_id(arch)) == -1) {
2299                 /* this is what NT returns */
2300                 return WERR_INVALID_ENVIRONMENT;
2301         }
2302
2303         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2304                 version = r->in.version;
2305
2306         ZERO_STRUCT(info);
2307         ZERO_STRUCT(info_win2k);
2308
2309         status = get_a_printer_driver(&info, 3, driver, arch, version);
2310
2311         if ( !W_ERROR_IS_OK(status) )
2312         {
2313                 /*
2314                  * if the client asked for a specific version,
2315                  * or this is something other than Windows NT x86,
2316                  * then we've failed
2317                  */
2318
2319                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2320                         goto done;
2321
2322                 /* try for Win2k driver if "Windows NT x86" */
2323
2324                 version = 3;
2325                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2326                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2327                         goto done;
2328                 }
2329         }
2330
2331         if ( printer_driver_in_use(info.info_3) ) {
2332                 status = WERR_PRINTER_DRIVER_IN_USE;
2333                 goto done;
2334         }
2335
2336         /*
2337          * we have a couple of cases to consider.
2338          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2339          *     then the delete should fail if **any** files overlap with
2340          *     other drivers
2341          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2342          *     non-overlapping files
2343          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2344          *     is set, the do not delete any files
2345          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2346          */
2347
2348         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2349
2350         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2351
2352         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2353                 /* no idea of the correct error here */
2354                 status = WERR_ACCESS_DENIED;
2355                 goto done;
2356         }
2357
2358
2359         /* also check for W32X86/3 if necessary; maybe we already have? */
2360
2361         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2362                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2363                 {
2364
2365                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2366                                 /* no idea of the correct error here */
2367                                 free_a_printer_driver( info_win2k, 3 );
2368                                 status = WERR_ACCESS_DENIED;
2369                                 goto done;
2370                         }
2371
2372                         /* if we get to here, we now have 2 driver info structures to remove */
2373                         /* remove the Win2k driver first*/
2374
2375                         status_win2k = delete_printer_driver(
2376                                 p, info_win2k.info_3, 3, delete_files);
2377                         free_a_printer_driver( info_win2k, 3 );
2378
2379                         /* this should not have failed---if it did, report to client */
2380
2381                         if ( !W_ERROR_IS_OK(status_win2k) )
2382                                 goto done;
2383                 }
2384         }
2385
2386         status = delete_printer_driver(p, info.info_3, version, delete_files);
2387
2388         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2389                 status = WERR_OK;
2390 done:
2391         free_a_printer_driver( info, 3 );
2392
2393         return status;
2394 }
2395
2396
2397 /****************************************************************************
2398  Internal routine for removing printerdata
2399  ***************************************************************************/
2400
2401 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2402 {
2403         return delete_printer_data( printer->info_2, key, value );
2404 }
2405
2406 /****************************************************************************
2407  Internal routine for storing printerdata
2408  ***************************************************************************/
2409
2410 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2411                                   uint32 type, uint8 *data, int real_len  )
2412 {
2413         /* the registry objects enforce uniqueness based on value name */
2414
2415         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2416 }
2417
2418 /********************************************************************
2419  GetPrinterData on a printer server Handle.
2420 ********************************************************************/
2421
2422 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2423                                             const char *value,
2424                                             enum winreg_Type *type,
2425                                             union spoolss_PrinterData *data)
2426 {
2427         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2428
2429         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2430                 *type = REG_DWORD;
2431                 data->value = 0x00;
2432                 return WERR_OK;
2433         }
2434
2435         if (!StrCaseCmp(value, "BeepEnabled")) {
2436                 *type = REG_DWORD;
2437                 data->value = 0x00;
2438                 return WERR_OK;
2439         }
2440
2441         if (!StrCaseCmp(value, "EventLog")) {
2442                 *type = REG_DWORD;
2443                 /* formally was 0x1b */
2444                 data->value = 0x00;
2445                 return WERR_OK;
2446         }
2447
2448         if (!StrCaseCmp(value, "NetPopup")) {
2449                 *type = REG_DWORD;
2450                 data->value = 0x00;
2451                 return WERR_OK;
2452         }
2453
2454         if (!StrCaseCmp(value, "MajorVersion")) {
2455                 *type = REG_DWORD;
2456
2457                 /* Windows NT 4.0 seems to not allow uploading of drivers
2458                    to a server that reports 0x3 as the MajorVersion.
2459                    need to investigate more how Win2k gets around this .
2460                    -- jerry */
2461
2462                 if (RA_WINNT == get_remote_arch()) {
2463                         data->value = 0x02;
2464                 } else {
2465                         data->value = 0x03;
2466                 }
2467
2468                 return WERR_OK;
2469         }
2470
2471         if (!StrCaseCmp(value, "MinorVersion")) {
2472                 *type = REG_DWORD;
2473                 data->value = 0x00;
2474                 return WERR_OK;
2475         }
2476
2477         /* REG_BINARY
2478          *  uint32 size          = 0x114
2479          *  uint32 major         = 5
2480          *  uint32 minor         = [0|1]
2481          *  uint32 build         = [2195|2600]
2482          *  extra unicode string = e.g. "Service Pack 3"
2483          */
2484         if (!StrCaseCmp(value, "OSVersion")) {
2485                 DATA_BLOB blob;
2486                 enum ndr_err_code ndr_err;
2487                 struct spoolss_OSVersion os;
2488
2489                 os.major                = 5;    /* Windows 2000 == 5.0 */
2490                 os.minor                = 0;
2491                 os.build                = 2195; /* build */
2492                 os.extra_string         = "";   /* leave extra string empty */
2493
2494                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2495                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2496                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2497                         return WERR_GENERAL_FAILURE;
2498                 }
2499
2500                 *type = REG_BINARY;
2501                 data->binary = blob;
2502
2503                 return WERR_OK;
2504         }
2505
2506
2507         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2508                 *type = REG_SZ;
2509
2510                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2511                 W_ERROR_HAVE_NO_MEMORY(data->string);
2512
2513                 return WERR_OK;
2514         }
2515
2516         if (!StrCaseCmp(value, "Architecture")) {
2517                 *type = REG_SZ;
2518
2519                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2520                 W_ERROR_HAVE_NO_MEMORY(data->string);
2521
2522                 return WERR_OK;
2523         }
2524
2525         if (!StrCaseCmp(value, "DsPresent")) {
2526                 *type = REG_DWORD;
2527
2528                 /* only show the publish check box if we are a
2529                    member of a AD domain */
2530
2531                 if (lp_security() == SEC_ADS) {
2532                         data->value = 0x01;
2533                 } else {
2534                         data->value = 0x00;
2535                 }
2536                 return WERR_OK;
2537         }
2538
2539         if (!StrCaseCmp(value, "DNSMachineName")) {
2540                 const char *hostname = get_mydnsfullname();
2541
2542                 if (!hostname) {
2543                         return WERR_BADFILE;
2544                 }
2545
2546                 *type = REG_SZ;
2547                 data->string = talloc_strdup(mem_ctx, hostname);
2548                 W_ERROR_HAVE_NO_MEMORY(data->string);
2549
2550                 return WERR_OK;
2551         }
2552
2553         return WERR_BADFILE;
2554 }
2555
2556 /****************************************************************
2557  _spoolss_GetPrinterData
2558 ****************************************************************/
2559
2560 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2561                                struct spoolss_GetPrinterData *r)
2562 {
2563         WERROR result;
2564         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2565         NT_PRINTER_INFO_LEVEL *printer = NULL;
2566         int snum = 0;
2567
2568         /*
2569          * Reminder: when it's a string, the length is in BYTES
2570          * even if UNICODE is negociated.
2571          *
2572          * JFM, 4/19/1999
2573          */
2574
2575         /* in case of problem, return some default values */
2576
2577         *r->out.needed  = 0;
2578         *r->out.type    = 0;
2579
2580         DEBUG(4,("_spoolss_GetPrinterData\n"));
2581
2582         if (!Printer) {
2583                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2584                         OUR_HANDLE(r->in.handle)));
2585                 result = WERR_BADFID;
2586                 goto done;
2587         }
2588
2589         if (Printer->printer_type == SPLHND_SERVER) {
2590                 result = getprinterdata_printer_server(p->mem_ctx,
2591                                                        r->in.value_name,
2592                                                        r->out.type,
2593                                                        r->out.data);
2594         } else {
2595                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2596                         result = WERR_BADFID;
2597                         goto done;
2598                 }
2599
2600                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2601                 if (!W_ERROR_IS_OK(result)) {
2602                         goto done;
2603                 }
2604
2605                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2606
2607                 if (strequal(r->in.value_name, "ChangeId")) {
2608                         *r->out.type = REG_DWORD;
2609                         r->out.data->value = printer->info_2->changeid;
2610                         result = WERR_OK;
2611                 } else {
2612                         REGISTRY_VALUE *v;
2613                         DATA_BLOB blob;
2614
2615                         v = get_printer_data(printer->info_2,
2616                                              SPOOL_PRINTERDATA_KEY,
2617                                              r->in.value_name);
2618                         if (!v) {
2619                                 result = WERR_BADFILE;
2620                                 goto done;
2621                         }
2622
2623                         *r->out.type = v->type;
2624
2625                         blob = data_blob_const(v->data_p, v->size);
2626
2627                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2628                                                           r->out.data,
2629                                                           *r->out.type);
2630                 }
2631         }
2632
2633  done:
2634         /* cleanup & exit */
2635
2636         if (printer) {
2637                 free_a_printer(&printer, 2);
2638         }
2639
2640         if (!W_ERROR_IS_OK(result)) {
2641                 return result;
2642         }
2643
2644         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2645         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2646         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2647
2648         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2649 }
2650
2651 /*********************************************************
2652  Connect to the client machine.
2653 **********************************************************/
2654
2655 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2656                         struct sockaddr_storage *client_ss, const char *remote_machine)
2657 {
2658         NTSTATUS ret;
2659         struct cli_state *the_cli;
2660         struct sockaddr_storage rm_addr;
2661
2662         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2663                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2664                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2665                         return False;
2666                 }
2667
2668                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2669                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2670                         return False;
2671                 }
2672         } else {
2673                 char addr[INET6_ADDRSTRLEN];
2674                 rm_addr = *client_ss;
2675                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2676                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2677                         addr));
2678         }
2679
2680         /* setup the connection */
2681
2682         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2683                 &rm_addr, 0, "IPC$", "IPC",
2684                 "", /* username */
2685                 "", /* domain */
2686                 "", /* password */
2687                 0, lp_client_signing(), NULL );
2688
2689         if ( !NT_STATUS_IS_OK( ret ) ) {
2690                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2691                         remote_machine ));
2692                 return False;
2693         }
2694
2695         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2696                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2697                 cli_shutdown(the_cli);
2698                 return False;
2699         }
2700
2701         /*
2702          * Ok - we have an anonymous connection to the IPC$ share.
2703          * Now start the NT Domain stuff :-).
2704          */
2705
2706         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2707         if (!NT_STATUS_IS_OK(ret)) {
2708                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2709                         remote_machine, nt_errstr(ret)));
2710                 cli_shutdown(the_cli);
2711                 return False;
2712         }
2713
2714         return True;
2715 }
2716
2717 /***************************************************************************
2718  Connect to the client.
2719 ****************************************************************************/
2720
2721 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2722                                         uint32 localprinter, uint32 type,
2723                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2724 {
2725         WERROR result;
2726         NTSTATUS status;
2727
2728         /*
2729          * If it's the first connection, contact the client
2730          * and connect to the IPC$ share anonymously
2731          */
2732         if (smb_connections==0) {
2733                 fstring unix_printer;
2734
2735                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2736
2737                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2738                         return False;
2739
2740                 messaging_register(smbd_messaging_context(), NULL,
2741                                    MSG_PRINTER_NOTIFY2,
2742                                    receive_notify2_message_list);
2743                 /* Tell the connections db we're now interested in printer
2744                  * notify messages. */
2745                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2746         }
2747
2748         /*
2749          * Tell the specific printing tdb we want messages for this printer
2750          * by registering our PID.
2751          */
2752
2753         if (!print_notify_register_pid(snum))
2754                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2755
2756         smb_connections++;
2757
2758         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2759                                                  printer,
2760                                                  localprinter,
2761                                                  type,
2762                                                  0,
2763                                                  NULL,
2764                                                  handle,
2765                                                  &result);
2766         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2767                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2768                         win_errstr(result)));
2769
2770         return (W_ERROR_IS_OK(result));
2771 }
2772
2773 /****************************************************************
2774  ****************************************************************/
2775
2776 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2777                                                              const struct spoolss_NotifyOption *r)
2778 {
2779         struct spoolss_NotifyOption *option;
2780         uint32_t i,k;
2781
2782         if (!r) {
2783                 return NULL;
2784         }
2785
2786         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2787         if (!option) {
2788                 return NULL;
2789         }
2790
2791         *option = *r;
2792
2793         if (!option->count) {
2794                 return option;
2795         }
2796
2797         option->types = talloc_zero_array(option,
2798                 struct spoolss_NotifyOptionType, option->count);
2799         if (!option->types) {
2800                 talloc_free(option);
2801                 return NULL;
2802         }
2803
2804         for (i=0; i < option->count; i++) {
2805                 option->types[i] = r->types[i];
2806
2807                 if (option->types[i].count) {
2808                         option->types[i].fields = talloc_zero_array(option,
2809                                 enum spoolss_Field, option->types[i].count);
2810                         if (!option->types[i].fields) {
2811                                 talloc_free(option);
2812                                 return NULL;
2813                         }
2814                         for (k=0; k<option->types[i].count; k++) {
2815                                 option->types[i].fields[k] =
2816                                         r->types[i].fields[k];
2817                         }
2818                 }
2819         }
2820
2821         return option;
2822 }
2823
2824 /****************************************************************
2825  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2826  *
2827  * before replying OK: status=0 a rpc call is made to the workstation
2828  * asking ReplyOpenPrinter
2829  *
2830  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2831  * called from api_spoolss_rffpcnex
2832 ****************************************************************/
2833
2834 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2835                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2836 {
2837         POLICY_HND *handle = r->in.handle;
2838         int snum = -1;
2839         struct spoolss_NotifyOption *option = r->in.notify_options;
2840         struct sockaddr_storage client_ss;
2841
2842         /* store the notify value in the printer struct */
2843
2844         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2845
2846         if (!Printer) {
2847                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2848                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2849                 return WERR_BADFID;
2850         }
2851
2852         Printer->notify.flags           = r->in.flags;
2853         Printer->notify.options         = r->in.options;
2854         Printer->notify.printerlocal    = r->in.printer_local;
2855
2856         TALLOC_FREE(Printer->notify.option);
2857         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2858
2859         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2860
2861         /* Connect to the client machine and send a ReplyOpenPrinter */
2862
2863         if ( Printer->printer_type == SPLHND_SERVER)
2864                 snum = -1;
2865         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2866                         !get_printer_snum(p, handle, &snum, NULL) )
2867                 return WERR_BADFID;
2868
2869         if (!interpret_string_addr(&client_ss, p->client_address,
2870                                    AI_NUMERICHOST)) {
2871                 return WERR_SERVER_UNAVAILABLE;
2872         }
2873
2874         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2875                                         Printer->notify.printerlocal, 1,
2876                                         &Printer->notify.client_hnd, &client_ss))
2877                 return WERR_SERVER_UNAVAILABLE;
2878
2879         Printer->notify.client_connected=True;
2880
2881         return WERR_OK;
2882 }
2883
2884 /*******************************************************************
2885  * fill a notify_info_data with the servername
2886  ********************************************************************/
2887
2888 void spoolss_notify_server_name(int snum,
2889                                        struct spoolss_Notify *data,
2890                                        print_queue_struct *queue,
2891                                        NT_PRINTER_INFO_LEVEL *printer,
2892                                        TALLOC_CTX *mem_ctx)
2893 {
2894         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2895 }
2896
2897 /*******************************************************************
2898  * fill a notify_info_data with the printername (not including the servername).
2899  ********************************************************************/
2900
2901 void spoolss_notify_printer_name(int snum,
2902                                         struct spoolss_Notify *data,
2903                                         print_queue_struct *queue,
2904                                         NT_PRINTER_INFO_LEVEL *printer,
2905                                         TALLOC_CTX *mem_ctx)
2906 {
2907         /* the notify name should not contain the \\server\ part */
2908         char *p = strrchr(printer->info_2->printername, '\\');
2909
2910         if (!p) {
2911                 p = printer->info_2->printername;
2912         } else {
2913                 p++;
2914         }
2915
2916         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2917 }
2918
2919 /*******************************************************************
2920  * fill a notify_info_data with the servicename
2921  ********************************************************************/
2922
2923 void spoolss_notify_share_name(int snum,
2924                                       struct spoolss_Notify *data,
2925                                       print_queue_struct *queue,
2926                                       NT_PRINTER_INFO_LEVEL *printer,
2927                                       TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the port name
2934  ********************************************************************/
2935
2936 void spoolss_notify_port_name(int snum,
2937                                      struct spoolss_Notify *data,
2938                                      print_queue_struct *queue,
2939                                      NT_PRINTER_INFO_LEVEL *printer,
2940                                      TALLOC_CTX *mem_ctx)
2941 {
2942         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2943 }
2944
2945 /*******************************************************************
2946  * fill a notify_info_data with the printername
2947  * but it doesn't exist, have to see what to do
2948  ********************************************************************/
2949
2950 void spoolss_notify_driver_name(int snum,
2951                                        struct spoolss_Notify *data,
2952                                        print_queue_struct *queue,
2953                                        NT_PRINTER_INFO_LEVEL *printer,
2954                                        TALLOC_CTX *mem_ctx)
2955 {
2956         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2957 }
2958
2959 /*******************************************************************
2960  * fill a notify_info_data with the comment
2961  ********************************************************************/
2962
2963 void spoolss_notify_comment(int snum,
2964                                    struct spoolss_Notify *data,
2965                                    print_queue_struct *queue,
2966                                    NT_PRINTER_INFO_LEVEL *printer,
2967                                    TALLOC_CTX *mem_ctx)
2968 {
2969         char *p;
2970
2971         if (*printer->info_2->comment == '\0') {
2972                 p = lp_comment(snum);
2973         } else {
2974                 p = printer->info_2->comment;
2975         }
2976
2977         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2978 }
2979
2980 /*******************************************************************
2981  * fill a notify_info_data with the comment
2982  * location = "Room 1, floor 2, building 3"
2983  ********************************************************************/
2984
2985 void spoolss_notify_location(int snum,
2986                                     struct spoolss_Notify *data,
2987                                     print_queue_struct *queue,
2988                                     NT_PRINTER_INFO_LEVEL *printer,
2989                                     TALLOC_CTX *mem_ctx)
2990 {
2991         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2992 }
2993
2994 /*******************************************************************
2995  * fill a notify_info_data with the device mode
2996  * jfm:xxxx don't to it for know but that's a real problem !!!
2997  ********************************************************************/
2998
2999 static void spoolss_notify_devmode(int snum,
3000                                    struct spoolss_Notify *data,
3001                                    print_queue_struct *queue,
3002                                    NT_PRINTER_INFO_LEVEL *printer,
3003                                    TALLOC_CTX *mem_ctx)
3004 {
3005         /* for a dummy implementation we have to zero the fields */
3006         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3007 }
3008
3009 /*******************************************************************
3010  * fill a notify_info_data with the separator file name
3011  ********************************************************************/
3012
3013 void spoolss_notify_sepfile(int snum,
3014                                    struct spoolss_Notify *data,
3015                                    print_queue_struct *queue,
3016                                    NT_PRINTER_INFO_LEVEL *printer,
3017                                    TALLOC_CTX *mem_ctx)
3018 {
3019         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3020 }
3021
3022 /*******************************************************************
3023  * fill a notify_info_data with the print processor
3024  * jfm:xxxx return always winprint to indicate we don't do anything to it
3025  ********************************************************************/
3026
3027 void spoolss_notify_print_processor(int snum,
3028                                            struct spoolss_Notify *data,
3029                                            print_queue_struct *queue,
3030                                            NT_PRINTER_INFO_LEVEL *printer,
3031                                            TALLOC_CTX *mem_ctx)
3032 {
3033         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the print processor options
3038  * jfm:xxxx send an empty string
3039  ********************************************************************/
3040
3041 void spoolss_notify_parameters(int snum,
3042                                       struct spoolss_Notify *data,
3043                                       print_queue_struct *queue,
3044                                       NT_PRINTER_INFO_LEVEL *printer,
3045                                       TALLOC_CTX *mem_ctx)
3046 {
3047         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with the data type
3052  * jfm:xxxx always send RAW as data type
3053  ********************************************************************/
3054
3055 void spoolss_notify_datatype(int snum,
3056                                     struct spoolss_Notify *data,
3057                                     print_queue_struct *queue,
3058                                     NT_PRINTER_INFO_LEVEL *printer,
3059                                     TALLOC_CTX *mem_ctx)
3060 {
3061         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3062 }
3063
3064 /*******************************************************************
3065  * fill a notify_info_data with the security descriptor
3066  * jfm:xxxx send an null pointer to say no security desc
3067  * have to implement security before !
3068  ********************************************************************/
3069
3070 static void spoolss_notify_security_desc(int snum,
3071                                          struct spoolss_Notify *data,
3072                                          print_queue_struct *queue,
3073                                          NT_PRINTER_INFO_LEVEL *printer,
3074                                          TALLOC_CTX *mem_ctx)
3075 {
3076         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3077                                           printer->info_2->secdesc_buf->sd_size,
3078                                           printer->info_2->secdesc_buf->sd);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with the attributes
3083  * jfm:xxxx a samba printer is always shared
3084  ********************************************************************/
3085
3086 void spoolss_notify_attributes(int snum,
3087                                       struct spoolss_Notify *data,
3088                                       print_queue_struct *queue,
3089                                       NT_PRINTER_INFO_LEVEL *printer,
3090                                       TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with the priority
3097  ********************************************************************/
3098
3099 static void spoolss_notify_priority(int snum,
3100                                     struct spoolss_Notify *data,
3101                                     print_queue_struct *queue,
3102                                     NT_PRINTER_INFO_LEVEL *printer,
3103                                     TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with the default priority
3110  ********************************************************************/
3111
3112 static void spoolss_notify_default_priority(int snum,
3113                                             struct spoolss_Notify *data,
3114                                             print_queue_struct *queue,
3115                                             NT_PRINTER_INFO_LEVEL *printer,
3116                                             TALLOC_CTX *mem_ctx)
3117 {
3118         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3119 }
3120
3121 /*******************************************************************
3122  * fill a notify_info_data with the start time
3123  ********************************************************************/
3124
3125 static void spoolss_notify_start_time(int snum,
3126                                       struct spoolss_Notify *data,
3127                                       print_queue_struct *queue,
3128                                       NT_PRINTER_INFO_LEVEL *printer,
3129                                       TALLOC_CTX *mem_ctx)
3130 {
3131         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3132 }
3133
3134 /*******************************************************************
3135  * fill a notify_info_data with the until time
3136  ********************************************************************/
3137
3138 static void spoolss_notify_until_time(int snum,
3139                                       struct spoolss_Notify *data,
3140                                       print_queue_struct *queue,
3141                                       NT_PRINTER_INFO_LEVEL *printer,
3142                                       TALLOC_CTX *mem_ctx)
3143 {
3144         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3145 }
3146
3147 /*******************************************************************
3148  * fill a notify_info_data with the status
3149  ********************************************************************/
3150
3151 static void spoolss_notify_status(int snum,
3152                                   struct spoolss_Notify *data,
3153                                   print_queue_struct *queue,
3154                                   NT_PRINTER_INFO_LEVEL *printer,
3155                                   TALLOC_CTX *mem_ctx)
3156 {
3157         print_status_struct status;
3158
3159         print_queue_length(snum, &status);
3160         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3161 }
3162
3163 /*******************************************************************
3164  * fill a notify_info_data with the number of jobs queued
3165  ********************************************************************/
3166
3167 void spoolss_notify_cjobs(int snum,
3168                                  struct spoolss_Notify *data,
3169                                  print_queue_struct *queue,
3170                                  NT_PRINTER_INFO_LEVEL *printer,
3171                                  TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with the average ppm
3178  ********************************************************************/
3179
3180 static void spoolss_notify_average_ppm(int snum,
3181                                        struct spoolss_Notify *data,
3182                                        print_queue_struct *queue,
3183                                        NT_PRINTER_INFO_LEVEL *printer,
3184                                        TALLOC_CTX *mem_ctx)
3185 {
3186         /* always respond 8 pages per minutes */
3187         /* a little hard ! */
3188         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3189 }
3190
3191 /*******************************************************************
3192  * fill a notify_info_data with username
3193  ********************************************************************/
3194
3195 static void spoolss_notify_username(int snum,
3196                                     struct spoolss_Notify *data,
3197                                     print_queue_struct *queue,
3198                                     NT_PRINTER_INFO_LEVEL *printer,
3199                                     TALLOC_CTX *mem_ctx)
3200 {
3201         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3202 }
3203
3204 /*******************************************************************
3205  * fill a notify_info_data with job status
3206  ********************************************************************/
3207
3208 static void spoolss_notify_job_status(int snum,
3209                                       struct spoolss_Notify *data,
3210                                       print_queue_struct *queue,
3211                                       NT_PRINTER_INFO_LEVEL *printer,
3212                                       TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3215 }
3216
3217 /*******************************************************************
3218  * fill a notify_info_data with job name
3219  ********************************************************************/
3220
3221 static void spoolss_notify_job_name(int snum,
3222                                     struct spoolss_Notify *data,
3223                                     print_queue_struct *queue,
3224                                     NT_PRINTER_INFO_LEVEL *printer,
3225                                     TALLOC_CTX *mem_ctx)
3226 {
3227         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3228 }
3229
3230 /*******************************************************************
3231  * fill a notify_info_data with job status
3232  ********************************************************************/
3233
3234 static void spoolss_notify_job_status_string(int snum,
3235                                              struct spoolss_Notify *data,
3236                                              print_queue_struct *queue,
3237                                              NT_PRINTER_INFO_LEVEL *printer,
3238                                              TALLOC_CTX *mem_ctx)
3239 {
3240         /*
3241          * Now we're returning job status codes we just return a "" here. JRA.
3242          */
3243
3244         const char *p = "";
3245
3246 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3247         p = "unknown";
3248
3249         switch (queue->status) {
3250         case LPQ_QUEUED:
3251                 p = "Queued";
3252                 break;
3253         case LPQ_PAUSED:
3254                 p = "";    /* NT provides the paused string */
3255                 break;
3256         case LPQ_SPOOLING:
3257                 p = "Spooling";
3258                 break;
3259         case LPQ_PRINTING:
3260                 p = "Printing";
3261                 break;
3262         }
3263 #endif /* NO LONGER NEEDED. */
3264
3265         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3266 }
3267
3268 /*******************************************************************
3269  * fill a notify_info_data with job time
3270  ********************************************************************/
3271
3272 static void spoolss_notify_job_time(int snum,
3273                                     struct spoolss_Notify *data,
3274                                     print_queue_struct *queue,
3275                                     NT_PRINTER_INFO_LEVEL *printer,
3276                                     TALLOC_CTX *mem_ctx)
3277 {
3278         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3279 }
3280
3281 /*******************************************************************
3282  * fill a notify_info_data with job size
3283  ********************************************************************/
3284
3285 static void spoolss_notify_job_size(int snum,
3286                                     struct spoolss_Notify *data,
3287                                     print_queue_struct *queue,
3288                                     NT_PRINTER_INFO_LEVEL *printer,
3289                                     TALLOC_CTX *mem_ctx)
3290 {
3291         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3292 }
3293
3294 /*******************************************************************
3295  * fill a notify_info_data with page info
3296  ********************************************************************/
3297 static void spoolss_notify_total_pages(int snum,
3298                                 struct spoolss_Notify *data,
3299                                 print_queue_struct *queue,
3300                                 NT_PRINTER_INFO_LEVEL *printer,
3301                                 TALLOC_CTX *mem_ctx)
3302 {
3303         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3304 }
3305
3306 /*******************************************************************
3307  * fill a notify_info_data with pages printed info.
3308  ********************************************************************/
3309 static void spoolss_notify_pages_printed(int snum,
3310                                 struct spoolss_Notify *data,
3311                                 print_queue_struct *queue,
3312                                 NT_PRINTER_INFO_LEVEL *printer,
3313                                 TALLOC_CTX *mem_ctx)
3314 {
3315         /* Add code when back-end tracks this */
3316         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3317 }
3318
3319 /*******************************************************************
3320  Fill a notify_info_data with job position.
3321  ********************************************************************/
3322
3323 static void spoolss_notify_job_position(int snum,
3324                                         struct spoolss_Notify *data,
3325                                         print_queue_struct *queue,
3326                                         NT_PRINTER_INFO_LEVEL *printer,
3327                                         TALLOC_CTX *mem_ctx)
3328 {
3329         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3330 }
3331
3332 /*******************************************************************
3333  Fill a notify_info_data with submitted time.
3334  ********************************************************************/
3335
3336 static void spoolss_notify_submitted_time(int snum,
3337                                           struct spoolss_Notify *data,
3338                                           print_queue_struct *queue,
3339                                           NT_PRINTER_INFO_LEVEL *printer,
3340                                           TALLOC_CTX *mem_ctx)
3341 {
3342         data->data.string.string = NULL;
3343         data->data.string.size = 0;
3344
3345         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3346                                &data->data.string.string,
3347                                &data->data.string.size);
3348
3349 }
3350
3351 struct s_notify_info_data_table
3352 {
3353         enum spoolss_NotifyType type;
3354         enum spoolss_Field field;
3355         const char *name;
3356         enum spoolss_NotifyTable variable_type;
3357         void (*fn) (int snum, struct spoolss_Notify *data,
3358                     print_queue_struct *queue,
3359                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3360 };
3361
3362 /* A table describing the various print notification constants and
3363    whether the notification data is a pointer to a variable sized
3364    buffer, a one value uint32 or a two value uint32. */
3365
3366 static const struct s_notify_info_data_table notify_info_data_table[] =
3367 {
3368 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3369 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3370 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3371 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3372 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3373 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3374 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3375 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3376 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3377 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3378 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3394 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3395 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3396 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3397 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3398 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3399 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3400 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3401 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3402 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3403 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3404 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3405 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3406 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3407 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3408 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3409 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3410 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3411 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3412 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3413 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3414 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3415 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3416 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3417 };
3418
3419 /*******************************************************************
3420  Return the variable_type of info_data structure.
3421 ********************************************************************/
3422
3423 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3424                                                   enum spoolss_Field field)
3425 {
3426         int i=0;
3427
3428         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3429                 if ( (notify_info_data_table[i].type == type) &&
3430                      (notify_info_data_table[i].field == field) ) {
3431                         return notify_info_data_table[i].variable_type;
3432                 }
3433         }
3434
3435         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3436
3437         return 0;
3438 }
3439
3440 /****************************************************************************
3441 ****************************************************************************/
3442
3443 static bool search_notify(enum spoolss_NotifyType type,
3444                           enum spoolss_Field field,
3445                           int *value)
3446 {
3447         int i;
3448
3449         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3450                 if (notify_info_data_table[i].type == type &&
3451                     notify_info_data_table[i].field == field &&
3452                     notify_info_data_table[i].fn != NULL) {
3453                         *value = i;
3454                         return True;
3455                 }
3456         }
3457
3458         return False;
3459 }
3460
3461 /****************************************************************************
3462 ****************************************************************************/
3463
3464 void construct_info_data(struct spoolss_Notify *info_data,
3465                          enum spoolss_NotifyType type,
3466                          enum spoolss_Field field,
3467                          int id)
3468 {
3469         info_data->type                 = type;
3470         info_data->field                = field;
3471         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3472         info_data->job_id               = id;
3473 }
3474
3475 /*******************************************************************
3476  *
3477  * fill a notify_info struct with info asked
3478  *
3479  ********************************************************************/
3480
3481 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3482                                           struct spoolss_NotifyInfo *info,
3483                                           int snum,
3484                                           const struct spoolss_NotifyOptionType *option_type,
3485                                           uint32_t id,
3486                                           TALLOC_CTX *mem_ctx)
3487 {
3488         int field_num,j;
3489         enum spoolss_NotifyType type;
3490         enum spoolss_Field field;
3491
3492         struct spoolss_Notify *current_data;
3493         NT_PRINTER_INFO_LEVEL *printer = NULL;
3494         print_queue_struct *queue=NULL;
3495
3496         type = option_type->type;
3497
3498         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3499                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3500                 option_type->count, lp_servicename(snum)));
3501
3502         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3503                 return False;
3504
3505         for(field_num=0; field_num < option_type->count; field_num++) {
3506                 field = option_type->fields[field_num];
3507
3508                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3509
3510                 if (!search_notify(type, field, &j) )
3511                         continue;
3512
3513                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3514                                                       struct spoolss_Notify,
3515                                                       info->count + 1);
3516                 if (info->notifies == NULL) {
3517                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3518                         free_a_printer(&printer, 2);
3519                         return False;
3520                 }
3521
3522                 current_data = &info->notifies[info->count];
3523
3524                 construct_info_data(current_data, type, field, id);
3525
3526                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3527                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3528
3529                 notify_info_data_table[j].fn(snum, current_data, queue,
3530                                              printer, mem_ctx);
3531
3532                 info->count++;
3533         }
3534
3535         free_a_printer(&printer, 2);
3536         return True;
3537 }
3538
3539 /*******************************************************************
3540  *
3541  * fill a notify_info struct with info asked
3542  *
3543  ********************************************************************/
3544
3545 static bool construct_notify_jobs_info(print_queue_struct *queue,
3546                                        struct spoolss_NotifyInfo *info,
3547                                        NT_PRINTER_INFO_LEVEL *printer,
3548                                        int snum,
3549                                        const struct spoolss_NotifyOptionType *option_type,
3550                                        uint32_t id,
3551                                        TALLOC_CTX *mem_ctx)
3552 {
3553         int field_num,j;
3554         enum spoolss_NotifyType type;
3555         enum spoolss_Field field;
3556         struct spoolss_Notify *current_data;
3557
3558         DEBUG(4,("construct_notify_jobs_info\n"));
3559
3560         type = option_type->type;
3561
3562         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3563                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3564                 option_type->count));
3565
3566         for(field_num=0; field_num<option_type->count; field_num++) {
3567                 field = option_type->fields[field_num];
3568
3569                 if (!search_notify(type, field, &j) )
3570                         continue;
3571
3572                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3573                                                       struct spoolss_Notify,
3574                                                       info->count + 1);
3575                 if (info->notifies == NULL) {
3576                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3577                         return False;
3578                 }
3579
3580                 current_data=&(info->notifies[info->count]);
3581
3582                 construct_info_data(current_data, type, field, id);
3583                 notify_info_data_table[j].fn(snum, current_data, queue,
3584                                              printer, mem_ctx);
3585                 info->count++;
3586         }
3587
3588         return True;
3589 }
3590
3591 /*
3592  * JFM: The enumeration is not that simple, it's even non obvious.
3593  *
3594  * let's take an example: I want to monitor the PRINTER SERVER for
3595  * the printer's name and the number of jobs currently queued.
3596  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3597  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3598  *
3599  * I have 3 printers on the back of my server.
3600  *
3601  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3602  * structures.
3603  *   Number     Data                    Id
3604  *      1       printer 1 name          1
3605  *      2       printer 1 cjob          1
3606  *      3       printer 2 name          2
3607  *      4       printer 2 cjob          2
3608  *      5       printer 3 name          3
3609  *      6       printer 3 name          3
3610  *
3611  * that's the print server case, the printer case is even worse.
3612  */
3613
3614 /*******************************************************************
3615  *
3616  * enumerate all printers on the printserver
3617  * fill a notify_info struct with info asked
3618  *
3619  ********************************************************************/
3620
3621 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3622                                       struct spoolss_NotifyInfo *info,
3623                                       TALLOC_CTX *mem_ctx)
3624 {
3625         int snum;
3626         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3627         int n_services=lp_numservices();
3628         int i;
3629         struct spoolss_NotifyOption *option;
3630         struct spoolss_NotifyOptionType option_type;
3631
3632         DEBUG(4,("printserver_notify_info\n"));
3633
3634         if (!Printer)
3635                 return WERR_BADFID;
3636
3637         option = Printer->notify.option;
3638
3639         info->version   = 2;
3640         info->notifies  = NULL;
3641         info->count     = 0;
3642
3643         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3644            sending a ffpcn() request first */
3645
3646         if ( !option )
3647                 return WERR_BADFID;
3648
3649         for (i=0; i<option->count; i++) {
3650                 option_type = option->types[i];
3651
3652                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3653                         continue;
3654
3655                 for (snum=0; snum<n_services; snum++)
3656                 {
3657                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3658                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3659                 }
3660         }
3661
3662 #if 0
3663         /*
3664          * Debugging information, don't delete.
3665          */
3666
3667         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3668         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3669         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3670
3671         for (i=0; i<info->count; i++) {
3672                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3673                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3674                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3675         }
3676 #endif
3677
3678         return WERR_OK;
3679 }
3680
3681 /*******************************************************************
3682  *
3683  * fill a notify_info struct with info asked
3684  *
3685  ********************************************************************/
3686
3687 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3688                                   TALLOC_CTX *mem_ctx)
3689 {
3690         int snum;
3691         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3692         int i;
3693         uint32 id;
3694         struct spoolss_NotifyOption *option;
3695         struct spoolss_NotifyOptionType option_type;
3696         int count,j;
3697         print_queue_struct *queue=NULL;
3698         print_status_struct status;
3699
3700         DEBUG(4,("printer_notify_info\n"));
3701
3702         if (!Printer)
3703                 return WERR_BADFID;
3704
3705         option = Printer->notify.option;
3706         id = 0x0;
3707
3708         info->version   = 2;
3709         info->notifies  = NULL;
3710         info->count     = 0;
3711
3712         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3713            sending a ffpcn() request first */
3714
3715         if ( !option )
3716                 return WERR_BADFID;
3717
3718         get_printer_snum(p, hnd, &snum, NULL);
3719
3720         for (i=0; i<option->count; i++) {
3721                 option_type = option->types[i];
3722
3723                 switch (option_type.type) {
3724                 case PRINTER_NOTIFY_TYPE:
3725                         if(construct_notify_printer_info(Printer, info, snum,
3726                                                          &option_type, id,
3727                                                          mem_ctx))
3728                                 id--;
3729                         break;
3730
3731                 case JOB_NOTIFY_TYPE: {
3732                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3733
3734                         count = print_queue_status(snum, &queue, &status);
3735
3736                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3737                                 goto done;
3738
3739                         for (j=0; j<count; j++) {
3740                                 construct_notify_jobs_info(&queue[j], info,
3741                                                            printer, snum,
3742                                                            &option_type,
3743                                                            queue[j].job,
3744                                                            mem_ctx);
3745                         }
3746
3747                         free_a_printer(&printer, 2);
3748
3749                 done:
3750                         SAFE_FREE(queue);
3751                         break;
3752                 }
3753                 }
3754         }
3755
3756         /*
3757          * Debugging information, don't delete.
3758          */
3759         /*
3760         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3761         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3762         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3763
3764         for (i=0; i<info->count; i++) {
3765                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3766                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3767                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3768         }
3769         */
3770         return WERR_OK;
3771 }
3772
3773 /****************************************************************
3774  _spoolss_RouterRefreshPrinterChangeNotify
3775 ****************************************************************/
3776
3777 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3778                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3779 {
3780         POLICY_HND *handle = r->in.handle;
3781         struct spoolss_NotifyInfo *info;
3782
3783         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3784         WERROR result = WERR_BADFID;
3785
3786         /* we always have a spoolss_NotifyInfo struct */
3787         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3788         if (!info) {
3789                 result = WERR_NOMEM;
3790                 goto done;
3791         }
3792
3793         *r->out.info = info;
3794
3795         if (!Printer) {
3796                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3797                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
3798                 goto done;
3799         }
3800
3801         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3802
3803         /*
3804          *      We are now using the change value, and
3805          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3806          *      I don't have a global notification system, I'm sending back all the
3807          *      informations even when _NOTHING_ has changed.
3808          */
3809
3810         /* We need to keep track of the change value to send back in
3811            RRPCN replies otherwise our updates are ignored. */
3812
3813         Printer->notify.fnpcn = True;
3814
3815         if (Printer->notify.client_connected) {
3816                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3817                         "Saving change value in request [%x]\n",
3818                         r->in.change_low));
3819                 Printer->notify.change = r->in.change_low;
3820         }
3821
3822         /* just ignore the spoolss_NotifyOption */
3823
3824         switch (Printer->printer_type) {
3825                 case SPLHND_SERVER:
3826                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3827                         break;
3828
3829                 case SPLHND_PRINTER:
3830                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3831                         break;
3832         }
3833
3834         Printer->notify.fnpcn = False;
3835
3836 done:
3837         return result;
3838 }
3839
3840 /********************************************************************
3841  * construct_printer_info_0
3842  * fill a printer_info_0 struct
3843  ********************************************************************/
3844
3845 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3846                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3847                                       struct spoolss_PrinterInfo0 *r,
3848                                       int snum)
3849 {
3850         int count;
3851         counter_printer_0 *session_counter;
3852         time_t setuptime;
3853         print_status_struct status;
3854
3855         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3856         W_ERROR_HAVE_NO_MEMORY(r->printername);
3857
3858         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3859         W_ERROR_HAVE_NO_MEMORY(r->servername);
3860
3861         count = print_queue_length(snum, &status);
3862
3863         /* check if we already have a counter for this printer */
3864         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3865                 if (session_counter->snum == snum)
3866                         break;
3867         }
3868
3869         /* it's the first time, add it to the list */
3870         if (session_counter == NULL) {
3871                 session_counter = SMB_MALLOC_P(counter_printer_0);
3872                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3873                 ZERO_STRUCTP(session_counter);
3874                 session_counter->snum           = snum;
3875                 session_counter->counter        = 0;
3876                 DLIST_ADD(counter_list, session_counter);
3877         }
3878
3879         /* increment it */
3880         session_counter->counter++;
3881
3882         r->cjobs                        = count;
3883         r->total_jobs                   = 0;
3884         r->total_bytes                  = 0;
3885
3886         setuptime = (time_t)ntprinter->info_2->setuptime;
3887
3888         init_systemtime(&r->time, gmtime(&setuptime));
3889
3890         /* JFM:
3891          * the global_counter should be stored in a TDB as it's common to all the clients
3892          * and should be zeroed on samba startup
3893          */
3894         r->global_counter               = session_counter->counter;
3895         r->total_pages                  = 0;
3896         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3897         r->version                      = 0x0005;       /* NT 5 */
3898         r->free_build                   = 0x0893;       /* build 2195 */
3899         r->spooling                     = 0;
3900         r->max_spooling                 = 0;
3901         r->session_counter              = session_counter->counter;
3902         r->num_error_out_of_paper       = 0x0;
3903         r->num_error_not_ready          = 0x0;          /* number of print failure */
3904         r->job_error                    = 0x0;
3905         r->number_of_processors         = 0x1;
3906         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3907         r->high_part_total_bytes        = 0x0;
3908         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3909         r->last_error                   = WERR_OK;
3910         r->status                       = nt_printq_status(status.status);
3911         r->enumerate_network_printers   = 0x0;
3912         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3913         r->processor_architecture       = 0x0;
3914         r->processor_level              = 0x6;          /* 6  ???*/
3915         r->ref_ic                       = 0;
3916         r->reserved2                    = 0;
3917         r->reserved3                    = 0;
3918
3919         return WERR_OK;
3920 }
3921
3922 /****************************************************************************
3923  Free a DEVMODE struct.
3924 ****************************************************************************/
3925
3926 static void free_dev_mode(DEVICEMODE *dev)
3927 {
3928         if (dev == NULL)
3929                 return;
3930
3931         SAFE_FREE(dev->dev_private);
3932         SAFE_FREE(dev);
3933 }
3934
3935 /****************************************************************************
3936  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3937  should be valid upon entry
3938 ****************************************************************************/
3939
3940 static WERROR convert_nt_devicemode_new(TALLOC_CTX *mem_ctx,
3941                                         struct spoolss_DeviceMode *r,
3942                                         const NT_DEVICEMODE *ntdevmode)
3943 {
3944         if (!r || !ntdevmode) {
3945                 return WERR_INVALID_PARAM;
3946         }
3947
3948         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3949         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3950
3951         r->specversion          = ntdevmode->specversion;
3952         r->driverversion        = ntdevmode->driverversion;
3953         r->size                 = ntdevmode->size;
3954         r->__driverextra_length = ntdevmode->driverextra;
3955         r->fields               = ntdevmode->fields;
3956
3957         r->orientation          = ntdevmode->orientation;
3958         r->papersize            = ntdevmode->papersize;
3959         r->paperlength          = ntdevmode->paperlength;
3960         r->paperwidth           = ntdevmode->paperwidth;
3961         r->scale                = ntdevmode->scale;
3962         r->copies               = ntdevmode->copies;
3963         r->defaultsource        = ntdevmode->defaultsource;
3964         r->printquality         = ntdevmode->printquality;
3965         r->color                = ntdevmode->color;
3966         r->duplex               = ntdevmode->duplex;
3967         r->yresolution          = ntdevmode->yresolution;
3968         r->ttoption             = ntdevmode->ttoption;
3969         r->collate              = ntdevmode->collate;
3970
3971         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3972         W_ERROR_HAVE_NO_MEMORY(r->formname);
3973
3974         /* all 0 below are values that have not been set in the old parsing/copy
3975          * function, maybe they should... - gd */
3976
3977         r->logpixels            = 0;
3978         r->bitsperpel           = 0;
3979         r->pelswidth            = 0;
3980         r->pelsheight           = 0;
3981         r->displayflags         = 0;
3982         r->displayfrequency     = 0;
3983         r->icmmethod            = ntdevmode->icmmethod;
3984         r->icmintent            = ntdevmode->icmintent;
3985         r->mediatype            = ntdevmode->mediatype;
3986         r->dithertype           = ntdevmode->dithertype;
3987         r->reserved1            = 0;
3988         r->reserved2            = 0;
3989         r->panningwidth         = 0;
3990         r->panningheight        = 0;
3991
3992         if (ntdevmode->nt_dev_private != NULL) {
3993                 r->driverextra_data = data_blob_talloc(mem_ctx,
3994                         ntdevmode->nt_dev_private,
3995                         ntdevmode->driverextra);
3996                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3997         }
3998
3999         return WERR_OK;
4000 }
4001
4002
4003 /****************************************************************************
4004  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4005  should be valid upon entry
4006 ****************************************************************************/
4007
4008 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4009 {
4010         if ( !devmode || !ntdevmode )
4011                 return False;
4012
4013         init_unistr(&devmode->devicename, ntdevmode->devicename);
4014
4015         init_unistr(&devmode->formname, ntdevmode->formname);
4016
4017         devmode->specversion      = ntdevmode->specversion;
4018         devmode->driverversion    = ntdevmode->driverversion;
4019         devmode->size             = ntdevmode->size;
4020         devmode->driverextra      = ntdevmode->driverextra;
4021         devmode->fields           = ntdevmode->fields;
4022
4023         devmode->orientation      = ntdevmode->orientation;
4024         devmode->papersize        = ntdevmode->papersize;
4025         devmode->paperlength      = ntdevmode->paperlength;
4026         devmode->paperwidth       = ntdevmode->paperwidth;
4027         devmode->scale            = ntdevmode->scale;
4028         devmode->copies           = ntdevmode->copies;
4029         devmode->defaultsource    = ntdevmode->defaultsource;
4030         devmode->printquality     = ntdevmode->printquality;
4031         devmode->color            = ntdevmode->color;
4032         devmode->duplex           = ntdevmode->duplex;
4033         devmode->yresolution      = ntdevmode->yresolution;
4034         devmode->ttoption         = ntdevmode->ttoption;
4035         devmode->collate          = ntdevmode->collate;
4036         devmode->icmmethod        = ntdevmode->icmmethod;
4037         devmode->icmintent        = ntdevmode->icmintent;
4038         devmode->mediatype        = ntdevmode->mediatype;
4039         devmode->dithertype       = ntdevmode->dithertype;
4040
4041         if (ntdevmode->nt_dev_private != NULL) {
4042                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4043                         return False;
4044         }
4045
4046         return True;
4047 }
4048
4049 /****************************************************************************
4050  Create a spoolss_DeviceMode struct. Returns talloced memory.
4051 ****************************************************************************/
4052
4053 struct spoolss_DeviceMode *construct_dev_mode_new(TALLOC_CTX *mem_ctx,
4054                                                   const char *servicename)
4055 {
4056         WERROR result;
4057         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4058         struct spoolss_DeviceMode *devmode = NULL;
4059
4060         DEBUG(7,("construct_dev_mode_new\n"));
4061
4062         DEBUGADD(8,("getting printer characteristics\n"));
4063
4064         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4065                 return NULL;
4066
4067         if (!printer->info_2->devmode) {
4068                 DEBUG(5, ("BONG! There was no device mode!\n"));
4069                 goto done;
4070         }
4071
4072         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4073         if (!devmode) {
4074                 DEBUG(2,("construct_dev_mode_new: talloc fail.\n"));
4075                 goto done;
4076         }
4077
4078         DEBUGADD(8,("loading DEVICEMODE\n"));
4079
4080         result = convert_nt_devicemode_new(mem_ctx, devmode, printer->info_2->devmode);
4081         if (!W_ERROR_IS_OK(result)) {
4082                 TALLOC_FREE(devmode);
4083         }
4084
4085 done:
4086         free_a_printer(&printer,2);
4087
4088         return devmode;
4089 }
4090
4091 /****************************************************************************
4092  Create a DEVMODE struct. Returns malloced memory.
4093 ****************************************************************************/
4094
4095 DEVICEMODE *construct_dev_mode(const char *servicename)
4096 {
4097         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4098         DEVICEMODE              *devmode = NULL;
4099
4100         DEBUG(7,("construct_dev_mode\n"));
4101
4102         DEBUGADD(8,("getting printer characteristics\n"));
4103
4104         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4105                 return NULL;
4106
4107         if ( !printer->info_2->devmode ) {
4108                 DEBUG(5, ("BONG! There was no device mode!\n"));
4109                 goto done;
4110         }
4111
4112         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4113                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4114                 goto done;
4115         }
4116
4117         ZERO_STRUCTP(devmode);
4118
4119         DEBUGADD(8,("loading DEVICEMODE\n"));
4120
4121         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4122                 free_dev_mode( devmode );
4123                 devmode = NULL;
4124         }
4125
4126 done:
4127         free_a_printer(&printer,2);
4128
4129         return devmode;
4130 }
4131
4132 /********************************************************************
4133  * construct_printer_info3
4134  * fill a spoolss_PrinterInfo3 struct
4135  ********************************************************************/
4136
4137 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4138                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4139                                       struct spoolss_PrinterInfo3 *r,
4140                                       int snum)
4141 {
4142         /* These are the components of the SD we are returning. */
4143
4144         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4145                 /* don't use talloc_steal() here unless you do a deep steal of all
4146                    the SEC_DESC members */
4147
4148                 r->secdesc = dup_sec_desc(mem_ctx,
4149                                           ntprinter->info_2->secdesc_buf->sd);
4150                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4151         }
4152
4153         return WERR_OK;
4154 }
4155
4156 /********************************************************************
4157  * construct_printer_info4
4158  * fill a spoolss_PrinterInfo4 struct
4159  ********************************************************************/
4160
4161 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4162                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4163                                       struct spoolss_PrinterInfo4 *r,
4164                                       int snum)
4165 {
4166         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4167         W_ERROR_HAVE_NO_MEMORY(r->printername);
4168         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4169         W_ERROR_HAVE_NO_MEMORY(r->servername);
4170
4171         r->attributes   = ntprinter->info_2->attributes;
4172
4173         return WERR_OK;
4174 }
4175
4176 /********************************************************************
4177  * construct_printer_info5
4178  * fill a spoolss_PrinterInfo5 struct
4179  ********************************************************************/
4180
4181 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4182                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4183                                       struct spoolss_PrinterInfo5 *r,
4184                                       int snum)
4185 {
4186         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4187         W_ERROR_HAVE_NO_MEMORY(r->printername);
4188         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4189         W_ERROR_HAVE_NO_MEMORY(r->portname);
4190
4191         r->attributes   = ntprinter->info_2->attributes;
4192
4193         /* these two are not used by NT+ according to MSDN */
4194
4195         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4196         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4197
4198         return WERR_OK;
4199 }
4200
4201 /********************************************************************
4202  * construct_printer_info_6
4203  * fill a spoolss_PrinterInfo6 struct
4204  ********************************************************************/
4205
4206 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4207                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4208                                       struct spoolss_PrinterInfo6 *r,
4209                                       int snum)
4210 {
4211         int count;
4212         print_status_struct status;
4213
4214         count = print_queue_length(snum, &status);
4215
4216         r->status = nt_printq_status(status.status);
4217
4218         return WERR_OK;
4219 }
4220
4221 /********************************************************************
4222  * construct_printer_info7
4223  * fill a spoolss_PrinterInfo7 struct
4224  ********************************************************************/
4225
4226 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4227                                       Printer_entry *print_hnd,
4228                                       struct spoolss_PrinterInfo7 *r,
4229                                       int snum)
4230 {
4231         struct GUID guid;
4232
4233         if (is_printer_published(print_hnd, snum, &guid)) {
4234                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4235                 r->action = DSPRINT_PUBLISH;
4236         } else {
4237                 r->guid = talloc_strdup(mem_ctx, "");
4238                 r->action = DSPRINT_UNPUBLISH;
4239         }
4240         W_ERROR_HAVE_NO_MEMORY(r->guid);
4241
4242         return WERR_OK;
4243 }
4244
4245 /********************************************************************
4246  * construct_printer_info1
4247  * fill a spoolss_PrinterInfo1 struct
4248 ********************************************************************/
4249
4250 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4251                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4252                                       uint32_t flags,
4253                                       struct spoolss_PrinterInfo1 *r,
4254                                       int snum)
4255 {
4256         char *chaine = NULL;
4257         r->flags                = flags;
4258
4259         if (*ntprinter->info_2->comment == '\0') {
4260                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4261                 chaine = talloc_asprintf(mem_ctx,
4262                                 "%s,%s,%s", ntprinter->info_2->printername,
4263                                 ntprinter->info_2->drivername, lp_comment(snum));
4264         } else {
4265                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4266                 chaine = talloc_asprintf(mem_ctx,
4267                                 "%s,%s,%s", ntprinter->info_2->printername,
4268                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4269         }
4270         W_ERROR_HAVE_NO_MEMORY(chaine);
4271         W_ERROR_HAVE_NO_MEMORY(r->comment);
4272
4273         r->description          = talloc_strdup(mem_ctx, chaine);
4274         W_ERROR_HAVE_NO_MEMORY(r->description);
4275         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4276         W_ERROR_HAVE_NO_MEMORY(r->name);
4277
4278         return WERR_OK;
4279 }
4280
4281 /********************************************************************
4282  * construct_printer_info2
4283  * fill a spoolss_PrinterInfo2 struct
4284 ********************************************************************/
4285
4286 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4287                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4288                                       struct spoolss_PrinterInfo2 *r,
4289                                       int snum)
4290 {
4291         int count;
4292
4293         print_status_struct status;
4294
4295         count = print_queue_length(snum, &status);
4296
4297         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4298         W_ERROR_HAVE_NO_MEMORY(r->servername);
4299         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4300         W_ERROR_HAVE_NO_MEMORY(r->printername);
4301         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4302         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4303         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4304         W_ERROR_HAVE_NO_MEMORY(r->portname);
4305         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4306         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4307
4308         if (*ntprinter->info_2->comment == '\0') {
4309                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4310         } else {
4311                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4312         }
4313         W_ERROR_HAVE_NO_MEMORY(r->comment);
4314
4315         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4316         W_ERROR_HAVE_NO_MEMORY(r->location);
4317         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4318         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4319         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4320         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4321         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4322         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4323         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4324         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4325
4326         r->attributes           = ntprinter->info_2->attributes;
4327
4328         r->priority             = ntprinter->info_2->priority;
4329         r->defaultpriority      = ntprinter->info_2->default_priority;
4330         r->starttime            = ntprinter->info_2->starttime;
4331         r->untiltime            = ntprinter->info_2->untiltime;
4332         r->status               = nt_printq_status(status.status);
4333         r->cjobs                = count;
4334         r->averageppm           = ntprinter->info_2->averageppm;
4335
4336         r->devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
4337         if (!r->devmode) {
4338                 DEBUG(8,("Returning NULL Devicemode!\n"));
4339         }
4340
4341         r->secdesc              = NULL;
4342
4343         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4344                 /* don't use talloc_steal() here unless you do a deep steal of all
4345                    the SEC_DESC members */
4346
4347                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4348         }
4349
4350         return WERR_OK;
4351 }
4352
4353 /********************************************************************
4354 ********************************************************************/
4355
4356 static bool snum_is_shared_printer(int snum)
4357 {
4358         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4359 }
4360
4361 /********************************************************************
4362  Spoolss_enumprinters.
4363 ********************************************************************/
4364
4365 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4366                                        uint32_t flags,
4367                                        union spoolss_PrinterInfo **info_p,
4368                                        uint32_t *count)
4369 {
4370         int snum;
4371         int n_services = lp_numservices();
4372         union spoolss_PrinterInfo *info = NULL;
4373         WERROR result = WERR_OK;
4374
4375         DEBUG(4,("enum_all_printers_info_1\n"));
4376
4377         *count = 0;
4378
4379         for (snum=0; snum<n_services; snum++) {
4380
4381                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4382                 struct spoolss_PrinterInfo1 info1;
4383
4384                 if (!snum_is_shared_printer(snum)) {
4385                         continue;
4386                 }
4387
4388                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4389
4390                 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4391                 if (!W_ERROR_IS_OK(result)) {
4392                         continue;
4393                 }
4394
4395                 result = construct_printer_info1(info, ntprinter, flags, &info1, snum);
4396                 free_a_printer(&ntprinter,2);
4397                 if (!W_ERROR_IS_OK(result)) {
4398                         continue;
4399                 }
4400
4401                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4402                                             union spoolss_PrinterInfo,
4403                                             *count + 1);
4404                 if (!info) {
4405                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4406                         result = WERR_NOMEM;
4407                         goto out;
4408                 }
4409
4410                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *count));
4411
4412                 info[*count].info1 = info1;
4413                 (*count)++;
4414         }
4415
4416  out:
4417         if (!W_ERROR_IS_OK(result)) {
4418                 TALLOC_FREE(info);
4419                 *count = 0;
4420                 return result;
4421         }
4422
4423         *info_p = info;
4424
4425         return WERR_OK;
4426 }
4427
4428 /********************************************************************
4429  enum_all_printers_info_1_local.
4430 *********************************************************************/
4431
4432 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4433                                              union spoolss_PrinterInfo **info,
4434                                              uint32_t *count)
4435 {
4436         DEBUG(4,("enum_all_printers_info_1_local\n"));
4437
4438         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4439 }
4440
4441 /********************************************************************
4442  enum_all_printers_info_1_name.
4443 *********************************************************************/
4444
4445 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4446                                             const char *name,
4447                                             union spoolss_PrinterInfo **info,
4448                                             uint32_t *count)
4449 {
4450         const char *s = name;
4451
4452         DEBUG(4,("enum_all_printers_info_1_name\n"));
4453
4454         if ((name[0] == '\\') && (name[1] == '\\')) {
4455                 s = name + 2;
4456         }
4457
4458         if (!is_myname_or_ipaddr(s)) {
4459                 return WERR_INVALID_NAME;
4460         }
4461
4462         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4463 }
4464
4465 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4466 /********************************************************************
4467  enum_all_printers_info_1_remote.
4468 *********************************************************************/
4469
4470 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4471 {
4472         PRINTER_INFO_1 *printer;
4473         fstring printername;
4474         fstring desc;
4475         fstring comment;
4476         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4477         WERROR result = WERR_OK;
4478
4479         /* JFM: currently it's more a place holder than anything else.
4480          * In the spooler world there is a notion of server registration.
4481          * the print servers are registered on the PDC (in the same domain)
4482          *
4483          * We should have a TDB here. The registration is done thru an
4484          * undocumented RPC call.
4485          */
4486
4487         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4488                 return WERR_NOMEM;
4489
4490         *returned=1;
4491
4492         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4493         slprintf(desc, sizeof(desc)-1,"%s", name);
4494         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4495
4496         init_unistr(&printer->description, desc);
4497         init_unistr(&printer->name, printername);
4498         init_unistr(&printer->comment, comment);
4499         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4500
4501         /* check the required size. */
4502         *needed += spoolss_size_printer_info_1(printer);
4503
4504         if (*needed > offered) {
4505                 result = WERR_INSUFFICIENT_BUFFER;
4506                 goto out;
4507         }
4508
4509         if (!rpcbuf_alloc_size(buffer, *needed)) {
4510                 result = WERR_NOMEM;
4511                 goto out;
4512         }
4513
4514         /* fill the buffer with the structures */
4515         smb_io_printer_info_1("", buffer, printer, 0);
4516
4517 out:
4518         /* clear memory */
4519         SAFE_FREE(printer);
4520
4521         if ( !W_ERROR_IS_OK(result) )
4522                 *returned = 0;
4523
4524         return result;
4525 }
4526
4527 #endif
4528
4529 /********************************************************************
4530  enum_all_printers_info_1_network.
4531 *********************************************************************/
4532
4533 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4534                                                const char *name,
4535                                                union spoolss_PrinterInfo **info,
4536                                                uint32_t *count)
4537 {
4538         const char *s = name;
4539
4540         DEBUG(4,("enum_all_printers_info_1_network\n"));
4541
4542         /* If we respond to a enum_printers level 1 on our name with flags
4543            set to PRINTER_ENUM_REMOTE with a list of printers then these
4544            printers incorrectly appear in the APW browse list.
4545            Specifically the printers for the server appear at the workgroup
4546            level where all the other servers in the domain are
4547            listed. Windows responds to this call with a
4548            WERR_CAN_NOT_COMPLETE so we should do the same. */
4549
4550         if (name[0] == '\\' && name[1] == '\\') {
4551                  s = name + 2;
4552         }
4553
4554         if (is_myname_or_ipaddr(s)) {
4555                  return WERR_CAN_NOT_COMPLETE;
4556         }
4557
4558         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4559 }
4560
4561 /********************************************************************
4562  * api_spoolss_enumprinters
4563  *
4564  * called from api_spoolss_enumprinters (see this to understand)
4565  ********************************************************************/
4566
4567 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4568                                        union spoolss_PrinterInfo **info_p,
4569                                        uint32_t *count)
4570 {
4571         int snum;
4572         int n_services = lp_numservices();
4573         union spoolss_PrinterInfo *info = NULL;
4574         WERROR result = WERR_OK;
4575
4576         *count = 0;
4577
4578         for (snum=0; snum<n_services; snum++) {
4579
4580                 struct spoolss_PrinterInfo2 info2;
4581                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4582
4583                 if (!snum_is_shared_printer(snum)) {
4584                         continue;
4585                 }
4586
4587                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4588
4589                 result = get_a_printer(NULL, &ntprinter, 2, lp_const_servicename(snum));
4590                 if (!W_ERROR_IS_OK(result)) {
4591                         continue;
4592                 }
4593
4594                 result = construct_printer_info2(info, ntprinter, &info2, snum);
4595                 free_a_printer(&ntprinter, 2);
4596                 if (!W_ERROR_IS_OK(result)) {
4597                         continue;
4598                 }
4599
4600                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4601                                             union spoolss_PrinterInfo,
4602                                             *count + 1);
4603                 if (!info) {
4604                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4605                         result = WERR_NOMEM;
4606                         goto out;
4607                 }
4608
4609                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *count + 1));
4610
4611                 info[*count].info2 = info2;
4612
4613                 (*count)++;
4614         }
4615
4616  out:
4617         if (!W_ERROR_IS_OK(result)) {
4618                 TALLOC_FREE(info);
4619                 *count = 0;
4620                 return result;
4621         }
4622
4623         *info_p = info;
4624
4625         return WERR_OK;
4626 }
4627
4628 /********************************************************************
4629  * handle enumeration of printers at level 1
4630  ********************************************************************/
4631
4632 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4633                                   uint32_t flags,
4634                                   const char *name,
4635                                   union spoolss_PrinterInfo **info,
4636                                   uint32_t *count)
4637 {
4638         /* Not all the flags are equals */
4639
4640         if (flags & PRINTER_ENUM_LOCAL) {
4641                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4642         }
4643
4644         if (flags & PRINTER_ENUM_NAME) {
4645                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4646         }
4647
4648 #if 0   /* JERRY - disabled for now */
4649         if (flags & PRINTER_ENUM_REMOTE) {
4650                 return enum_all_printers_info_1_remote(mem_ctx, name, info, count);
4651         }
4652 #endif
4653
4654         if (flags & PRINTER_ENUM_NETWORK) {
4655                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4656         }
4657
4658         return WERR_OK; /* NT4sp5 does that */
4659 }
4660
4661 /********************************************************************
4662  * handle enumeration of printers at level 2
4663  ********************************************************************/
4664
4665 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4666                                   uint32_t flags,
4667                                   const char *servername,
4668                                   union spoolss_PrinterInfo **info,
4669                                   uint32_t *count)
4670 {
4671         if (flags & PRINTER_ENUM_LOCAL) {
4672                 return enum_all_printers_info_2(mem_ctx, info, count);
4673         }
4674
4675         if (flags & PRINTER_ENUM_NAME) {
4676                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4677                         return WERR_INVALID_NAME;
4678                 }
4679
4680                 return enum_all_printers_info_2(mem_ctx, info, count);
4681         }
4682
4683         if (flags & PRINTER_ENUM_REMOTE) {
4684                 return WERR_UNKNOWN_LEVEL;
4685         }
4686
4687         return WERR_OK;
4688 }
4689
4690 /********************************************************************
4691  * handle enumeration of printers at level 5
4692  ********************************************************************/
4693
4694 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4695                                   uint32_t flags,
4696                                   const char *servername,
4697                                   union spoolss_PrinterInfo **info,
4698                                   uint32_t *count)
4699 {
4700 /*      return enum_all_printers_info_5(mem_ctx, info, offered, needed, count);*/
4701         return WERR_OK;
4702 }
4703
4704 /****************************************************************
4705  _spoolss_EnumPrinters
4706 ****************************************************************/
4707
4708 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4709                              struct spoolss_EnumPrinters *r)
4710 {
4711         const char *name;
4712         WERROR result;
4713
4714         /* that's an [in out] buffer */
4715
4716         if (!r->in.buffer && (r->in.offered != 0)) {
4717                 return WERR_INVALID_PARAM;
4718         }
4719
4720         DEBUG(4,("_spoolss_EnumPrinters\n"));
4721
4722         *r->out.needed = 0;
4723         *r->out.count = 0;
4724         *r->out.info = NULL;
4725
4726         /*
4727          * Level 1:
4728          *          flags==PRINTER_ENUM_NAME
4729          *           if name=="" then enumerates all printers
4730          *           if name!="" then enumerate the printer
4731          *          flags==PRINTER_ENUM_REMOTE
4732          *          name is NULL, enumerate printers
4733          * Level 2: name!="" enumerates printers, name can't be NULL
4734          * Level 3: doesn't exist
4735          * Level 4: does a local registry lookup
4736          * Level 5: same as Level 2
4737          */
4738
4739         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4740         W_ERROR_HAVE_NO_MEMORY(name);
4741
4742         switch (r->in.level) {
4743         case 1:
4744                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4745                                              r->out.info, r->out.count);
4746                 break;
4747         case 2:
4748                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4749                                              r->out.info, r->out.count);
4750                 break;
4751         case 5:
4752                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4753                                              r->out.info, r->out.count);
4754                 break;
4755         case 3:
4756         case 4:
4757                 result = WERR_OK; /* ??? */
4758                 break;
4759         default:
4760                 return WERR_UNKNOWN_LEVEL;
4761         }
4762
4763         if (!W_ERROR_IS_OK(result)) {
4764                 return result;
4765         }
4766
4767         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4768                                                      spoolss_EnumPrinters, NULL,
4769                                                      *r->out.info, r->in.level,
4770                                                      *r->out.count);
4771         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4772         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4773
4774         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4775 }
4776
4777 /****************************************************************
4778  _spoolss_GetPrinter
4779 ****************************************************************/
4780
4781 WERROR _spoolss_GetPrinter(pipes_struct *p,
4782                            struct spoolss_GetPrinter *r)
4783 {
4784         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4785         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4786         WERROR result = WERR_OK;
4787
4788         int snum;
4789
4790         /* that's an [in out] buffer */
4791
4792         if (!r->in.buffer && (r->in.offered != 0)) {
4793                 return WERR_INVALID_PARAM;
4794         }
4795
4796         *r->out.needed = 0;
4797
4798         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4799                 return WERR_BADFID;
4800         }
4801
4802         result = get_a_printer(Printer, &ntprinter, 2,
4803                                lp_const_servicename(snum));
4804         if (!W_ERROR_IS_OK(result)) {
4805                 return result;
4806         }
4807
4808         switch (r->in.level) {
4809         case 0:
4810                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4811                                                  &r->out.info->info0, snum);
4812                 break;
4813         case 1:
4814                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4815                                                  PRINTER_ENUM_ICON8,
4816                                                  &r->out.info->info1, snum);
4817                 break;
4818         case 2:
4819                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4820                                                  &r->out.info->info2, snum);
4821                 break;
4822         case 3:
4823                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4824                                                  &r->out.info->info3, snum);
4825                 break;
4826         case 4:
4827                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4828                                                  &r->out.info->info4, snum);
4829                 break;
4830         case 5:
4831                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4832                                                  &r->out.info->info5, snum);
4833                 break;
4834         case 6:
4835                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4836                                                  &r->out.info->info6, snum);
4837                 break;
4838         case 7:
4839                 result = construct_printer_info7(p->mem_ctx, Printer,
4840                                                  &r->out.info->info7, snum);
4841                 break;
4842         default:
4843                 result = WERR_UNKNOWN_LEVEL;
4844                 break;
4845         }
4846
4847         free_a_printer(&ntprinter, 2);
4848
4849         if (!W_ERROR_IS_OK(result)) {
4850                 TALLOC_FREE(r->out.info);
4851                 return result;
4852         }
4853
4854         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4855                                                r->out.info, r->in.level);
4856         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4857
4858         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4859 }
4860
4861 /********************************************************************
4862  ********************************************************************/
4863
4864 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4865                                                   fstring *fstring_array,
4866                                                   const char *cservername)
4867 {
4868         int i, num_strings = 0;
4869         const char **array = NULL;
4870
4871         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4872
4873                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4874                                                   cservername, fstring_array[i]);
4875                 if (!str) {
4876                         TALLOC_FREE(array);
4877                         return NULL;
4878                 }
4879
4880
4881                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4882                         TALLOC_FREE(array);
4883                         return NULL;
4884                 }
4885         }
4886
4887         if (i > 0) {
4888                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4889                              &array, &num_strings);
4890         }
4891
4892         return array;
4893 }
4894
4895 /********************************************************************
4896  * fill a spoolss_DriverInfo1 struct
4897  ********************************************************************/
4898
4899 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4900                                         struct spoolss_DriverInfo1 *r,
4901                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4902                                         const char *servername,
4903                                         const char *architecture)
4904 {
4905         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4906         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4907
4908         return WERR_OK;
4909 }
4910
4911 /********************************************************************
4912  * fill a spoolss_DriverInfo2 struct
4913  ********************************************************************/
4914
4915 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4916                                         struct spoolss_DriverInfo2 *r,
4917                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4918                                         const char *servername)
4919
4920 {
4921         const char *cservername = canon_servername(servername);
4922
4923         r->version              = driver->info_3->cversion;
4924
4925         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4926         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4927         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4928         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4929
4930         if (strlen(driver->info_3->driverpath)) {
4931                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4932                                 cservername, driver->info_3->driverpath);
4933         } else {
4934                 r->driver_path  = talloc_strdup(mem_ctx, "");
4935         }
4936         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4937
4938         if (strlen(driver->info_3->datafile)) {
4939                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4940                                 cservername, driver->info_3->datafile);
4941         } else {
4942                 r->data_file    = talloc_strdup(mem_ctx, "");
4943         }
4944         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4945
4946         if (strlen(driver->info_3->configfile)) {
4947                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4948                                 cservername, driver->info_3->configfile);
4949         } else {
4950                 r->config_file  = talloc_strdup(mem_ctx, "");
4951         }
4952         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4953
4954         return WERR_OK;
4955 }
4956
4957 /********************************************************************
4958  * fill a spoolss_DriverInfo3 struct
4959  ********************************************************************/
4960
4961 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4962                                         struct spoolss_DriverInfo3 *r,
4963                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4964                                         const char *servername)
4965 {
4966         const char *cservername = canon_servername(servername);
4967
4968         r->version              = driver->info_3->cversion;
4969
4970         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4971         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4972         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4973         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4974
4975         if (strlen(driver->info_3->driverpath)) {
4976                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4977                                 cservername, driver->info_3->driverpath);
4978         } else {
4979                 r->driver_path  = talloc_strdup(mem_ctx, "");
4980         }
4981         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4982
4983         if (strlen(driver->info_3->datafile)) {
4984                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4985                                 cservername, driver->info_3->datafile);
4986         } else {
4987                 r->data_file    = talloc_strdup(mem_ctx, "");
4988         }
4989         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4990
4991         if (strlen(driver->info_3->configfile)) {
4992                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4993                                 cservername, driver->info_3->configfile);
4994         } else {
4995                 r->config_file  = talloc_strdup(mem_ctx, "");
4996         }
4997         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4998
4999         if (strlen(driver->info_3->helpfile)) {
5000                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5001                                 cservername, driver->info_3->helpfile);
5002         } else {
5003                 r->help_file    = talloc_strdup(mem_ctx, "");
5004         }
5005         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5006
5007         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5008         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5009         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5010         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5011
5012         r->dependent_files = string_array_from_driver_info(mem_ctx,
5013                                                            driver->info_3->dependentfiles,
5014                                                            cservername);
5015         return WERR_OK;
5016 }
5017
5018 /********************************************************************
5019  * fill a spoolss_DriverInfo6 struct
5020  ********************************************************************/
5021
5022 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5023                                         struct spoolss_DriverInfo6 *r,
5024                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5025                                         const char *servername)
5026 {
5027         const char *cservername = canon_servername(servername);
5028
5029         r->version              = driver->info_3->cversion;
5030
5031         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5032         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5033         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5034         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5035
5036         if (strlen(driver->info_3->driverpath)) {
5037                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5038                                 cservername, driver->info_3->driverpath);
5039         } else {
5040                 r->driver_path  = talloc_strdup(mem_ctx, "");
5041         }
5042         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
5043
5044         if (strlen(driver->info_3->datafile)) {
5045                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5046                                 cservername, driver->info_3->datafile);
5047         } else {
5048                 r->data_file    = talloc_strdup(mem_ctx, "");
5049         }
5050         W_ERROR_HAVE_NO_MEMORY(r->data_file);
5051
5052         if (strlen(driver->info_3->configfile)) {
5053                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
5054                                 cservername, driver->info_3->configfile);
5055         } else {
5056                 r->config_file  = talloc_strdup(mem_ctx, "");
5057         }
5058         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5059
5060         if (strlen(driver->info_3->helpfile)) {
5061                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5062                                 cservername, driver->info_3->helpfile);
5063         } else {
5064                 r->help_file    = talloc_strdup(mem_ctx, "");
5065         }
5066         W_ERROR_HAVE_NO_MEMORY(r->config_file);
5067
5068         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5069         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5070         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5071         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5072
5073         r->dependent_files = string_array_from_driver_info(mem_ctx,
5074                                                            driver->info_3->dependentfiles,
5075                                                            cservername);
5076         r->previous_names = string_array_from_driver_info(mem_ctx,
5077                                                           NULL,
5078                                                           cservername);
5079
5080         r->driver_date          = 0;
5081         r->driver_version       = 0;
5082
5083         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5084         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5085         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5086         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5087         r->hardware_id          = talloc_strdup(mem_ctx, "");
5088         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5089         r->provider             = talloc_strdup(mem_ctx, "");
5090         W_ERROR_HAVE_NO_MEMORY(r->provider);
5091
5092         return WERR_OK;
5093 }
5094
5095 /********************************************************************
5096  * construct_printer_driver_info_1
5097  ********************************************************************/
5098
5099 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5100                                               struct spoolss_DriverInfo1 *r,
5101                                               int snum,
5102                                               const char *servername,
5103                                               const char *architecture,
5104                                               uint32_t version)
5105 {
5106         NT_PRINTER_INFO_LEVEL *printer = NULL;
5107         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5108         WERROR result;
5109
5110         ZERO_STRUCT(driver);
5111
5112         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5113                 return WERR_INVALID_PRINTER_NAME;
5114
5115         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5116                 free_a_printer(&printer, 2);
5117                 return WERR_UNKNOWN_PRINTER_DRIVER;
5118         }
5119
5120         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5121
5122         free_a_printer(&printer,2);
5123
5124         return result;
5125 }
5126
5127 /********************************************************************
5128  * construct_printer_driver_info_2
5129  * fill a printer_info_2 struct
5130  ********************************************************************/
5131
5132 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5133                                               struct spoolss_DriverInfo2 *r,
5134                                               int snum,
5135                                               const char *servername,
5136                                               const char *architecture,
5137                                               uint32_t version)
5138 {
5139         NT_PRINTER_INFO_LEVEL *printer = NULL;
5140         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5141         WERROR result;
5142
5143         ZERO_STRUCT(printer);
5144         ZERO_STRUCT(driver);
5145
5146         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5147                 return WERR_INVALID_PRINTER_NAME;
5148
5149         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5150                 free_a_printer(&printer, 2);
5151                 return WERR_UNKNOWN_PRINTER_DRIVER;
5152         }
5153
5154         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5155
5156         free_a_printer(&printer,2);
5157
5158         return result;
5159 }
5160
5161 /********************************************************************
5162  * copy a strings array and convert to UNICODE
5163  *
5164  * convert an array of ascii string to a UNICODE string
5165  ********************************************************************/
5166
5167 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5168 {
5169         int i=0;
5170         int j=0;
5171         const char *v;
5172         char *line = NULL;
5173         TALLOC_CTX *ctx = talloc_tos();
5174
5175         DEBUG(6,("init_unistr_array\n"));
5176         *uni_array=NULL;
5177
5178         while (true) {
5179                 if ( !char_array ) {
5180                         v = "";
5181                 } else {
5182                         v = char_array[i];
5183                         if (!v)
5184                                 v = ""; /* hack to handle null lists */
5185                 }
5186
5187                 /* hack to allow this to be used in places other than when generating
5188                    the list of dependent files */
5189
5190                 TALLOC_FREE(line);
5191                 if ( servername ) {
5192                         line = talloc_asprintf(ctx,
5193                                         "\\\\%s%s",
5194                                         canon_servername(servername),
5195                                         v);
5196                 } else {
5197                         line = talloc_strdup(ctx, v);
5198                 }
5199
5200                 if (!line) {
5201                         SAFE_FREE(*uni_array);
5202                         return 0;
5203                 }
5204                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5205
5206                 /* add one extra unit16 for the second terminating NULL */
5207
5208                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5209                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5210                         return 0;
5211                 }
5212
5213                 if ( !strlen(v) )
5214                         break;
5215
5216                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5217                 i++;
5218         }
5219
5220         if (*uni_array) {
5221                 /* special case for ""; we need to add both NULL's here */
5222                 if (!j)
5223                         (*uni_array)[j++]=0x0000;
5224                 (*uni_array)[j]=0x0000;
5225         }
5226
5227         DEBUGADD(6,("last one:done\n"));
5228
5229         /* return size of array in uint16's */
5230
5231         return j+1;
5232 }
5233
5234 /********************************************************************
5235  * construct_printer_info_3
5236  * fill a printer_info_3 struct
5237  ********************************************************************/
5238
5239 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5240                                               struct spoolss_DriverInfo3 *r,
5241                                               int snum,
5242                                               const char *servername,
5243                                               const char *architecture,
5244                                               uint32_t version)
5245 {
5246         NT_PRINTER_INFO_LEVEL *printer = NULL;
5247         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5248         WERROR status;
5249         ZERO_STRUCT(driver);
5250
5251         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5252         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5253         if (!W_ERROR_IS_OK(status))
5254                 return WERR_INVALID_PRINTER_NAME;
5255
5256         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5257         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5258
5259 #if 0   /* JERRY */
5260
5261         /*
5262          * I put this code in during testing.  Helpful when commenting out the
5263          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5264          * as win2k always queries the driver using an infor level of 6.
5265          * I've left it in (but ifdef'd out) because I'll probably
5266          * use it in experimentation again in the future.   --jerry 22/01/2002
5267          */
5268
5269         if (!W_ERROR_IS_OK(status)) {
5270                 /*
5271                  * Is this a W2k client ?
5272                  */
5273                 if (version == 3) {
5274                         /* Yes - try again with a WinNT driver. */
5275                         version = 2;
5276                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5277                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5278                 }
5279 #endif
5280
5281                 if (!W_ERROR_IS_OK(status)) {
5282                         free_a_printer(&printer,2);
5283                         return WERR_UNKNOWN_PRINTER_DRIVER;
5284                 }
5285
5286 #if 0   /* JERRY */
5287         }
5288 #endif
5289
5290
5291         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5292
5293         free_a_printer(&printer,2);
5294
5295         return status;
5296 }
5297
5298 /********************************************************************
5299  * construct_printer_info_6
5300  * fill a printer_info_6 struct
5301  ********************************************************************/
5302
5303 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5304                                               struct spoolss_DriverInfo6 *r,
5305                                               int snum,
5306                                               const char *servername,
5307                                               const char *architecture,
5308                                               uint32_t version)
5309 {
5310         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5311         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5312         WERROR                          status;
5313
5314         ZERO_STRUCT(driver);
5315
5316         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5317
5318         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5319
5320         if (!W_ERROR_IS_OK(status))
5321                 return WERR_INVALID_PRINTER_NAME;
5322
5323         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5324
5325         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5326
5327         if (!W_ERROR_IS_OK(status))
5328         {
5329                 /*
5330                  * Is this a W2k client ?
5331                  */
5332
5333                 if (version < 3) {
5334                         free_a_printer(&printer,2);
5335                         return WERR_UNKNOWN_PRINTER_DRIVER;
5336                 }
5337
5338                 /* Yes - try again with a WinNT driver. */
5339                 version = 2;
5340                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5341                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5342                 if (!W_ERROR_IS_OK(status)) {
5343                         free_a_printer(&printer,2);
5344                         return WERR_UNKNOWN_PRINTER_DRIVER;
5345                 }
5346         }
5347
5348         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5349
5350         free_a_printer(&printer,2);
5351         free_a_printer_driver(driver, 3);
5352
5353         return status;
5354 }
5355
5356 /****************************************************************
5357  _spoolss_GetPrinterDriver2
5358 ****************************************************************/
5359
5360 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5361                                   struct spoolss_GetPrinterDriver2 *r)
5362 {
5363         Printer_entry *printer;
5364         WERROR result;
5365
5366         const char *servername;
5367         int snum;
5368
5369         /* that's an [in out] buffer */
5370
5371         if (!r->in.buffer && (r->in.offered != 0)) {
5372                 return WERR_INVALID_PARAM;
5373         }
5374
5375         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5376
5377         if (!(printer = find_printer_index_by_hnd( p, r->in.handle))) {
5378                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5379                 return WERR_INVALID_PRINTER_NAME;
5380         }
5381
5382         *r->out.needed = 0;
5383         *r->out.server_major_version = 0;
5384         *r->out.server_minor_version = 0;
5385
5386         servername = get_server_name(printer);
5387
5388         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5389                 return WERR_BADFID;
5390         }
5391
5392         switch (r->in.level) {
5393         case 1:
5394                 result = construct_printer_driver_info_1(p->mem_ctx,
5395                                                          &r->out.info->info1,
5396                                                          snum,
5397                                                          servername,
5398                                                          r->in.architecture,
5399                                                          r->in.client_major_version);
5400                 break;
5401         case 2:
5402                 result = construct_printer_driver_info_2(p->mem_ctx,
5403                                                          &r->out.info->info2,
5404                                                          snum,
5405                                                          servername,
5406                                                          r->in.architecture,
5407                                                          r->in.client_major_version);
5408                 break;
5409         case 3:
5410                 result = construct_printer_driver_info_3(p->mem_ctx,
5411                                                          &r->out.info->info3,
5412                                                          snum,
5413                                                          servername,
5414                                                          r->in.architecture,
5415                                                          r->in.client_major_version);
5416                 break;
5417         case 6:
5418                 result = construct_printer_driver_info_6(p->mem_ctx,
5419                                                          &r->out.info->info6,
5420                                                          snum,
5421                                                          servername,
5422                                                          r->in.architecture,
5423                                                          r->in.client_major_version);
5424                 break;
5425         default:
5426 #if 0   /* JERRY */
5427         case 101:
5428                 /* apparently this call is the equivalent of
5429                    EnumPrinterDataEx() for the DsDriver key */
5430                 break;
5431 #endif
5432                 result = WERR_UNKNOWN_LEVEL;
5433                 break;
5434         }
5435
5436         if (!W_ERROR_IS_OK(result)) {
5437                 TALLOC_FREE(r->out.info);
5438                 return result;
5439         }
5440
5441         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5442                                                r->out.info, r->in.level);
5443         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5444
5445         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5446 }
5447
5448
5449 /****************************************************************
5450  _spoolss_StartPagePrinter
5451 ****************************************************************/
5452
5453 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5454                                  struct spoolss_StartPagePrinter *r)
5455 {
5456         POLICY_HND *handle = r->in.handle;
5457
5458         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5459
5460         if (!Printer) {
5461                 DEBUG(3,("_spoolss_StartPagePrinter: "
5462                         "Error in startpageprinter printer handle\n"));
5463                 return WERR_BADFID;
5464         }
5465
5466         Printer->page_started=True;
5467         return WERR_OK;
5468 }
5469
5470 /****************************************************************
5471  _spoolss_EndPagePrinter
5472 ****************************************************************/
5473
5474 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5475                                struct spoolss_EndPagePrinter *r)
5476 {
5477         POLICY_HND *handle = r->in.handle;
5478         int snum;
5479
5480         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5481
5482         if (!Printer) {
5483                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5484                         OUR_HANDLE(handle)));
5485                 return WERR_BADFID;
5486         }
5487
5488         if (!get_printer_snum(p, handle, &snum, NULL))
5489                 return WERR_BADFID;
5490
5491         Printer->page_started=False;
5492         print_job_endpage(snum, Printer->jobid);
5493
5494         return WERR_OK;
5495 }
5496
5497 /****************************************************************
5498  _spoolss_StartDocPrinter
5499 ****************************************************************/
5500
5501 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5502                                 struct spoolss_StartDocPrinter *r)
5503 {
5504         POLICY_HND *handle = r->in.handle;
5505         uint32_t *jobid = r->out.job_id;
5506         struct spoolss_DocumentInfo1 *info_1;
5507         int snum;
5508         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5509
5510         if (!Printer) {
5511                 DEBUG(2,("_spoolss_StartDocPrinter: "
5512                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5513                 return WERR_BADFID;
5514         }
5515
5516         if (r->in.level != 1) {
5517                 return WERR_UNKNOWN_LEVEL;
5518         }
5519
5520         info_1 = r->in.info.info1;
5521
5522         /*
5523          * a nice thing with NT is it doesn't listen to what you tell it.
5524          * when asked to send _only_ RAW datas, it tries to send datas
5525          * in EMF format.
5526          *
5527          * So I add checks like in NT Server ...
5528          */
5529
5530         if (info_1->datatype) {
5531                 if (strcmp(info_1->datatype, "RAW") != 0) {
5532                         (*jobid)=0;
5533                         return WERR_INVALID_DATATYPE;
5534                 }
5535         }
5536
5537         /* get the share number of the printer */
5538         if (!get_printer_snum(p, handle, &snum, NULL)) {
5539                 return WERR_BADFID;
5540         }
5541
5542         Printer->jobid = print_job_start(p->server_info, snum,
5543                                          info_1->document_name,
5544                                          Printer->nt_devmode);
5545
5546         /* An error occured in print_job_start() so return an appropriate
5547            NT error code. */
5548
5549         if (Printer->jobid == -1) {
5550                 return map_werror_from_unix(errno);
5551         }
5552
5553         Printer->document_started=True;
5554         (*jobid) = Printer->jobid;
5555
5556         return WERR_OK;
5557 }
5558
5559 /****************************************************************
5560  _spoolss_EndDocPrinter
5561 ****************************************************************/
5562
5563 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5564                               struct spoolss_EndDocPrinter *r)
5565 {
5566         POLICY_HND *handle = r->in.handle;
5567
5568         return _spoolss_enddocprinter_internal(p, handle);
5569 }
5570
5571 /****************************************************************
5572  _spoolss_WritePrinter
5573 ****************************************************************/
5574
5575 WERROR _spoolss_WritePrinter(pipes_struct *p,
5576                              struct spoolss_WritePrinter *r)
5577 {
5578         POLICY_HND *handle = r->in.handle;
5579         uint32 buffer_size = r->in._data_size;
5580         uint8 *buffer = r->in.data.data;
5581         uint32 *buffer_written = &r->in._data_size;
5582         int snum;
5583         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5584
5585         if (!Printer) {
5586                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5587                         OUR_HANDLE(handle)));
5588                 *r->out.num_written = r->in._data_size;
5589                 return WERR_BADFID;
5590         }
5591
5592         if (!get_printer_snum(p, handle, &snum, NULL))
5593                 return WERR_BADFID;
5594
5595         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5596                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5597         if (*buffer_written == (uint32)-1) {
5598                 *r->out.num_written = 0;
5599                 if (errno == ENOSPC)
5600                         return WERR_NO_SPOOL_SPACE;
5601                 else
5602                         return WERR_ACCESS_DENIED;
5603         }
5604
5605         *r->out.num_written = r->in._data_size;
5606
5607         return WERR_OK;
5608 }
5609
5610 /********************************************************************
5611  * api_spoolss_getprinter
5612  * called from the spoolss dispatcher
5613  *
5614  ********************************************************************/
5615
5616 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5617                               pipes_struct *p)
5618 {
5619         int snum;
5620         WERROR errcode = WERR_BADFUNC;
5621         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5622
5623         if (!Printer) {
5624                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5625                 return WERR_BADFID;
5626         }
5627
5628         if (!get_printer_snum(p, handle, &snum, NULL))
5629                 return WERR_BADFID;
5630
5631         switch (command) {
5632         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5633                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5634                         errcode = WERR_OK;
5635                 }
5636                 break;
5637         case SPOOLSS_PRINTER_CONTROL_RESUME:
5638         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5639                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5640                         errcode = WERR_OK;
5641                 }
5642                 break;
5643         case SPOOLSS_PRINTER_CONTROL_PURGE:
5644                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5645                         errcode = WERR_OK;
5646                 }
5647                 break;
5648         default:
5649                 return WERR_UNKNOWN_LEVEL;
5650         }
5651
5652         return errcode;
5653 }
5654
5655
5656 /****************************************************************
5657  _spoolss_AbortPrinter
5658  * From MSDN: "Deletes printer's spool file if printer is configured
5659  * for spooling"
5660 ****************************************************************/
5661
5662 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5663                              struct spoolss_AbortPrinter *r)
5664 {
5665         POLICY_HND      *handle = r->in.handle;
5666         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5667         int             snum;
5668         WERROR          errcode = WERR_OK;
5669
5670         if (!Printer) {
5671                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5672                         OUR_HANDLE(handle)));
5673                 return WERR_BADFID;
5674         }
5675
5676         if (!get_printer_snum(p, handle, &snum, NULL))
5677                 return WERR_BADFID;
5678
5679         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5680
5681         return errcode;
5682 }
5683
5684 /********************************************************************
5685  * called by spoolss_api_setprinter
5686  * when updating a printer description
5687  ********************************************************************/
5688
5689 static WERROR update_printer_sec(POLICY_HND *handle,
5690                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5691 {
5692         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5693         WERROR result;
5694         int snum;
5695
5696         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5697
5698         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5699                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5700                          OUR_HANDLE(handle)));
5701
5702                 result = WERR_BADFID;
5703                 goto done;
5704         }
5705
5706         if (!secdesc_ctr) {
5707                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5708                 result = WERR_INVALID_PARAM;
5709                 goto done;
5710         }
5711
5712         /* Check the user has permissions to change the security
5713            descriptor.  By experimentation with two NT machines, the user
5714            requires Full Access to the printer to change security
5715            information. */
5716
5717         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5718                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5719                 result = WERR_ACCESS_DENIED;
5720                 goto done;
5721         }
5722
5723         /* NT seems to like setting the security descriptor even though
5724            nothing may have actually changed. */
5725
5726         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5727                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5728                 result = WERR_BADFID;
5729                 goto done;
5730         }
5731
5732         if (DEBUGLEVEL >= 10) {
5733                 SEC_ACL *the_acl;
5734                 int i;
5735
5736                 the_acl = old_secdesc_ctr->sd->dacl;
5737                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5738                            PRINTERNAME(snum), the_acl->num_aces));
5739
5740                 for (i = 0; i < the_acl->num_aces; i++) {
5741                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5742                                            &the_acl->aces[i].trustee),
5743                                   the_acl->aces[i].access_mask));
5744                 }
5745
5746                 the_acl = secdesc_ctr->sd->dacl;
5747
5748                 if (the_acl) {
5749                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5750                                    PRINTERNAME(snum), the_acl->num_aces));
5751
5752                         for (i = 0; i < the_acl->num_aces; i++) {
5753                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5754                                                    &the_acl->aces[i].trustee),
5755                                            the_acl->aces[i].access_mask));
5756                         }
5757                 } else {
5758                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5759                 }
5760         }
5761
5762         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5763         if (!new_secdesc_ctr) {
5764                 result = WERR_NOMEM;
5765                 goto done;
5766         }
5767
5768         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5769                 result = WERR_OK;
5770                 goto done;
5771         }
5772
5773         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5774
5775  done:
5776
5777         return result;
5778 }
5779
5780 /********************************************************************
5781  Canonicalize printer info from a client
5782
5783  ATTN: It does not matter what we set the servername to hear
5784  since we do the necessary work in get_a_printer() to set it to
5785  the correct value based on what the client sent in the
5786  _spoolss_open_printer_ex().
5787  ********************************************************************/
5788
5789 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5790 {
5791         fstring printername;
5792         const char *p;
5793
5794         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5795                 "portname=%s drivername=%s comment=%s location=%s\n",
5796                 info->servername, info->printername, info->sharename,
5797                 info->portname, info->drivername, info->comment, info->location));
5798
5799         /* we force some elements to "correct" values */
5800         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5801         fstrcpy(info->sharename, lp_servicename(snum));
5802
5803         /* check to see if we allow printername != sharename */
5804
5805         if ( lp_force_printername(snum) ) {
5806                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5807                         global_myname(), info->sharename );
5808         } else {
5809
5810                 /* make sure printername is in \\server\printername format */
5811
5812                 fstrcpy( printername, info->printername );
5813                 p = printername;
5814                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5815                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5816                                 p++;
5817                 }
5818
5819                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5820                          global_myname(), p );
5821         }
5822
5823         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5824         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5825
5826
5827
5828         return True;
5829 }
5830
5831 /****************************************************************************
5832 ****************************************************************************/
5833
5834 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5835 {
5836         char *cmd = lp_addport_cmd();
5837         char *command = NULL;
5838         int ret;
5839         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5840         bool is_print_op = False;
5841
5842         if ( !*cmd ) {
5843                 return WERR_ACCESS_DENIED;
5844         }
5845
5846         command = talloc_asprintf(ctx,
5847                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5848         if (!command) {
5849                 return WERR_NOMEM;
5850         }
5851
5852         if ( token )
5853                 is_print_op = user_has_privileges( token, &se_printop );
5854
5855         DEBUG(10,("Running [%s]\n", command));
5856
5857         /********* BEGIN SePrintOperatorPrivilege **********/
5858
5859         if ( is_print_op )
5860                 become_root();
5861
5862         ret = smbrun(command, NULL);
5863
5864         if ( is_print_op )
5865                 unbecome_root();
5866
5867         /********* END SePrintOperatorPrivilege **********/
5868
5869         DEBUGADD(10,("returned [%d]\n", ret));
5870
5871         TALLOC_FREE(command);
5872
5873         if ( ret != 0 ) {
5874                 return WERR_ACCESS_DENIED;
5875         }
5876
5877         return WERR_OK;
5878 }
5879
5880 /****************************************************************************
5881 ****************************************************************************/
5882
5883 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5884 {
5885         char *cmd = lp_addprinter_cmd();
5886         char **qlines;
5887         char *command = NULL;
5888         int numlines;
5889         int ret;
5890         int fd;
5891         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5892         bool is_print_op = False;
5893         char *remote_machine = talloc_strdup(ctx, "%m");
5894
5895         if (!remote_machine) {
5896                 return false;
5897         }
5898         remote_machine = talloc_sub_basic(ctx,
5899                                 current_user_info.smb_name,
5900                                 current_user_info.domain,
5901                                 remote_machine);
5902         if (!remote_machine) {
5903                 return false;
5904         }
5905
5906         command = talloc_asprintf(ctx,
5907                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5908                         cmd, printer->info_2->printername, printer->info_2->sharename,
5909                         printer->info_2->portname, printer->info_2->drivername,
5910                         printer->info_2->location, printer->info_2->comment, remote_machine);
5911         if (!command) {
5912                 return false;
5913         }
5914
5915         if ( token )
5916                 is_print_op = user_has_privileges( token, &se_printop );
5917
5918         DEBUG(10,("Running [%s]\n", command));
5919
5920         /********* BEGIN SePrintOperatorPrivilege **********/
5921
5922         if ( is_print_op )
5923                 become_root();
5924
5925         if ( (ret = smbrun(command, &fd)) == 0 ) {
5926                 /* Tell everyone we updated smb.conf. */
5927                 message_send_all(smbd_messaging_context(),
5928                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5929         }
5930
5931         if ( is_print_op )
5932                 unbecome_root();
5933
5934         /********* END SePrintOperatorPrivilege **********/
5935
5936         DEBUGADD(10,("returned [%d]\n", ret));
5937
5938         TALLOC_FREE(command);
5939         TALLOC_FREE(remote_machine);
5940
5941         if ( ret != 0 ) {
5942                 if (fd != -1)
5943                         close(fd);
5944                 return False;
5945         }
5946
5947         /* reload our services immediately */
5948         reload_services( False );
5949
5950         numlines = 0;
5951         /* Get lines and convert them back to dos-codepage */
5952         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5953         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5954         close(fd);
5955
5956         /* Set the portname to what the script says the portname should be. */
5957         /* but don't require anything to be return from the script exit a good error code */
5958
5959         if (numlines) {
5960                 /* Set the portname to what the script says the portname should be. */
5961                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5962                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5963         }
5964
5965         TALLOC_FREE(qlines);
5966         return True;
5967 }
5968
5969
5970 /********************************************************************
5971  * Called by spoolss_api_setprinter
5972  * when updating a printer description.
5973  ********************************************************************/
5974
5975 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
5976                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5977                              struct spoolss_DeviceMode *devmode)
5978 {
5979         int snum;
5980         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5981         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5982         WERROR result;
5983         UNISTR2 buffer;
5984         fstring asc_buffer;
5985
5986         DEBUG(8,("update_printer\n"));
5987
5988         result = WERR_OK;
5989
5990         if (!Printer) {
5991                 result = WERR_BADFID;
5992                 goto done;
5993         }
5994
5995         if (!get_printer_snum(p, handle, &snum, NULL)) {
5996                 result = WERR_BADFID;
5997                 goto done;
5998         }
5999
6000         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6001             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6002                 result = WERR_BADFID;
6003                 goto done;
6004         }
6005
6006         DEBUGADD(8,("Converting info_2 struct\n"));
6007
6008         /*
6009          * convert_printer_info converts the incoming
6010          * info from the client and overwrites the info
6011          * just read from the tdb in the pointer 'printer'.
6012          */
6013
6014         if (!convert_printer_info_new(info_ctr, printer)) {
6015                 result =  WERR_NOMEM;
6016                 goto done;
6017         }
6018
6019         if (devmode) {
6020                 /* we have a valid devmode
6021                    convert it and link it*/
6022
6023                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6024                 if (!convert_devicemode_new(printer->info_2->printername,
6025                                             devmode,
6026                                             &printer->info_2->devmode)) {
6027                         result =  WERR_NOMEM;
6028                         goto done;
6029                 }
6030         }
6031
6032         /* Do sanity check on the requested changes for Samba */
6033
6034         if (!check_printer_ok(printer->info_2, snum)) {
6035                 result = WERR_INVALID_PARAM;
6036                 goto done;
6037         }
6038
6039         /* FIXME!!! If the driver has changed we really should verify that
6040            it is installed before doing much else   --jerry */
6041
6042         /* Check calling user has permission to update printer description */
6043
6044         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6045                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6046                 result = WERR_ACCESS_DENIED;
6047                 goto done;
6048         }
6049
6050         /* Call addprinter hook */
6051         /* Check changes to see if this is really needed */
6052
6053         if ( *lp_addprinter_cmd()
6054                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6055                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6056                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6057                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6058         {
6059                 /* add_printer_hook() will call reload_services() */
6060
6061                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6062                                        printer) ) {
6063                         result = WERR_ACCESS_DENIED;
6064                         goto done;
6065                 }
6066         }
6067
6068         /*
6069          * When a *new* driver is bound to a printer, the drivername is used to
6070          * lookup previously saved driver initialization info, which is then
6071          * bound to the printer, simulating what happens in the Windows arch.
6072          */
6073         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6074         {
6075                 if (!set_driver_init(printer, 2))
6076                 {
6077                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6078                                 printer->info_2->drivername));
6079                 }
6080
6081                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6082                         printer->info_2->drivername));
6083
6084                 notify_printer_driver(snum, printer->info_2->drivername);
6085         }
6086
6087         /*
6088          * flag which changes actually occured.  This is a small subset of
6089          * all the possible changes.  We also have to update things in the
6090          * DsSpooler key.
6091          */
6092
6093         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6094                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6095                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6096                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6097
6098                 notify_printer_comment(snum, printer->info_2->comment);
6099         }
6100
6101         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6102                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6103                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6104                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6105
6106                 notify_printer_sharename(snum, printer->info_2->sharename);
6107         }
6108
6109         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6110                 char *pname;
6111
6112                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6113                         pname++;
6114                 else
6115                         pname = printer->info_2->printername;
6116
6117
6118                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6119                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6120                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6121
6122                 notify_printer_printername( snum, pname );
6123         }
6124
6125         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6126                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6127                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6128                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6129
6130                 notify_printer_port(snum, printer->info_2->portname);
6131         }
6132
6133         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6134                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6135                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6136                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6137
6138                 notify_printer_location(snum, printer->info_2->location);
6139         }
6140
6141         /* here we need to update some more DsSpooler keys */
6142         /* uNCName, serverName, shortServerName */
6143
6144         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6145         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6146                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6147         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6148                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6149
6150         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6151                  global_myname(), printer->info_2->sharename );
6152         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6153         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6154                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6155
6156         /* Update printer info */
6157         result = mod_a_printer(printer, 2);
6158
6159 done:
6160         free_a_printer(&printer, 2);
6161         free_a_printer(&old_printer, 2);
6162
6163
6164         return result;
6165 }
6166
6167 /****************************************************************************
6168 ****************************************************************************/
6169 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6170                                            struct spoolss_SetPrinterInfo7 *info7)
6171 {
6172 #ifdef HAVE_ADS
6173         int snum;
6174         Printer_entry *Printer;
6175
6176         if ( lp_security() != SEC_ADS ) {
6177                 return WERR_UNKNOWN_LEVEL;
6178         }
6179
6180         Printer = find_printer_index_by_hnd(p, handle);
6181
6182         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6183
6184         if (!Printer)
6185                 return WERR_BADFID;
6186
6187         if (!get_printer_snum(p, handle, &snum, NULL))
6188                 return WERR_BADFID;
6189
6190         nt_printer_publish(Printer, snum, info7->action);
6191
6192         return WERR_OK;
6193 #else
6194         return WERR_UNKNOWN_LEVEL;
6195 #endif
6196 }
6197
6198 /****************************************************************
6199  _spoolss_SetPrinter
6200 ****************************************************************/
6201
6202 WERROR _spoolss_SetPrinter(pipes_struct *p,
6203                            struct spoolss_SetPrinter *r)
6204 {
6205         POLICY_HND *handle = r->in.handle;
6206         WERROR result;
6207
6208         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6209
6210         if (!Printer) {
6211                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6212                         OUR_HANDLE(handle)));
6213                 return WERR_BADFID;
6214         }
6215
6216         /* check the level */
6217         switch (r->in.info_ctr->level) {
6218                 case 0:
6219                         return control_printer(handle, r->in.command, p);
6220                 case 2:
6221                         result = update_printer(p, handle,
6222                                                 r->in.info_ctr,
6223                                                 r->in.devmode_ctr->devmode);
6224                         if (!W_ERROR_IS_OK(result))
6225                                 return result;
6226                         if (r->in.secdesc_ctr->sd)
6227                                 result = update_printer_sec(handle, p,
6228                                                             r->in.secdesc_ctr);
6229                         return result;
6230                 case 3:
6231                         return update_printer_sec(handle, p,
6232                                                   r->in.secdesc_ctr);
6233                 case 7:
6234                         return publish_or_unpublish_printer(p, handle,
6235                                                             r->in.info_ctr->info.info7);
6236                 default:
6237                         return WERR_UNKNOWN_LEVEL;
6238         }
6239 }
6240
6241 /****************************************************************
6242  _spoolss_FindClosePrinterNotify
6243 ****************************************************************/
6244
6245 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6246                                        struct spoolss_FindClosePrinterNotify *r)
6247 {
6248         POLICY_HND *handle = r->in.handle;
6249         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6250
6251         if (!Printer) {
6252                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6253                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6254                 return WERR_BADFID;
6255         }
6256
6257         if (Printer->notify.client_connected==True) {
6258                 int snum = -1;
6259
6260                 if ( Printer->printer_type == SPLHND_SERVER)
6261                         snum = -1;
6262                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6263                                 !get_printer_snum(p, handle, &snum, NULL) )
6264                         return WERR_BADFID;
6265
6266                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6267         }
6268
6269         Printer->notify.flags=0;
6270         Printer->notify.options=0;
6271         Printer->notify.localmachine[0]='\0';
6272         Printer->notify.printerlocal=0;
6273         TALLOC_FREE(Printer->notify.option);
6274         Printer->notify.client_connected=False;
6275
6276         return WERR_OK;
6277 }
6278
6279 /****************************************************************
6280  _spoolss_AddJob
6281 ****************************************************************/
6282
6283 WERROR _spoolss_AddJob(pipes_struct *p,
6284                        struct spoolss_AddJob *r)
6285 {
6286         if (!r->in.buffer && (r->in.offered != 0)) {
6287                 return WERR_INVALID_PARAM;
6288         }
6289
6290         /* this is what a NT server returns for AddJob. AddJob must fail on
6291          * non-local printers */
6292
6293         if (r->in.level != 1) {
6294                 return WERR_UNKNOWN_LEVEL;
6295         }
6296
6297         return WERR_INVALID_PARAM;
6298 }
6299
6300 /****************************************************************************
6301 fill_job_info1
6302 ****************************************************************************/
6303
6304 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6305                              struct spoolss_JobInfo1 *r,
6306                              const print_queue_struct *queue,
6307                              int position, int snum,
6308                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6309 {
6310         struct tm *t;
6311
6312         t = gmtime(&queue->time);
6313
6314         r->job_id               = queue->job;
6315
6316         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6317         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6318         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6319         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6320         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6321         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6322         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6323         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6324         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6325         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6326         r->text_status          = talloc_strdup(mem_ctx, "");
6327         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6328
6329         r->status               = nt_printj_status(queue->status);
6330         r->priority             = queue->priority;
6331         r->position             = position;
6332         r->total_pages          = queue->page_count;
6333         r->pages_printed        = 0; /* ??? */
6334
6335         init_systemtime(&r->submitted, t);
6336
6337         return WERR_OK;
6338 }
6339
6340 /****************************************************************************
6341 fill_job_info2
6342 ****************************************************************************/
6343
6344 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6345                              struct spoolss_JobInfo2 *r,
6346                              const print_queue_struct *queue,
6347                              int position, int snum,
6348                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6349                              struct spoolss_DeviceMode *devmode)
6350 {
6351         struct tm *t;
6352
6353         t = gmtime(&queue->time);
6354
6355         r->job_id               = queue->job;
6356
6357         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6358         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6359         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6360         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6361         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6362         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6363         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6364         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6365         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6366         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6367         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6368         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6369         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6370         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6371         r->parameters           = talloc_strdup(mem_ctx, "");
6372         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6373         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6374         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6375
6376         r->devmode              = devmode;
6377
6378         r->text_status          = talloc_strdup(mem_ctx, "");
6379         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6380
6381         r->secdesc              = NULL;
6382
6383         r->status               = nt_printj_status(queue->status);
6384         r->priority             = queue->priority;
6385         r->position             = position;
6386         r->start_time           = 0;
6387         r->until_time           = 0;
6388         r->total_pages          = queue->page_count;
6389         r->size                 = queue->size;
6390         init_systemtime(&r->submitted, t);
6391         r->time                 = 0;
6392         r->pages_printed        = 0; /* ??? */
6393
6394         return WERR_OK;
6395 }
6396
6397 /****************************************************************************
6398  Enumjobs at level 1.
6399 ****************************************************************************/
6400
6401 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6402                               const print_queue_struct *queue,
6403                               uint32_t num_queues, int snum,
6404                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6405                               union spoolss_JobInfo **info_p,
6406                               uint32_t *count)
6407 {
6408         union spoolss_JobInfo *info;
6409         int i;
6410         WERROR result = WERR_OK;
6411
6412         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6413         W_ERROR_HAVE_NO_MEMORY(info);
6414
6415         *count = num_queues;
6416
6417         for (i=0; i<*count; i++) {
6418                 result = fill_job_info1(info,
6419                                         &info[i].info1,
6420                                         &queue[i],
6421                                         i,
6422                                         snum,
6423                                         ntprinter);
6424                 if (!W_ERROR_IS_OK(result)) {
6425                         goto out;
6426                 }
6427         }
6428
6429  out:
6430         if (!W_ERROR_IS_OK(result)) {
6431                 TALLOC_FREE(info);
6432                 *count = 0;
6433                 return result;
6434         }
6435
6436         *info_p = info;
6437
6438         return WERR_OK;
6439 }
6440
6441 /****************************************************************************
6442  Enumjobs at level 2.
6443 ****************************************************************************/
6444
6445 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6446                               const print_queue_struct *queue,
6447                               uint32_t num_queues, int snum,
6448                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6449                               union spoolss_JobInfo **info_p,
6450                               uint32_t *count)
6451 {
6452         union spoolss_JobInfo *info;
6453         int i;
6454         WERROR result = WERR_OK;
6455
6456         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6457         W_ERROR_HAVE_NO_MEMORY(info);
6458
6459         *count = num_queues;
6460
6461         for (i=0; i<*count; i++) {
6462
6463                 struct spoolss_DeviceMode *devmode;
6464
6465                 devmode = construct_dev_mode_new(info, lp_const_servicename(snum));
6466                 if (!devmode) {
6467                         result = WERR_NOMEM;
6468                         goto out;
6469                 }
6470
6471                 result = fill_job_info2(info,
6472                                         &info[i].info2,
6473                                         &queue[i],
6474                                         i,
6475                                         snum,
6476                                         ntprinter,
6477                                         devmode);
6478                 if (!W_ERROR_IS_OK(result)) {
6479                         goto out;
6480                 }
6481         }
6482
6483  out:
6484         if (!W_ERROR_IS_OK(result)) {
6485                 TALLOC_FREE(info);
6486                 *count = 0;
6487                 return result;
6488         }
6489
6490         *info_p = info;
6491
6492         return WERR_OK;
6493 }
6494
6495 /****************************************************************
6496  _spoolss_EnumJobs
6497 ****************************************************************/
6498
6499 WERROR _spoolss_EnumJobs(pipes_struct *p,
6500                          struct spoolss_EnumJobs *r)
6501 {
6502         WERROR result;
6503         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6504         int snum;
6505         print_status_struct prt_status;
6506         print_queue_struct *queue = NULL;
6507         uint32_t count;
6508
6509         /* that's an [in out] buffer */
6510
6511         if (!r->in.buffer && (r->in.offered != 0)) {
6512                 return WERR_INVALID_PARAM;
6513         }
6514
6515         DEBUG(4,("_spoolss_EnumJobs\n"));
6516
6517         *r->out.needed = 0;
6518         *r->out.count = 0;
6519         *r->out.info = NULL;
6520
6521         /* lookup the printer snum and tdb entry */
6522
6523         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6524                 return WERR_BADFID;
6525         }
6526
6527         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6528         if (!W_ERROR_IS_OK(result)) {
6529                 return result;
6530         }
6531
6532         count = print_queue_status(snum, &queue, &prt_status);
6533         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6534                 count, prt_status.status, prt_status.message));
6535
6536         if (count == 0) {
6537                 SAFE_FREE(queue);
6538                 free_a_printer(&ntprinter, 2);
6539                 return WERR_OK;
6540         }
6541
6542         switch (r->in.level) {
6543         case 1:
6544                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6545                                          ntprinter, r->out.info, r->out.count);
6546                 break;
6547         case 2:
6548                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6549                                          ntprinter, r->out.info, r->out.count);
6550                 break;
6551         default:
6552                 result = WERR_UNKNOWN_LEVEL;
6553                 break;
6554         }
6555
6556         SAFE_FREE(queue);
6557         free_a_printer(&ntprinter, 2);
6558
6559         if (!W_ERROR_IS_OK(result)) {
6560                 return result;
6561         }
6562
6563         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6564                                                      spoolss_EnumJobs, NULL,
6565                                                      *r->out.info, r->in.level,
6566                                                      *r->out.count);
6567         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6568         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6569
6570         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6571 }
6572
6573 /****************************************************************
6574  _spoolss_ScheduleJob
6575 ****************************************************************/
6576
6577 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6578                             struct spoolss_ScheduleJob *r)
6579 {
6580         return WERR_OK;
6581 }
6582
6583 /****************************************************************
6584  _spoolss_SetJob
6585 ****************************************************************/
6586
6587 WERROR _spoolss_SetJob(pipes_struct *p,
6588                        struct spoolss_SetJob *r)
6589 {
6590         POLICY_HND *handle = r->in.handle;
6591         uint32 jobid = r->in.job_id;
6592         uint32 command = r->in.command;
6593
6594         int snum;
6595         WERROR errcode = WERR_BADFUNC;
6596
6597         if (!get_printer_snum(p, handle, &snum, NULL)) {
6598                 return WERR_BADFID;
6599         }
6600
6601         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6602                 return WERR_INVALID_PRINTER_NAME;
6603         }
6604
6605         switch (command) {
6606         case SPOOLSS_JOB_CONTROL_CANCEL:
6607         case SPOOLSS_JOB_CONTROL_DELETE:
6608                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6609                         errcode = WERR_OK;
6610                 }
6611                 break;
6612         case SPOOLSS_JOB_CONTROL_PAUSE:
6613                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6614                         errcode = WERR_OK;
6615                 }
6616                 break;
6617         case SPOOLSS_JOB_CONTROL_RESTART:
6618         case SPOOLSS_JOB_CONTROL_RESUME:
6619                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6620                         errcode = WERR_OK;
6621                 }
6622                 break;
6623         default:
6624                 return WERR_UNKNOWN_LEVEL;
6625         }
6626
6627         return errcode;
6628 }
6629
6630 /****************************************************************************
6631  Enumerates all printer drivers at level 1.
6632 ****************************************************************************/
6633
6634 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6635                                         const char *servername,
6636                                         const char *architecture,
6637                                         union spoolss_DriverInfo **info_p,
6638                                         uint32_t *count)
6639 {
6640         int i;
6641         int ndrivers;
6642         uint32_t version;
6643         fstring *list = NULL;
6644         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6645         union spoolss_DriverInfo *info = NULL;
6646         WERROR result = WERR_OK;
6647
6648         *count = 0;
6649
6650         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6651                 list = NULL;
6652                 ndrivers = get_ntdrivers(&list, architecture, version);
6653                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6654                         ndrivers, architecture, version));
6655
6656                 if (ndrivers == -1) {
6657                         result = WERR_NOMEM;
6658                         goto out;
6659                 }
6660
6661                 if (ndrivers != 0) {
6662                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6663                                                     union spoolss_DriverInfo,
6664                                                     *count + ndrivers);
6665                         if (!info) {
6666                                 DEBUG(0,("enumprinterdrivers_level1: "
6667                                         "failed to enlarge driver info buffer!\n"));
6668                                 result = WERR_NOMEM;
6669                                 goto out;
6670                         }
6671                 }
6672
6673                 for (i=0; i<ndrivers; i++) {
6674                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6675                         ZERO_STRUCT(driver);
6676                         result = get_a_printer_driver(&driver, 3, list[i],
6677                                                       architecture, version);
6678                         if (!W_ERROR_IS_OK(result)) {
6679                                 goto out;
6680                         }
6681                         result = fill_printer_driver_info1(info, &info[*count+i].info1,
6682                                                            &driver, servername,
6683                                                            architecture);
6684                         if (!W_ERROR_IS_OK(result)) {
6685                                 free_a_printer_driver(driver, 3);
6686                                 goto out;
6687                         }
6688                         free_a_printer_driver(driver, 3);
6689                 }
6690
6691                 *count += ndrivers;
6692                 SAFE_FREE(list);
6693         }
6694
6695  out:
6696         SAFE_FREE(list);
6697
6698         if (!W_ERROR_IS_OK(result)) {
6699                 TALLOC_FREE(info);
6700                 *count = 0;
6701                 return result;
6702         }
6703
6704         *info_p = info;
6705
6706         return WERR_OK;
6707 }
6708
6709 /****************************************************************************
6710  Enumerates all printer drivers at level 2.
6711 ****************************************************************************/
6712
6713 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6714                                         const char *servername,
6715                                         const char *architecture,
6716                                         union spoolss_DriverInfo **info_p,
6717                                         uint32_t *count)
6718 {
6719         int i;
6720         int ndrivers;
6721         uint32_t version;
6722         fstring *list = NULL;
6723         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6724         union spoolss_DriverInfo *info = NULL;
6725         WERROR result = WERR_OK;
6726
6727         *count = 0;
6728
6729         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6730                 list = NULL;
6731                 ndrivers = get_ntdrivers(&list, architecture, version);
6732                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6733                         ndrivers, architecture, version));
6734
6735                 if (ndrivers == -1) {
6736                         result = WERR_NOMEM;
6737                         goto out;
6738                 }
6739
6740                 if (ndrivers != 0) {
6741                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6742                                                     union spoolss_DriverInfo,
6743                                                     *count + ndrivers);
6744                         if (!info) {
6745                                 DEBUG(0,("enumprinterdrivers_level2: "
6746                                         "failed to enlarge driver info buffer!\n"));
6747                                 result = WERR_NOMEM;
6748                                 goto out;
6749                         }
6750                 }
6751
6752                 for (i=0; i<ndrivers; i++) {
6753                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6754                         ZERO_STRUCT(driver);
6755                         result = get_a_printer_driver(&driver, 3, list[i],
6756                                                       architecture, version);
6757                         if (!W_ERROR_IS_OK(result)) {
6758                                 goto out;
6759                         }
6760                         result = fill_printer_driver_info2(info, &info[*count+i].info2,
6761                                                            &driver, servername);
6762                         if (!W_ERROR_IS_OK(result)) {
6763                                 free_a_printer_driver(driver, 3);
6764                                 goto out;
6765                         }
6766                         free_a_printer_driver(driver, 3);
6767                 }
6768
6769                 *count += ndrivers;
6770                 SAFE_FREE(list);
6771         }
6772
6773  out:
6774         SAFE_FREE(list);
6775
6776         if (!W_ERROR_IS_OK(result)) {
6777                 TALLOC_FREE(info);
6778                 *count = 0;
6779                 return result;
6780         }
6781
6782         *info_p = info;
6783
6784         return WERR_OK;
6785 }
6786
6787 /****************************************************************************
6788  Enumerates all printer drivers at level 3.
6789 ****************************************************************************/
6790
6791 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6792                                         const char *servername,
6793                                         const char *architecture,
6794                                         union spoolss_DriverInfo **info_p,
6795                                         uint32_t *count)
6796 {
6797         int i;
6798         int ndrivers;
6799         uint32_t version;
6800         fstring *list = NULL;
6801         union spoolss_DriverInfo *info = NULL;
6802         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6803         WERROR result = WERR_OK;
6804
6805         *count = 0;
6806
6807         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6808                 list = NULL;
6809                 ndrivers = get_ntdrivers(&list, architecture, version);
6810                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6811                         ndrivers, architecture, version));
6812
6813                 if (ndrivers == -1) {
6814                         result = WERR_NOMEM;
6815                         goto out;
6816                 }
6817
6818                 if (ndrivers != 0) {
6819                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6820                                                     union spoolss_DriverInfo,
6821                                                     *count + ndrivers);
6822                         if (!info) {
6823                                 DEBUG(0,("enumprinterdrivers_level3: "
6824                                         "failed to enlarge driver info buffer!\n"));
6825                                 result = WERR_NOMEM;
6826                                 goto out;
6827                         }
6828                 }
6829
6830                 for (i=0; i<ndrivers; i++) {
6831                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6832                         ZERO_STRUCT(driver);
6833                         result = get_a_printer_driver(&driver, 3, list[i],
6834                                                       architecture, version);
6835                         if (!W_ERROR_IS_OK(result)) {
6836                                 goto out;
6837                         }
6838                         result = fill_printer_driver_info3(info, &info[*count+i].info3,
6839                                                            &driver, servername);
6840                         if (!W_ERROR_IS_OK(result)) {
6841                                 free_a_printer_driver(driver, 3);
6842                                 goto out;
6843                         }
6844
6845                         free_a_printer_driver(driver, 3);
6846                 }
6847
6848                 *count += ndrivers;
6849                 SAFE_FREE(list);
6850         }
6851
6852  out:
6853         SAFE_FREE(list);
6854
6855         if (!W_ERROR_IS_OK(result)) {
6856                 TALLOC_FREE(info);
6857                 *count = 0;
6858                 return result;
6859         }
6860
6861         *info_p = info;
6862
6863         return WERR_OK;
6864 }
6865
6866 /****************************************************************
6867  _spoolss_EnumPrinterDrivers
6868 ****************************************************************/
6869
6870 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6871                                    struct spoolss_EnumPrinterDrivers *r)
6872 {
6873         const char *cservername;
6874         WERROR result;
6875
6876         /* that's an [in out] buffer */
6877
6878         if (!r->in.buffer && (r->in.offered != 0)) {
6879                 return WERR_INVALID_PARAM;
6880         }
6881
6882         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6883
6884         *r->out.needed = 0;
6885         *r->out.count = 0;
6886         *r->out.info = NULL;
6887
6888         cservername = canon_servername(r->in.server);
6889
6890         if (!is_myname_or_ipaddr(cservername)) {
6891                 return WERR_UNKNOWN_PRINTER_DRIVER;
6892         }
6893
6894         switch (r->in.level) {
6895         case 1:
6896                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
6897                                                    r->in.environment,
6898                                                    r->out.info, r->out.count);
6899                 break;
6900         case 2:
6901                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
6902                                                    r->in.environment,
6903                                                    r->out.info, r->out.count);
6904                 break;
6905         case 3:
6906                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
6907                                                    r->in.environment,
6908                                                    r->out.info, r->out.count);
6909                 break;
6910         default:
6911                 return WERR_UNKNOWN_LEVEL;
6912         }
6913
6914         if (!W_ERROR_IS_OK(result)) {
6915                 return result;
6916         }
6917
6918         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6919                                                      spoolss_EnumPrinterDrivers, NULL,
6920                                                      *r->out.info, r->in.level,
6921                                                      *r->out.count);
6922         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6923         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6924
6925         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6926 }
6927
6928 /****************************************************************************
6929 ****************************************************************************/
6930
6931 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6932                                struct spoolss_FormInfo1 *r,
6933                                const nt_forms_struct *form)
6934 {
6935         r->form_name    = talloc_strdup(mem_ctx, form->name);
6936         W_ERROR_HAVE_NO_MEMORY(r->form_name);
6937
6938         r->flags        = form->flag;
6939         r->size.width   = form->width;
6940         r->size.height  = form->length;
6941         r->area.left    = form->left;
6942         r->area.top     = form->top;
6943         r->area.right   = form->right;
6944         r->area.bottom  = form->bottom;
6945
6946         return WERR_OK;
6947 }
6948
6949 /****************************************************************
6950  spoolss_enumforms_level1
6951 ****************************************************************/
6952
6953 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6954                                        const nt_forms_struct *builtin_forms,
6955                                        uint32_t num_builtin_forms,
6956                                        const nt_forms_struct *user_forms,
6957                                        uint32_t num_user_forms,
6958                                        union spoolss_FormInfo **info_p,
6959                                        uint32_t *count)
6960 {
6961         union spoolss_FormInfo *info;
6962         WERROR result = WERR_OK;
6963         int i;
6964
6965         *count = num_builtin_forms + num_user_forms;
6966
6967         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6968         W_ERROR_HAVE_NO_MEMORY(info);
6969
6970         /* construct the list of form structures */
6971         for (i=0; i<num_builtin_forms; i++) {
6972                 DEBUGADD(6,("Filling form number [%d]\n",i));
6973                 result = fill_form_info_1(info, &info[i].info1,
6974                                           &builtin_forms[i]);
6975                 if (!W_ERROR_IS_OK(result)) {
6976                         goto out;
6977                 }
6978         }
6979
6980         for (; i<num_user_forms; i++) {
6981                 DEBUGADD(6,("Filling form number [%d]\n",i));
6982                 result = fill_form_info_1(info, &info[i].info1,
6983                                           &user_forms[i-num_builtin_forms]);
6984                 if (!W_ERROR_IS_OK(result)) {
6985                         goto out;
6986                 }
6987         }
6988
6989  out:
6990         if (!W_ERROR_IS_OK(result)) {
6991                 TALLOC_FREE(info);
6992                 *count = 0;
6993                 return result;
6994         }
6995
6996         *info_p = info;
6997
6998         return WERR_OK;
6999 }
7000
7001 /****************************************************************
7002  _spoolss_EnumForms
7003 ****************************************************************/
7004
7005 WERROR _spoolss_EnumForms(pipes_struct *p,
7006                           struct spoolss_EnumForms *r)
7007 {
7008         WERROR result;
7009         nt_forms_struct *user_forms = NULL;
7010         nt_forms_struct *builtin_forms = NULL;
7011         uint32_t num_user_forms;
7012         uint32_t num_builtin_forms;
7013
7014         *r->out.count = 0;
7015         *r->out.needed = 0;
7016         *r->out.info = NULL;
7017
7018         /* that's an [in out] buffer */
7019
7020         if (!r->in.buffer && (r->in.offered != 0) ) {
7021                 return WERR_INVALID_PARAM;
7022         }
7023
7024         DEBUG(4,("_spoolss_EnumForms\n"));
7025         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7026         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7027
7028         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7029         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7030         num_user_forms = get_ntforms(&user_forms);
7031         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7032
7033         if (num_user_forms + num_builtin_forms == 0) {
7034                 SAFE_FREE(builtin_forms);
7035                 SAFE_FREE(user_forms);
7036                 return WERR_NO_MORE_ITEMS;
7037         }
7038
7039         switch (r->in.level) {
7040         case 1:
7041                 result = spoolss_enumforms_level1(p->mem_ctx,
7042                                                   builtin_forms,
7043                                                   num_builtin_forms,
7044                                                   user_forms,
7045                                                   num_user_forms,
7046                                                   r->out.info,
7047                                                   r->out.count);
7048                 break;
7049         default:
7050                 result = WERR_UNKNOWN_LEVEL;
7051                 break;
7052         }
7053
7054         SAFE_FREE(user_forms);
7055         SAFE_FREE(builtin_forms);
7056
7057         if (!W_ERROR_IS_OK(result)) {
7058                 return result;
7059         }
7060
7061         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7062                                                      spoolss_EnumForms, NULL,
7063                                                      *r->out.info, r->in.level,
7064                                                      *r->out.count);
7065         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7066         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7067
7068         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7069 }
7070
7071 /****************************************************************
7072 ****************************************************************/
7073
7074 static WERROR find_form_byname(const char *name,
7075                                nt_forms_struct *form)
7076 {
7077         nt_forms_struct *list = NULL;
7078         int num_forms = 0, i = 0;
7079
7080         if (get_a_builtin_ntform_by_string(name, form)) {
7081                 return WERR_OK;
7082         }
7083
7084         num_forms = get_ntforms(&list);
7085         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7086
7087         if (num_forms == 0) {
7088                 return WERR_BADFID;
7089         }
7090
7091         /* Check if the requested name is in the list of form structures */
7092         for (i = 0; i < num_forms; i++) {
7093
7094                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7095
7096                 if (strequal(name, list[i].name)) {
7097                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7098                         *form = list[i];
7099                         SAFE_FREE(list);
7100                         return WERR_OK;
7101                 }
7102         }
7103
7104         SAFE_FREE(list);
7105
7106         return WERR_BADFID;
7107 }
7108
7109 /****************************************************************
7110  _spoolss_GetForm
7111 ****************************************************************/
7112
7113 WERROR _spoolss_GetForm(pipes_struct *p,
7114                         struct spoolss_GetForm *r)
7115 {
7116         WERROR result;
7117         nt_forms_struct form;
7118
7119         /* that's an [in out] buffer */
7120
7121         if (!r->in.buffer && (r->in.offered != 0)) {
7122                 return WERR_INVALID_PARAM;
7123         }
7124
7125         DEBUG(4,("_spoolss_GetForm\n"));
7126         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7127         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7128
7129         result = find_form_byname(r->in.form_name, &form);
7130         if (!W_ERROR_IS_OK(result)) {
7131                 TALLOC_FREE(r->out.info);
7132                 return result;
7133         }
7134
7135         switch (r->in.level) {
7136         case 1:
7137                 result = fill_form_info_1(p->mem_ctx,
7138                                           &r->out.info->info1,
7139                                           &form);
7140                 break;
7141
7142         default:
7143                 result = WERR_UNKNOWN_LEVEL;
7144                 break;
7145         }
7146
7147         if (!W_ERROR_IS_OK(result)) {
7148                 TALLOC_FREE(r->out.info);
7149                 return result;
7150         }
7151
7152         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7153                                                r->out.info, r->in.level);
7154         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7155
7156         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7157 }
7158
7159 /****************************************************************************
7160 ****************************************************************************/
7161
7162 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7163                           struct spoolss_PortInfo1 *r,
7164                           const char *name)
7165 {
7166         r->port_name = talloc_strdup(mem_ctx, name);
7167         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7168
7169         return WERR_OK;
7170 }
7171
7172 /****************************************************************************
7173  TODO: This probably needs distinguish between TCP/IP and Local ports
7174  somehow.
7175 ****************************************************************************/
7176
7177 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7178                           struct spoolss_PortInfo2 *r,
7179                           const char *name)
7180 {
7181         r->port_name = talloc_strdup(mem_ctx, name);
7182         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7183
7184         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7185         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7186
7187         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT); /* FIXME */
7188         W_ERROR_HAVE_NO_MEMORY(r->description);
7189
7190         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7191         r->reserved = 0;
7192
7193         return WERR_OK;
7194 }
7195
7196
7197 /****************************************************************************
7198  wrapper around the enumer ports command
7199 ****************************************************************************/
7200
7201 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7202 {
7203         char *cmd = lp_enumports_cmd();
7204         char **qlines = NULL;
7205         char *command = NULL;
7206         int numlines;
7207         int ret;
7208         int fd;
7209
7210         *count = 0;
7211         *lines = NULL;
7212
7213         /* if no hook then just fill in the default port */
7214
7215         if ( !*cmd ) {
7216                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7217                         return WERR_NOMEM;
7218                 }
7219                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7220                         TALLOC_FREE(qlines);
7221                         return WERR_NOMEM;
7222                 }
7223                 qlines[1] = NULL;
7224                 numlines = 1;
7225         }
7226         else {
7227                 /* we have a valid enumport command */
7228
7229                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7230                 if (!command) {
7231                         return WERR_NOMEM;
7232                 }
7233
7234                 DEBUG(10,("Running [%s]\n", command));
7235                 ret = smbrun(command, &fd);
7236                 DEBUG(10,("Returned [%d]\n", ret));
7237                 TALLOC_FREE(command);
7238                 if (ret != 0) {
7239                         if (fd != -1) {
7240                                 close(fd);
7241                         }
7242                         return WERR_ACCESS_DENIED;
7243                 }
7244
7245                 numlines = 0;
7246                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7247                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7248                 close(fd);
7249         }
7250
7251         *count = numlines;
7252         *lines = qlines;
7253
7254         return WERR_OK;
7255 }
7256
7257 /****************************************************************************
7258  enumports level 1.
7259 ****************************************************************************/
7260
7261 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7262                                 union spoolss_PortInfo **info_p,
7263                                 uint32_t *count)
7264 {
7265         union spoolss_PortInfo *info = NULL;
7266         int i=0;
7267         WERROR result = WERR_OK;
7268         char **qlines = NULL;
7269         int numlines = 0;
7270
7271         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7272         if (!W_ERROR_IS_OK(result)) {
7273                 goto out;
7274         }
7275
7276         if (numlines) {
7277                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7278                 if (!info) {
7279                         DEBUG(10,("Returning WERR_NOMEM\n"));
7280                         result = WERR_NOMEM;
7281                         goto out;
7282                 }
7283
7284                 for (i=0; i<numlines; i++) {
7285                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7286                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7287                         if (!W_ERROR_IS_OK(result)) {
7288                                 goto out;
7289                         }
7290                 }
7291         }
7292         TALLOC_FREE(qlines);
7293
7294 out:
7295         if (!W_ERROR_IS_OK(result)) {
7296                 TALLOC_FREE(info);
7297                 TALLOC_FREE(qlines);
7298                 *count = 0;
7299                 *info_p = NULL;
7300                 return result;
7301         }
7302
7303         *info_p = info;
7304         *count = numlines;
7305
7306         return WERR_OK;
7307 }
7308
7309 /****************************************************************************
7310  enumports level 2.
7311 ****************************************************************************/
7312
7313 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7314                                 union spoolss_PortInfo **info_p,
7315                                 uint32_t *count)
7316 {
7317         union spoolss_PortInfo *info = NULL;
7318         int i=0;
7319         WERROR result = WERR_OK;
7320         char **qlines = NULL;
7321         int numlines = 0;
7322
7323         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7324         if (!W_ERROR_IS_OK(result)) {
7325                 goto out;
7326         }
7327
7328         if (numlines) {
7329                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7330                 if (!info) {
7331                         DEBUG(10,("Returning WERR_NOMEM\n"));
7332                         result = WERR_NOMEM;
7333                         goto out;
7334                 }
7335
7336                 for (i=0; i<numlines; i++) {
7337                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7338                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7339                         if (!W_ERROR_IS_OK(result)) {
7340                                 goto out;
7341                         }
7342                 }
7343         }
7344         TALLOC_FREE(qlines);
7345
7346 out:
7347         if (!W_ERROR_IS_OK(result)) {
7348                 TALLOC_FREE(info);
7349                 TALLOC_FREE(qlines);
7350                 *count = 0;
7351                 *info_p = NULL;
7352                 return result;
7353         }
7354
7355         *info_p = info;
7356         *count = numlines;
7357
7358         return WERR_OK;
7359 }
7360
7361 /****************************************************************
7362  _spoolss_EnumPorts
7363 ****************************************************************/
7364
7365 WERROR _spoolss_EnumPorts(pipes_struct *p,
7366                           struct spoolss_EnumPorts *r)
7367 {
7368         WERROR result;
7369
7370         /* that's an [in out] buffer */
7371
7372         if (!r->in.buffer && (r->in.offered != 0)) {
7373                 return WERR_INVALID_PARAM;
7374         }
7375
7376         DEBUG(4,("_spoolss_EnumPorts\n"));
7377
7378         *r->out.count = 0;
7379         *r->out.needed = 0;
7380         *r->out.info = NULL;
7381
7382         switch (r->in.level) {
7383         case 1:
7384                 result = enumports_level_1(p->mem_ctx, r->out.info,
7385                                            r->out.count);
7386                 break;
7387         case 2:
7388                 result = enumports_level_2(p->mem_ctx, r->out.info,
7389                                            r->out.count);
7390                 break;
7391         default:
7392                 return WERR_UNKNOWN_LEVEL;
7393         }
7394
7395         if (!W_ERROR_IS_OK(result)) {
7396                 return result;
7397         }
7398
7399         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7400                                                      spoolss_EnumPorts, NULL,
7401                                                      *r->out.info, r->in.level,
7402                                                      *r->out.count);
7403         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7404         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7405
7406         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7407 }
7408
7409 /****************************************************************************
7410 ****************************************************************************/
7411
7412 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7413                                            const char *server,
7414                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7415                                            struct spoolss_DeviceMode *devmode,
7416                                            struct security_descriptor *sec_desc,
7417                                            struct spoolss_UserLevelCtr *user_ctr,
7418                                            POLICY_HND *handle)
7419 {
7420         NT_PRINTER_INFO_LEVEL *printer = NULL;
7421         fstring name;
7422         int     snum;
7423         WERROR err = WERR_OK;
7424
7425         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7426                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7427                 return WERR_NOMEM;
7428         }
7429
7430         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7431         if (!convert_printer_info_new(info_ctr, printer)) {
7432                 free_a_printer(&printer, 2);
7433                 return WERR_NOMEM;
7434         }
7435
7436         /* check to see if the printer already exists */
7437
7438         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7439                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7440                         printer->info_2->sharename));
7441                 free_a_printer(&printer, 2);
7442                 return WERR_PRINTER_ALREADY_EXISTS;
7443         }
7444
7445         /* FIXME!!!  smbd should check to see if the driver is installed before
7446            trying to add a printer like this  --jerry */
7447
7448         if (*lp_addprinter_cmd() ) {
7449                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7450                                        printer) ) {
7451                         free_a_printer(&printer,2);
7452                         return WERR_ACCESS_DENIED;
7453                 }
7454         } else {
7455                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7456                         "smb.conf parameter \"addprinter command\" is defined. This"
7457                         "parameter must exist for this call to succeed\n",
7458                         printer->info_2->sharename ));
7459         }
7460
7461         /* use our primary netbios name since get_a_printer() will convert
7462            it to what the client expects on a case by case basis */
7463
7464         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7465              printer->info_2->sharename);
7466
7467
7468         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7469                 free_a_printer(&printer,2);
7470                 return WERR_ACCESS_DENIED;
7471         }
7472
7473         /* you must be a printer admin to add a new printer */
7474         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7475                 free_a_printer(&printer,2);
7476                 return WERR_ACCESS_DENIED;
7477         }
7478
7479         /*
7480          * Do sanity check on the requested changes for Samba.
7481          */
7482
7483         if (!check_printer_ok(printer->info_2, snum)) {
7484                 free_a_printer(&printer,2);
7485                 return WERR_INVALID_PARAM;
7486         }
7487
7488         /*
7489          * When a printer is created, the drivername bound to the printer is used
7490          * to lookup previously saved driver initialization info, which is then
7491          * bound to the new printer, simulating what happens in the Windows arch.
7492          */
7493
7494         if (!devmode)
7495         {
7496                 set_driver_init(printer, 2);
7497         }
7498         else
7499         {
7500                 /* A valid devmode was included, convert and link it
7501                 */
7502                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7503
7504                 if (!convert_devicemode_new(printer->info_2->printername,
7505                                             devmode,
7506                                             &printer->info_2->devmode))
7507                         return  WERR_NOMEM;
7508         }
7509
7510         /* write the ASCII on disk */
7511         err = mod_a_printer(printer, 2);
7512         if (!W_ERROR_IS_OK(err)) {
7513                 free_a_printer(&printer,2);
7514                 return err;
7515         }
7516
7517         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7518                 /* Handle open failed - remove addition. */
7519                 del_a_printer(printer->info_2->sharename);
7520                 free_a_printer(&printer,2);
7521                 ZERO_STRUCTP(handle);
7522                 return WERR_ACCESS_DENIED;
7523         }
7524
7525         update_c_setprinter(False);
7526         free_a_printer(&printer,2);
7527
7528         return WERR_OK;
7529 }
7530
7531 /****************************************************************
7532  _spoolss_AddPrinterEx
7533 ****************************************************************/
7534
7535 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7536                              struct spoolss_AddPrinterEx *r)
7537 {
7538         switch (r->in.info_ctr->level) {
7539         case 1:
7540                 /* we don't handle yet */
7541                 /* but I know what to do ... */
7542                 return WERR_UNKNOWN_LEVEL;
7543         case 2:
7544                 return spoolss_addprinterex_level_2(p, r->in.server,
7545                                                     r->in.info_ctr,
7546                                                     r->in.devmode_ctr->devmode,
7547                                                     r->in.secdesc_ctr->sd,
7548                                                     r->in.userlevel_ctr,
7549                                                     r->out.handle);
7550         default:
7551                 return WERR_UNKNOWN_LEVEL;
7552         }
7553 }
7554
7555 /****************************************************************
7556  _spoolss_AddPrinterDriver
7557 ****************************************************************/
7558
7559 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7560                                  struct spoolss_AddPrinterDriver *r)
7561 {
7562         uint32_t level = r->in.info_ctr->level;
7563         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7564         WERROR err = WERR_OK;
7565         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7566         fstring driver_name;
7567         uint32 version;
7568         const char *fn;
7569
7570         switch (p->hdr_req.opnum) {
7571                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7572                         fn = "_spoolss_AddPrinterDriver";
7573                         break;
7574                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7575                         fn = "_spoolss_AddPrinterDriverEx";
7576                         break;
7577                 default:
7578                         return WERR_INVALID_PARAM;
7579         }
7580
7581
7582         /* FIXME */
7583         if (level != 3 && level != 6) {
7584                 /* Clever hack from Martin Zielinski <mz@seh.de>
7585                  * to allow downgrade from level 8 (Vista).
7586                  */
7587                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7588                 return WERR_UNKNOWN_LEVEL;
7589         }
7590
7591         ZERO_STRUCT(driver);
7592
7593         if (!convert_printer_driver_info(info, &driver, level)) {
7594                 err = WERR_NOMEM;
7595                 goto done;
7596         }
7597
7598         DEBUG(5,("Cleaning driver's information\n"));
7599         err = clean_up_driver_struct(p, driver, level);
7600         if (!W_ERROR_IS_OK(err))
7601                 goto done;
7602
7603         DEBUG(5,("Moving driver to final destination\n"));
7604         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7605                                                               &err)) ) {
7606                 goto done;
7607         }
7608
7609         if (add_a_printer_driver(driver, level)!=0) {
7610                 err = WERR_ACCESS_DENIED;
7611                 goto done;
7612         }
7613
7614         switch(level) {
7615         case 3:
7616                 fstrcpy(driver_name,
7617                         driver.info_3->name ? driver.info_3->name : "");
7618                 break;
7619         case 6:
7620                 fstrcpy(driver_name,
7621                         driver.info_6->name ?  driver.info_6->name : "");
7622                 break;
7623         }
7624
7625         /*
7626          * I think this is where he DrvUpgradePrinter() hook would be
7627          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7628          * server.  Right now, we just need to send ourselves a message
7629          * to update each printer bound to this driver.   --jerry
7630          */
7631
7632         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7633                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7634                         fn, driver_name));
7635         }
7636
7637         /*
7638          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7639          * decide if the driver init data should be deleted. The rules are:
7640          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7641          *  2) delete init data only if there is no 2k/Xp driver
7642          *  3) always delete init data
7643          * The generalized rule is always use init data from the highest order driver.
7644          * It is necessary to follow the driver install by an initialization step to
7645          * finish off this process.
7646         */
7647         if (level == 3)
7648                 version = driver.info_3->cversion;
7649         else if (level == 6)
7650                 version = driver.info_6->version;
7651         else
7652                 version = -1;
7653         switch (version) {
7654                 /*
7655                  * 9x printer driver - never delete init data
7656                 */
7657                 case 0:
7658                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7659                                 fn, driver_name));
7660                         break;
7661
7662                 /*
7663                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7664                  * there is no 2k/Xp driver init data for this driver name.
7665                 */
7666                 case 2:
7667                 {
7668                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7669
7670                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7671                                 /*
7672                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7673                                 */
7674                                 if (!del_driver_init(driver_name))
7675                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7676                                                 fn, driver_name));
7677                         } else {
7678                                 /*
7679                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7680                                 */
7681                                 free_a_printer_driver(driver1,3);
7682                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7683                                         fn, driver_name));
7684                         }
7685                 }
7686                 break;
7687
7688                 /*
7689                  * 2k or Xp printer driver - always delete init data
7690                 */
7691                 case 3:
7692                         if (!del_driver_init(driver_name))
7693                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7694                                         fn, driver_name));
7695                         break;
7696
7697                 default:
7698                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7699                         break;
7700         }
7701
7702
7703 done:
7704         free_a_printer_driver(driver, level);
7705         return err;
7706 }
7707
7708 /****************************************************************
7709  _spoolss_AddPrinterDriverEx
7710 ****************************************************************/
7711
7712 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7713                                    struct spoolss_AddPrinterDriverEx *r)
7714 {
7715         struct spoolss_AddPrinterDriver a;
7716
7717         /*
7718          * we only support the semantics of AddPrinterDriver()
7719          * i.e. only copy files that are newer than existing ones
7720          */
7721
7722         if (r->in.flags != APD_COPY_NEW_FILES) {
7723                 return WERR_ACCESS_DENIED;
7724         }
7725
7726         a.in.servername         = r->in.servername;
7727         a.in.info_ctr           = r->in.info_ctr;
7728
7729         return _spoolss_AddPrinterDriver(p, &a);
7730 }
7731
7732 /****************************************************************************
7733 ****************************************************************************/
7734
7735 struct _spoolss_paths {
7736         int type;
7737         const char *share;
7738         const char *dir;
7739 };
7740
7741 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7742
7743 static const struct _spoolss_paths spoolss_paths[]= {
7744         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7745         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7746 };
7747
7748 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7749                                           const char *servername,
7750                                           const char *environment,
7751                                           int component,
7752                                           char **path)
7753 {
7754         const char *pservername = NULL;
7755         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7756         const char *short_archi;
7757
7758         *path = NULL;
7759
7760         /* environment may be empty */
7761         if (environment && strlen(environment)) {
7762                 long_archi = environment;
7763         }
7764
7765         /* servername may be empty */
7766         if (servername && strlen(servername)) {
7767                 pservername = canon_servername(servername);
7768
7769                 if (!is_myname_or_ipaddr(pservername)) {
7770                         return WERR_INVALID_PARAM;
7771                 }
7772         }
7773
7774         if (!(short_archi = get_short_archi(long_archi))) {
7775                 return WERR_INVALID_ENVIRONMENT;
7776         }
7777
7778         switch (component) {
7779         case SPOOLSS_PRTPROCS_PATH:
7780         case SPOOLSS_DRIVER_PATH:
7781                 if (pservername) {
7782                         *path = talloc_asprintf(mem_ctx,
7783                                         "\\\\%s\\%s\\%s",
7784                                         pservername,
7785                                         spoolss_paths[component].share,
7786                                         short_archi);
7787                 } else {
7788                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7789                                         SPOOLSS_DEFAULT_SERVER_PATH,
7790                                         spoolss_paths[component].dir,
7791                                         short_archi);
7792                 }
7793                 break;
7794         default:
7795                 return WERR_INVALID_PARAM;
7796         }
7797
7798         if (!*path) {
7799                 return WERR_NOMEM;
7800         }
7801
7802         return WERR_OK;
7803 }
7804
7805 /****************************************************************************
7806 ****************************************************************************/
7807
7808 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7809                                           const char *servername,
7810                                           const char *environment,
7811                                           struct spoolss_DriverDirectoryInfo1 *r)
7812 {
7813         WERROR werr;
7814         char *path = NULL;
7815
7816         werr = compose_spoolss_server_path(mem_ctx,
7817                                            servername,
7818                                            environment,
7819                                            SPOOLSS_DRIVER_PATH,
7820                                            &path);
7821         if (!W_ERROR_IS_OK(werr)) {
7822                 return werr;
7823         }
7824
7825         DEBUG(4,("printer driver directory: [%s]\n", path));
7826
7827         r->directory_name = path;
7828
7829         return WERR_OK;
7830 }
7831
7832 /****************************************************************
7833  _spoolss_GetPrinterDriverDirectory
7834 ****************************************************************/
7835
7836 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7837                                           struct spoolss_GetPrinterDriverDirectory *r)
7838 {
7839         WERROR werror;
7840
7841         /* that's an [in out] buffer */
7842
7843         if (!r->in.buffer && (r->in.offered != 0)) {
7844                 return WERR_INVALID_PARAM;
7845         }
7846
7847         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7848                 r->in.level));
7849
7850         *r->out.needed = 0;
7851
7852         /* r->in.level is ignored */
7853
7854         werror = getprinterdriverdir_level_1(p->mem_ctx,
7855                                              r->in.server,
7856                                              r->in.environment,
7857                                              &r->out.info->info1);
7858         if (!W_ERROR_IS_OK(werror)) {
7859                 TALLOC_FREE(r->out.info);
7860                 return werror;
7861         }
7862
7863         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7864                                                r->out.info, r->in.level);
7865         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7866
7867         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7868 }
7869
7870 /****************************************************************
7871  _spoolss_EnumPrinterData
7872 ****************************************************************/
7873
7874 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7875                                 struct spoolss_EnumPrinterData *r)
7876 {
7877         NT_PRINTER_INFO_LEVEL *printer = NULL;
7878         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7879         int             snum;
7880         WERROR          result;
7881         REGISTRY_VALUE  *val = NULL;
7882         NT_PRINTER_DATA *p_data;
7883         int             i, key_index, num_values;
7884         int             name_length;
7885
7886         *r->out.value_needed    = 0;
7887         *r->out.type            = REG_NONE;
7888         *r->out.data_needed     = 0;
7889
7890         DEBUG(5,("_spoolss_EnumPrinterData\n"));
7891
7892         if (!Printer) {
7893                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
7894                         OUR_HANDLE(r->in.handle)));
7895                 return WERR_BADFID;
7896         }
7897
7898         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7899                 return WERR_BADFID;
7900         }
7901
7902         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7903         if (!W_ERROR_IS_OK(result)) {
7904                 return result;
7905         }
7906
7907         p_data = printer->info_2->data;
7908         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7909
7910         result = WERR_OK;
7911
7912         /*
7913          * The NT machine wants to know the biggest size of value and data
7914          *
7915          * cf: MSDN EnumPrinterData remark section
7916          */
7917
7918         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
7919
7920                 uint32_t biggest_valuesize = 0;
7921                 uint32_t biggest_datasize = 0;
7922
7923                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7924
7925                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7926
7927                 for ( i=0; i<num_values; i++ )
7928                 {
7929                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7930
7931                         name_length = strlen(val->valuename);
7932                         if ( strlen(val->valuename) > biggest_valuesize )
7933                                 biggest_valuesize = name_length;
7934
7935                         if ( val->size > biggest_datasize )
7936                                 biggest_datasize = val->size;
7937
7938                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7939                                 biggest_datasize));
7940                 }
7941
7942                 /* the value is an UNICODE string but real_value_size is the length
7943                    in bytes including the trailing 0 */
7944
7945                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7946                 *r->out.data_needed  = biggest_datasize;
7947
7948                 DEBUG(6,("final values: [%d], [%d]\n",
7949                         *r->out.value_needed, *r->out.data_needed));
7950
7951                 goto done;
7952         }
7953
7954         /*
7955          * the value len is wrong in NT sp3
7956          * that's the number of bytes not the number of unicode chars
7957          */
7958
7959         if (key_index != -1) {
7960                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
7961                                                 r->in.enum_index);
7962         }
7963
7964         if (!val) {
7965
7966                 /* out_value should default to "" or else NT4 has
7967                    problems unmarshalling the response */
7968
7969                 if (r->in.value_offered) {
7970                         *r->out.value_needed = 1;
7971                         r->out.value_name = talloc_strdup(r, "");
7972                         if (!r->out.value_name) {
7973                                 result = WERR_NOMEM;
7974                                 goto done;
7975                         }
7976                 } else {
7977                         r->out.value_name = NULL;
7978                         *r->out.value_needed = 0;
7979                 }
7980
7981                 /* the data is counted in bytes */
7982
7983                 *r->out.data_needed = r->in.data_offered;
7984
7985                 result = WERR_NO_MORE_ITEMS;
7986         } else {
7987                 /*
7988                  * the value is:
7989                  * - counted in bytes in the request
7990                  * - counted in UNICODE chars in the max reply
7991                  * - counted in bytes in the real size
7992                  *
7993                  * take a pause *before* coding not *during* coding
7994                  */
7995
7996                 /* name */
7997                 if (r->in.value_offered) {
7998                         r->out.value_name = talloc_strdup(r, regval_name(val));
7999                         if (!r->out.value_name) {
8000                                 result = WERR_NOMEM;
8001                                 goto done;
8002                         }
8003                         *r->out.value_needed = strlen_m(regval_name(val));
8004                 } else {
8005                         r->out.value_name = NULL;
8006                         *r->out.value_needed = 0;
8007                 }
8008
8009                 /* type */
8010
8011                 *r->out.type = regval_type(val);
8012
8013                 /* data - counted in bytes */
8014
8015                 if (r->out.data && regval_size(val)) {
8016                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
8017                 }
8018
8019                 *r->out.data_needed = regval_size(val);
8020         }
8021
8022 done:
8023         free_a_printer(&printer, 2);
8024         return result;
8025 }
8026
8027 /****************************************************************
8028  _spoolss_SetPrinterData
8029 ****************************************************************/
8030
8031 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8032                                struct spoolss_SetPrinterData *r)
8033 {
8034         NT_PRINTER_INFO_LEVEL *printer = NULL;
8035         int snum=0;
8036         WERROR result = WERR_OK;
8037         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8038         DATA_BLOB blob;
8039
8040         DEBUG(5,("_spoolss_SetPrinterData\n"));
8041
8042         if (!Printer) {
8043                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8044                         OUR_HANDLE(r->in.handle)));
8045                 return WERR_BADFID;
8046         }
8047
8048         if (Printer->printer_type == SPLHND_SERVER) {
8049                 DEBUG(10,("_spoolss_SetPrinterData: "
8050                         "Not implemented for server handles yet\n"));
8051                 return WERR_INVALID_PARAM;
8052         }
8053
8054         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8055                 return WERR_BADFID;
8056         }
8057
8058         /*
8059          * Access check : NT returns "access denied" if you make a
8060          * SetPrinterData call without the necessary privildge.
8061          * we were originally returning OK if nothing changed
8062          * which made Win2k issue **a lot** of SetPrinterData
8063          * when connecting to a printer  --jerry
8064          */
8065
8066         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8067                 DEBUG(3,("_spoolss_SetPrinterData: "
8068                         "change denied by handle access permissions\n"));
8069                 result = WERR_ACCESS_DENIED;
8070                 goto done;
8071         }
8072
8073         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8074         if (!W_ERROR_IS_OK(result)) {
8075                 return result;
8076         }
8077
8078         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8079                                           r->in.type, &r->in.data);
8080         if (!W_ERROR_IS_OK(result)) {
8081                 goto done;
8082         }
8083
8084         /*
8085          * When client side code sets a magic printer data key, detect it and save
8086          * the current printer data and the magic key's data (its the DEVMODE) for
8087          * future printer/driver initializations.
8088          */
8089         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8090                 /* Set devmode and printer initialization info */
8091                 result = save_driver_init(printer, 2, blob.data, blob.length);
8092
8093                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8094
8095                 goto done;
8096         }
8097
8098         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8099                                     r->in.value_name, r->in.type,
8100                                     blob.data, blob.length);
8101         if (W_ERROR_IS_OK(result)) {
8102                 result = mod_a_printer(printer, 2);
8103         }
8104
8105 done:
8106         free_a_printer(&printer, 2);
8107
8108         return result;
8109 }
8110
8111 /****************************************************************
8112  _spoolss_ResetPrinter
8113 ****************************************************************/
8114
8115 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8116                              struct spoolss_ResetPrinter *r)
8117 {
8118         POLICY_HND      *handle = r->in.handle;
8119         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8120         int             snum;
8121
8122         DEBUG(5,("_spoolss_ResetPrinter\n"));
8123
8124         /*
8125          * All we do is to check to see if the handle and queue is valid.
8126          * This call really doesn't mean anything to us because we only
8127          * support RAW printing.   --jerry
8128          */
8129
8130         if (!Printer) {
8131                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8132                         OUR_HANDLE(handle)));
8133                 return WERR_BADFID;
8134         }
8135
8136         if (!get_printer_snum(p,handle, &snum, NULL))
8137                 return WERR_BADFID;
8138
8139
8140         /* blindly return success */
8141         return WERR_OK;
8142 }
8143
8144 /****************************************************************
8145  _spoolss_DeletePrinterData
8146 ****************************************************************/
8147
8148 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8149                                   struct spoolss_DeletePrinterData *r)
8150 {
8151         POLICY_HND      *handle = r->in.handle;
8152         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8153         int             snum=0;
8154         WERROR          status = WERR_OK;
8155         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8156
8157         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8158
8159         if (!Printer) {
8160                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8161                         OUR_HANDLE(handle)));
8162                 return WERR_BADFID;
8163         }
8164
8165         if (!get_printer_snum(p, handle, &snum, NULL))
8166                 return WERR_BADFID;
8167
8168         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8169                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8170                         "printer properties change denied by handle\n"));
8171                 return WERR_ACCESS_DENIED;
8172         }
8173
8174         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8175         if (!W_ERROR_IS_OK(status))
8176                 return status;
8177
8178         if (!r->in.value_name) {
8179                 free_a_printer(&printer, 2);
8180                 return WERR_NOMEM;
8181         }
8182
8183         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8184                                         r->in.value_name );
8185
8186         if ( W_ERROR_IS_OK(status) )
8187                 mod_a_printer( printer, 2 );
8188
8189         free_a_printer(&printer, 2);
8190
8191         return status;
8192 }
8193
8194 /****************************************************************
8195  _spoolss_AddForm
8196 ****************************************************************/
8197
8198 WERROR _spoolss_AddForm(pipes_struct *p,
8199                         struct spoolss_AddForm *r)
8200 {
8201         POLICY_HND *handle = r->in.handle;
8202         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8203         nt_forms_struct tmpForm;
8204         int snum;
8205         WERROR status = WERR_OK;
8206         NT_PRINTER_INFO_LEVEL *printer = NULL;
8207
8208         int count=0;
8209         nt_forms_struct *list=NULL;
8210         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8211
8212         DEBUG(5,("_spoolss_AddForm\n"));
8213
8214         if (!Printer) {
8215                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8216                         OUR_HANDLE(handle)));
8217                 return WERR_BADFID;
8218         }
8219
8220
8221         /* forms can be added on printer of on the print server handle */
8222
8223         if ( Printer->printer_type == SPLHND_PRINTER )
8224         {
8225                 if (!get_printer_snum(p,handle, &snum, NULL))
8226                         return WERR_BADFID;
8227
8228                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8229                 if (!W_ERROR_IS_OK(status))
8230                         goto done;
8231         }
8232
8233         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8234                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8235                 status = WERR_ACCESS_DENIED;
8236                 goto done;
8237         }
8238
8239         /* can't add if builtin */
8240
8241         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8242                 status = WERR_FILE_EXISTS;
8243                 goto done;
8244         }
8245
8246         count = get_ntforms(&list);
8247
8248         if(!add_a_form(&list, form, &count)) {
8249                 status =  WERR_NOMEM;
8250                 goto done;
8251         }
8252
8253         write_ntforms(&list, count);
8254
8255         /*
8256          * ChangeID must always be set if this is a printer
8257          */
8258
8259         if ( Printer->printer_type == SPLHND_PRINTER )
8260                 status = mod_a_printer(printer, 2);
8261
8262 done:
8263         if ( printer )
8264                 free_a_printer(&printer, 2);
8265         SAFE_FREE(list);
8266
8267         return status;
8268 }
8269
8270 /****************************************************************
8271  _spoolss_DeleteForm
8272 ****************************************************************/
8273
8274 WERROR _spoolss_DeleteForm(pipes_struct *p,
8275                            struct spoolss_DeleteForm *r)
8276 {
8277         POLICY_HND *handle = r->in.handle;
8278         const char *form_name = r->in.form_name;
8279         nt_forms_struct tmpForm;
8280         int count=0;
8281         nt_forms_struct *list=NULL;
8282         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8283         int snum;
8284         WERROR status = WERR_OK;
8285         NT_PRINTER_INFO_LEVEL *printer = NULL;
8286
8287         DEBUG(5,("_spoolss_DeleteForm\n"));
8288
8289         if (!Printer) {
8290                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8291                         OUR_HANDLE(handle)));
8292                 return WERR_BADFID;
8293         }
8294
8295         /* forms can be deleted on printer of on the print server handle */
8296
8297         if ( Printer->printer_type == SPLHND_PRINTER )
8298         {
8299                 if (!get_printer_snum(p,handle, &snum, NULL))
8300                         return WERR_BADFID;
8301
8302                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8303                 if (!W_ERROR_IS_OK(status))
8304                         goto done;
8305         }
8306
8307         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8308                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8309                 status = WERR_ACCESS_DENIED;
8310                 goto done;
8311         }
8312
8313         /* can't delete if builtin */
8314
8315         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8316                 status = WERR_INVALID_PARAM;
8317                 goto done;
8318         }
8319
8320         count = get_ntforms(&list);
8321
8322         if ( !delete_a_form(&list, form_name, &count, &status ))
8323                 goto done;
8324
8325         /*
8326          * ChangeID must always be set if this is a printer
8327          */
8328
8329         if ( Printer->printer_type == SPLHND_PRINTER )
8330                 status = mod_a_printer(printer, 2);
8331
8332 done:
8333         if ( printer )
8334                 free_a_printer(&printer, 2);
8335         SAFE_FREE(list);
8336
8337         return status;
8338 }
8339
8340 /****************************************************************
8341  _spoolss_SetForm
8342 ****************************************************************/
8343
8344 WERROR _spoolss_SetForm(pipes_struct *p,
8345                         struct spoolss_SetForm *r)
8346 {
8347         POLICY_HND *handle = r->in.handle;
8348         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8349         nt_forms_struct tmpForm;
8350         int snum;
8351         WERROR status = WERR_OK;
8352         NT_PRINTER_INFO_LEVEL *printer = NULL;
8353
8354         int count=0;
8355         nt_forms_struct *list=NULL;
8356         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8357
8358         DEBUG(5,("_spoolss_SetForm\n"));
8359
8360         if (!Printer) {
8361                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8362                         OUR_HANDLE(handle)));
8363                 return WERR_BADFID;
8364         }
8365
8366         /* forms can be modified on printer of on the print server handle */
8367
8368         if ( Printer->printer_type == SPLHND_PRINTER )
8369         {
8370                 if (!get_printer_snum(p,handle, &snum, NULL))
8371                         return WERR_BADFID;
8372
8373                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8374                 if (!W_ERROR_IS_OK(status))
8375                         goto done;
8376         }
8377
8378         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8379                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8380                 status = WERR_ACCESS_DENIED;
8381                 goto done;
8382         }
8383
8384         /* can't set if builtin */
8385         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8386                 status = WERR_INVALID_PARAM;
8387                 goto done;
8388         }
8389
8390         count = get_ntforms(&list);
8391         update_a_form(&list, form, count);
8392         write_ntforms(&list, count);
8393
8394         /*
8395          * ChangeID must always be set if this is a printer
8396          */
8397
8398         if ( Printer->printer_type == SPLHND_PRINTER )
8399                 status = mod_a_printer(printer, 2);
8400
8401
8402 done:
8403         if ( printer )
8404                 free_a_printer(&printer, 2);
8405         SAFE_FREE(list);
8406
8407         return status;
8408 }
8409
8410 /****************************************************************************
8411  fill_print_processor1
8412 ****************************************************************************/
8413
8414 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8415                                     struct spoolss_PrintProcessorInfo1 *r,
8416                                     const char *print_processor_name)
8417 {
8418         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8419         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8420
8421         return WERR_OK;
8422 }
8423
8424 /****************************************************************************
8425  enumprintprocessors level 1.
8426 ****************************************************************************/
8427
8428 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8429                                           union spoolss_PrintProcessorInfo **info_p,
8430                                           uint32_t *count)
8431 {
8432         union spoolss_PrintProcessorInfo *info;
8433         WERROR result;
8434
8435         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8436         W_ERROR_HAVE_NO_MEMORY(info);
8437
8438         *count = 1;
8439
8440         result = fill_print_processor1(info, &info[0].info1, "winprint");
8441         if (!W_ERROR_IS_OK(result)) {
8442                 goto out;
8443         }
8444
8445  out:
8446         if (!W_ERROR_IS_OK(result)) {
8447                 TALLOC_FREE(info);
8448                 *count = 0;
8449                 return result;
8450         }
8451
8452         *info_p = info;
8453
8454         return WERR_OK;
8455 }
8456
8457 /****************************************************************
8458  _spoolss_EnumPrintProcessors
8459 ****************************************************************/
8460
8461 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8462                                     struct spoolss_EnumPrintProcessors *r)
8463 {
8464         WERROR result;
8465
8466         /* that's an [in out] buffer */
8467
8468         if (!r->in.buffer && (r->in.offered != 0)) {
8469                 return WERR_INVALID_PARAM;
8470         }
8471
8472         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8473
8474         /*
8475          * Enumerate the print processors ...
8476          *
8477          * Just reply with "winprint", to keep NT happy
8478          * and I can use my nice printer checker.
8479          */
8480
8481         *r->out.count = 0;
8482         *r->out.needed = 0;
8483         *r->out.info = NULL;
8484
8485         switch (r->in.level) {
8486         case 1:
8487                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8488                                                      r->out.count);
8489                 break;
8490         default:
8491                 return WERR_UNKNOWN_LEVEL;
8492         }
8493
8494         if (!W_ERROR_IS_OK(result)) {
8495                 return result;
8496         }
8497
8498         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8499                                                      spoolss_EnumPrintProcessors, NULL,
8500                                                      *r->out.info, r->in.level,
8501                                                      *r->out.count);
8502         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8503         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8504
8505         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8506 }
8507
8508 /****************************************************************************
8509  fill_printprocdatatype1
8510 ****************************************************************************/
8511
8512 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8513                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8514                                       const char *name_array)
8515 {
8516         r->name_array = talloc_strdup(mem_ctx, name_array);
8517         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8518
8519         return WERR_OK;
8520 }
8521
8522 /****************************************************************************
8523  enumprintprocdatatypes level 1.
8524 ****************************************************************************/
8525
8526 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8527                                              union spoolss_PrintProcDataTypesInfo **info_p,
8528                                              uint32_t *count)
8529 {
8530         WERROR result;
8531         union spoolss_PrintProcDataTypesInfo *info;
8532
8533         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8534         W_ERROR_HAVE_NO_MEMORY(info);
8535
8536         *count = 1;
8537
8538         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8539         if (!W_ERROR_IS_OK(result)) {
8540                 goto out;
8541         }
8542
8543  out:
8544         if (!W_ERROR_IS_OK(result)) {
8545                 TALLOC_FREE(info);
8546                 *count = 0;
8547                 return result;
8548         }
8549
8550         *info_p = info;
8551
8552         return WERR_OK;
8553 }
8554
8555 /****************************************************************
8556  _spoolss_EnumPrintProcDataTypes
8557 ****************************************************************/
8558
8559 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8560                                        struct spoolss_EnumPrintProcDataTypes *r)
8561 {
8562         WERROR result;
8563
8564         /* that's an [in out] buffer */
8565
8566         if (!r->in.buffer && (r->in.offered != 0)) {
8567                 return WERR_INVALID_PARAM;
8568         }
8569
8570         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8571
8572         *r->out.count = 0;
8573         *r->out.needed = 0;
8574         *r->out.info = NULL;
8575
8576         switch (r->in.level) {
8577         case 1:
8578                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8579                                                         r->out.count);
8580                 break;
8581         default:
8582                 return WERR_UNKNOWN_LEVEL;
8583         }
8584
8585         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8586                                                      spoolss_EnumPrintProcDataTypes, NULL,
8587                                                      *r->out.info, r->in.level,
8588                                                      *r->out.count);
8589         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8590         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8591
8592         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8593 }
8594
8595 /****************************************************************************
8596  fill_monitor_1
8597 ****************************************************************************/
8598
8599 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8600                              struct spoolss_MonitorInfo1 *r,
8601                              const char *monitor_name)
8602 {
8603         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8604         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8605
8606         return WERR_OK;
8607 }
8608
8609 /****************************************************************************
8610  fill_monitor_2
8611 ****************************************************************************/
8612
8613 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8614                              struct spoolss_MonitorInfo2 *r,
8615                              const char *monitor_name,
8616                              const char *environment,
8617                              const char *dll_name)
8618 {
8619         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8620         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8621         r->environment                  = talloc_strdup(mem_ctx, environment);
8622         W_ERROR_HAVE_NO_MEMORY(r->environment);
8623         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8624         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8625
8626         return WERR_OK;
8627 }
8628
8629 /****************************************************************************
8630  enumprintmonitors level 1.
8631 ****************************************************************************/
8632
8633 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8634                                         union spoolss_MonitorInfo **info_p,
8635                                         uint32_t *count)
8636 {
8637         union spoolss_MonitorInfo *info;
8638         WERROR result = WERR_OK;
8639
8640         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8641         W_ERROR_HAVE_NO_MEMORY(info);
8642
8643         *count = 2;
8644
8645         result = fill_monitor_1(info, &info[0].info1,
8646                                 SPL_LOCAL_PORT /* FIXME */);
8647         if (!W_ERROR_IS_OK(result)) {
8648                 goto out;
8649         }
8650
8651         result = fill_monitor_1(info, &info[1].info1,
8652                                 SPL_TCPIP_PORT /* FIXME */);
8653         if (!W_ERROR_IS_OK(result)) {
8654                 goto out;
8655         }
8656
8657 out:
8658         if (!W_ERROR_IS_OK(result)) {
8659                 TALLOC_FREE(info);
8660                 *count = 0;
8661                 return result;
8662         }
8663
8664         *info_p = info;
8665
8666         return WERR_OK;
8667 }
8668
8669 /****************************************************************************
8670  enumprintmonitors level 2.
8671 ****************************************************************************/
8672
8673 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8674                                         union spoolss_MonitorInfo **info_p,
8675                                         uint32_t *count)
8676 {
8677         union spoolss_MonitorInfo *info;
8678         WERROR result = WERR_OK;
8679
8680         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8681         W_ERROR_HAVE_NO_MEMORY(info);
8682
8683         *count = 2;
8684
8685         result = fill_monitor_2(info, &info[0].info2,
8686                                 SPL_LOCAL_PORT, /* FIXME */
8687                                 "Windows NT X86", /* FIXME */
8688                                 "localmon.dll");
8689         if (!W_ERROR_IS_OK(result)) {
8690                 goto out;
8691         }
8692
8693         result = fill_monitor_2(info, &info[1].info2,
8694                                 SPL_TCPIP_PORT, /* FIXME */
8695                                 "Windows NT X86", /* FIXME */
8696                                 "tcpmon.dll");
8697         if (!W_ERROR_IS_OK(result)) {
8698                 goto out;
8699         }
8700
8701 out:
8702         if (!W_ERROR_IS_OK(result)) {
8703                 TALLOC_FREE(info);
8704                 *count = 0;
8705                 return result;
8706         }
8707
8708         *info_p = info;
8709
8710         return WERR_OK;
8711 }
8712
8713 /****************************************************************
8714  _spoolss_EnumMonitors
8715 ****************************************************************/
8716
8717 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8718                              struct spoolss_EnumMonitors *r)
8719 {
8720         WERROR result;
8721
8722         /* that's an [in out] buffer */
8723
8724         if (!r->in.buffer && (r->in.offered != 0)) {
8725                 return WERR_INVALID_PARAM;
8726         }
8727
8728         DEBUG(5,("_spoolss_EnumMonitors\n"));
8729
8730         /*
8731          * Enumerate the print monitors ...
8732          *
8733          * Just reply with "Local Port", to keep NT happy
8734          * and I can use my nice printer checker.
8735          */
8736
8737         *r->out.count = 0;
8738         *r->out.needed = 0;
8739         *r->out.info = NULL;
8740
8741         switch (r->in.level) {
8742         case 1:
8743                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8744                                                    r->out.count);
8745                 break;
8746         case 2:
8747                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8748                                                    r->out.count);
8749                 break;
8750         default:
8751                 return WERR_UNKNOWN_LEVEL;
8752         }
8753
8754         if (!W_ERROR_IS_OK(result)) {
8755                 return result;
8756         }
8757
8758         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8759                                                      spoolss_EnumMonitors, NULL,
8760                                                      *r->out.info, r->in.level,
8761                                                      *r->out.count);
8762         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8763         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8764
8765         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8766 }
8767
8768 /****************************************************************************
8769 ****************************************************************************/
8770
8771 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8772                              const print_queue_struct *queue,
8773                              int count, int snum,
8774                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8775                              uint32_t jobid,
8776                              struct spoolss_JobInfo1 *r)
8777 {
8778         int i = 0;
8779         bool found = false;
8780
8781         for (i=0; i<count && found == false; i++) {
8782                 if (queue[i].job == (int)jobid) {
8783                         found = true;
8784                 }
8785         }
8786
8787         if (found == false) {
8788                 /* NT treats not found as bad param... yet another bad choice */
8789                 return WERR_INVALID_PARAM;
8790         }
8791
8792         return fill_job_info1(mem_ctx,
8793                               r,
8794                               &queue[i-1],
8795                               i,
8796                               snum,
8797                               ntprinter);
8798 }
8799
8800 /****************************************************************************
8801 ****************************************************************************/
8802
8803 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8804                              const print_queue_struct *queue,
8805                              int count, int snum,
8806                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8807                              uint32_t jobid,
8808                              struct spoolss_JobInfo2 *r)
8809 {
8810         int i = 0;
8811         bool found = false;
8812         struct spoolss_DeviceMode *devmode;
8813         NT_DEVICEMODE *nt_devmode;
8814         WERROR result;
8815
8816         for (i=0; i<count && found == false; i++) {
8817                 if (queue[i].job == (int)jobid) {
8818                         found = true;
8819                 }
8820         }
8821
8822         if (found == false) {
8823                 /* NT treats not found as bad param... yet another bad
8824                    choice */
8825                 return WERR_INVALID_PARAM;
8826         }
8827
8828         /*
8829          * if the print job does not have a DEVMODE associated with it,
8830          * just use the one for the printer. A NULL devicemode is not
8831          *  a failure condition
8832          */
8833
8834         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8835         if (nt_devmode) {
8836                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8837                 W_ERROR_HAVE_NO_MEMORY(devmode);
8838                 result = convert_nt_devicemode_new(devmode, devmode, nt_devmode);
8839                 if (!W_ERROR_IS_OK(result)) {
8840                         return result;
8841                 }
8842         } else {
8843                 devmode = construct_dev_mode_new(mem_ctx, lp_const_servicename(snum));
8844                 W_ERROR_HAVE_NO_MEMORY(devmode);
8845         }
8846
8847         return fill_job_info2(mem_ctx,
8848                               r,
8849                               &queue[i-1],
8850                               i,
8851                               snum,
8852                               ntprinter,
8853                               devmode);
8854 }
8855
8856 /****************************************************************
8857  _spoolss_GetJob
8858 ****************************************************************/
8859
8860 WERROR _spoolss_GetJob(pipes_struct *p,
8861                        struct spoolss_GetJob *r)
8862 {
8863         WERROR result = WERR_OK;
8864         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8865         int snum;
8866         int count;
8867         print_queue_struct      *queue = NULL;
8868         print_status_struct prt_status;
8869
8870         /* that's an [in out] buffer */
8871
8872         if (!r->in.buffer && (r->in.offered != 0)) {
8873                 return WERR_INVALID_PARAM;
8874         }
8875
8876         DEBUG(5,("_spoolss_GetJob\n"));
8877
8878         *r->out.needed = 0;
8879
8880         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8881                 return WERR_BADFID;
8882         }
8883
8884         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8885         if (!W_ERROR_IS_OK(result)) {
8886                 return result;
8887         }
8888
8889         count = print_queue_status(snum, &queue, &prt_status);
8890
8891         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8892                      count, prt_status.status, prt_status.message));
8893
8894         switch (r->in.level) {
8895         case 1:
8896                 result = getjob_level_1(p->mem_ctx,
8897                                         queue, count, snum, ntprinter,
8898                                         r->in.job_id, &r->out.info->info1);
8899                 break;
8900         case 2:
8901                 result = getjob_level_2(p->mem_ctx,
8902                                         queue, count, snum, ntprinter,
8903                                         r->in.job_id, &r->out.info->info2);
8904                 break;
8905         default:
8906                 result = WERR_UNKNOWN_LEVEL;
8907                 break;
8908         }
8909
8910         SAFE_FREE(queue);
8911         free_a_printer(&ntprinter, 2);
8912
8913         if (!W_ERROR_IS_OK(result)) {
8914                 TALLOC_FREE(r->out.info);
8915                 return result;
8916         }
8917
8918         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
8919                                                r->out.info, r->in.level);
8920         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8921
8922         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8923 }
8924
8925 /****************************************************************
8926  _spoolss_GetPrinterDataEx
8927
8928  From MSDN documentation of GetPrinterDataEx: pass request
8929  to GetPrinterData if key is "PrinterDriverData".
8930 ****************************************************************/
8931
8932 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8933                                  struct spoolss_GetPrinterDataEx *r)
8934 {
8935
8936         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8937         REGISTRY_VALUE          *val = NULL;
8938         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8939         int                     snum = 0;
8940         WERROR result = WERR_OK;
8941
8942         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8943
8944         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8945                 r->in.key_name, r->in.value_name));
8946
8947         /* in case of problem, return some default values */
8948
8949         *r->out.needed  = 0;
8950         *r->out.type    = REG_NONE;
8951
8952         if (!Printer) {
8953                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8954                         OUR_HANDLE(r->in.handle)));
8955                 result = WERR_BADFID;
8956                 goto done;
8957         }
8958
8959         /* Is the handle to a printer or to the server? */
8960
8961         if (Printer->printer_type == SPLHND_SERVER) {
8962                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
8963                         "Not implemented for server handles yet\n"));
8964                 result = WERR_INVALID_PARAM;
8965                 goto done;
8966         }
8967
8968         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8969                 return WERR_BADFID;
8970         }
8971
8972         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8973         if (!W_ERROR_IS_OK(result)) {
8974                 goto done;
8975         }
8976
8977         /* check to see if the keyname is valid */
8978         if (!strlen(r->in.key_name)) {
8979                 result = WERR_INVALID_PARAM;
8980                 goto done;
8981         }
8982
8983         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8984                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8985                         "Invalid keyname [%s]\n", r->in.key_name ));
8986                 result = WERR_BADFILE;
8987                 goto done;
8988         }
8989
8990         /* When given a new keyname, we should just create it */
8991
8992         val = get_printer_data(printer->info_2,
8993                                r->in.key_name, r->in.value_name);
8994         if (!val) {
8995                 result = WERR_BADFILE;
8996                 goto done;
8997         }
8998
8999         *r->out.needed = regval_size(val);
9000
9001         if (*r->out.needed > r->in.offered) {
9002                 result = WERR_MORE_DATA;
9003                 goto done;
9004         }
9005
9006         *r->out.type = regval_type(val);
9007
9008         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9009
9010  done:
9011         if (printer) {
9012                 free_a_printer(&printer, 2);
9013         }
9014
9015         return result;
9016 }
9017
9018 /****************************************************************
9019  _spoolss_SetPrinterDataEx
9020 ****************************************************************/
9021
9022 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9023                                  struct spoolss_SetPrinterDataEx *r)
9024 {
9025         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9026         int                     snum = 0;
9027         WERROR                  result = WERR_OK;
9028         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9029         char                    *oid_string;
9030
9031         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9032
9033         /* From MSDN documentation of SetPrinterDataEx: pass request to
9034            SetPrinterData if key is "PrinterDriverData" */
9035
9036         if (!Printer) {
9037                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9038                         OUR_HANDLE(r->in.handle)));
9039                 return WERR_BADFID;
9040         }
9041
9042         if (Printer->printer_type == SPLHND_SERVER) {
9043                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9044                         "Not implemented for server handles yet\n"));
9045                 return WERR_INVALID_PARAM;
9046         }
9047
9048         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9049                 return WERR_BADFID;
9050         }
9051
9052         /*
9053          * Access check : NT returns "access denied" if you make a
9054          * SetPrinterData call without the necessary privildge.
9055          * we were originally returning OK if nothing changed
9056          * which made Win2k issue **a lot** of SetPrinterData
9057          * when connecting to a printer  --jerry
9058          */
9059
9060         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9061                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9062                         "change denied by handle access permissions\n"));
9063                 return WERR_ACCESS_DENIED;
9064         }
9065
9066         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9067         if (!W_ERROR_IS_OK(result)) {
9068                 return result;
9069         }
9070
9071         /* check for OID in valuename */
9072
9073         oid_string = strchr(r->in.value_name, ',');
9074         if (oid_string) {
9075                 *oid_string = '\0';
9076                 oid_string++;
9077         }
9078
9079         /* save the registry data */
9080
9081         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9082                                     r->in.type, r->in.buffer, r->in.offered);
9083
9084         if (W_ERROR_IS_OK(result)) {
9085                 /* save the OID if one was specified */
9086                 if (oid_string) {
9087                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9088                                 r->in.key_name, SPOOL_OID_KEY);
9089                         if (!str) {
9090                                 result = WERR_NOMEM;
9091                                 goto done;
9092                         }
9093
9094                         /*
9095                          * I'm not checking the status here on purpose.  Don't know
9096                          * if this is right, but I'm returning the status from the
9097                          * previous set_printer_dataex() call.  I have no idea if
9098                          * this is right.    --jerry
9099                          */
9100
9101                         set_printer_dataex(printer, str, r->in.value_name,
9102                                            REG_SZ, (uint8_t *)oid_string,
9103                                            strlen(oid_string)+1);
9104                 }
9105
9106                 result = mod_a_printer(printer, 2);
9107         }
9108
9109  done:
9110         free_a_printer(&printer, 2);
9111
9112         return result;
9113 }
9114
9115 /****************************************************************
9116  _spoolss_DeletePrinterDataEx
9117 ****************************************************************/
9118
9119 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9120                                     struct spoolss_DeletePrinterDataEx *r)
9121 {
9122         POLICY_HND      *handle = r->in.handle;
9123         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9124         int             snum=0;
9125         WERROR          status = WERR_OK;
9126         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9127
9128         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9129
9130         if (!Printer) {
9131                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9132                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9133                 return WERR_BADFID;
9134         }
9135
9136         if (!get_printer_snum(p, handle, &snum, NULL))
9137                 return WERR_BADFID;
9138
9139         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9140                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9141                         "printer properties change denied by handle\n"));
9142                 return WERR_ACCESS_DENIED;
9143         }
9144
9145         if (!r->in.value_name || !r->in.key_name) {
9146                 return WERR_NOMEM;
9147         }
9148
9149         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9150         if (!W_ERROR_IS_OK(status))
9151                 return status;
9152
9153         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9154
9155         if ( W_ERROR_IS_OK(status) )
9156                 mod_a_printer( printer, 2 );
9157
9158         free_a_printer(&printer, 2);
9159
9160         return status;
9161 }
9162
9163 /****************************************************************
9164  _spoolss_EnumPrinterKey
9165 ****************************************************************/
9166
9167 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9168                                struct spoolss_EnumPrinterKey *r)
9169 {
9170         fstring         *keynames = NULL;
9171         int             num_keys;
9172         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9173         NT_PRINTER_DATA *data;
9174         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9175         int             snum = 0;
9176         WERROR          result = WERR_BADFILE;
9177         int i;
9178         const char **array = NULL;
9179
9180
9181         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9182
9183         if (!Printer) {
9184                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9185                         OUR_HANDLE(r->in.handle)));
9186                 return WERR_BADFID;
9187         }
9188
9189         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9190                 return WERR_BADFID;
9191         }
9192
9193         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9194         if (!W_ERROR_IS_OK(result)) {
9195                 return result;
9196         }
9197
9198         /* get the list of subkey names */
9199
9200         data = printer->info_2->data;
9201
9202         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9203         if (num_keys == -1) {
9204                 result = WERR_BADFILE;
9205                 goto done;
9206         }
9207
9208         *r->out.needed = 4;
9209
9210         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9211         if (!array) {
9212                 result = WERR_NOMEM;
9213                 goto done;
9214         }
9215
9216         for (i=0; i < num_keys; i++) {
9217                 array[i] = talloc_strdup(array, keynames[i]);
9218                 if (!array[i]) {
9219                         result = WERR_NOMEM;
9220                         goto done;
9221                 }
9222
9223                 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9224         }
9225
9226         if (r->in.offered < *r->out.needed) {
9227                 result = WERR_MORE_DATA;
9228                 goto done;
9229         }
9230
9231         result = WERR_OK;
9232
9233         *r->out.key_buffer = array;
9234
9235  done:
9236         if (!W_ERROR_IS_OK(result)) {
9237                 TALLOC_FREE(array);
9238                 ZERO_STRUCTP(r->out.key_buffer);
9239         }
9240
9241         free_a_printer(&printer, 2);
9242         SAFE_FREE(keynames);
9243
9244         return result;
9245 }
9246
9247 /****************************************************************
9248  _spoolss_DeletePrinterKey
9249 ****************************************************************/
9250
9251 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9252                                  struct spoolss_DeletePrinterKey *r)
9253 {
9254         POLICY_HND              *handle = r->in.handle;
9255         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9256         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9257         int                     snum=0;
9258         WERROR                  status;
9259
9260         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9261
9262         if (!Printer) {
9263                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9264                         OUR_HANDLE(handle)));
9265                 return WERR_BADFID;
9266         }
9267
9268         /* if keyname == NULL, return error */
9269
9270         if ( !r->in.key_name )
9271                 return WERR_INVALID_PARAM;
9272
9273         if (!get_printer_snum(p, handle, &snum, NULL))
9274                 return WERR_BADFID;
9275
9276         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9277                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9278                         "printer properties change denied by handle\n"));
9279                 return WERR_ACCESS_DENIED;
9280         }
9281
9282         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9283         if (!W_ERROR_IS_OK(status))
9284                 return status;
9285
9286         /* delete the key and all subneys */
9287
9288         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9289
9290         if ( W_ERROR_IS_OK(status) )
9291                 status = mod_a_printer(printer, 2);
9292
9293         free_a_printer( &printer, 2 );
9294
9295         return status;
9296 }
9297
9298
9299 /********************************************************************
9300  * spoolss_enumprinterdataex
9301  ********************************************************************/
9302
9303 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9304 {
9305         POLICY_HND      *handle = &q_u->handle;
9306         uint32          in_size = q_u->size;
9307         uint32          num_entries,
9308                         needed;
9309         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9310         PRINTER_ENUM_VALUES     *enum_values = NULL;
9311         NT_PRINTER_DATA         *p_data;
9312         fstring         key;
9313         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9314         int             snum;
9315         WERROR          result;
9316         int             key_index;
9317         int             i;
9318         REGISTRY_VALUE  *val;
9319         char            *value_name;
9320         uint32          data_len;
9321
9322
9323         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9324
9325         if (!Printer) {
9326                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9327                 return WERR_BADFID;
9328         }
9329
9330         /*
9331          * first check for a keyname of NULL or "".  Win2k seems to send
9332          * this a lot and we should send back WERR_INVALID_PARAM
9333          * no need to spend time looking up the printer in this case.
9334          * --jerry
9335          */
9336
9337         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9338         if ( !strlen(key) ) {
9339                 result = WERR_INVALID_PARAM;
9340                 goto done;
9341         }
9342
9343         /* get the printer off of disk */
9344
9345         if (!get_printer_snum(p,handle, &snum, NULL))
9346                 return WERR_BADFID;
9347
9348         ZERO_STRUCT(printer);
9349         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9350         if (!W_ERROR_IS_OK(result))
9351                 return result;
9352
9353         /* now look for a match on the key name */
9354
9355         p_data = printer->info_2->data;
9356
9357         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9358         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9359         {
9360                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9361                 result = WERR_INVALID_PARAM;
9362                 goto done;
9363         }
9364
9365         result = WERR_OK;
9366         needed = 0;
9367
9368         /* allocate the memory for the array of pointers -- if necessary */
9369
9370         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9371         if ( num_entries )
9372         {
9373                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9374                 {
9375                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9376                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9377                         result = WERR_NOMEM;
9378                         goto done;
9379                 }
9380
9381                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9382         }
9383
9384         /*
9385          * loop through all params and build the array to pass
9386          * back to the  client
9387          */
9388
9389         for ( i=0; i<num_entries; i++ )
9390         {
9391                 /* lookup the registry value */
9392
9393                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9394                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9395
9396                 /* copy the data */
9397
9398                 value_name = regval_name( val );
9399                 init_unistr( &enum_values[i].valuename, value_name );
9400                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9401                 enum_values[i].type      = regval_type( val );
9402
9403                 data_len = regval_size( val );
9404                 if ( data_len ) {
9405                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9406                         {
9407                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9408                                         data_len ));
9409                                 result = WERR_NOMEM;
9410                                 goto done;
9411                         }
9412                 }
9413                 enum_values[i].data_len = data_len;
9414
9415                 /* keep track of the size of the array in bytes */
9416
9417                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9418         }
9419
9420         /* housekeeping information in the reply */
9421
9422         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9423          * the hand marshalled container size is a multiple
9424          * of 4 bytes for RPC alignment.
9425          */
9426
9427         if (needed % 4) {
9428                 needed += 4-(needed % 4);
9429         }
9430
9431         r_u->needed     = needed;
9432         r_u->returned   = num_entries;
9433
9434         if (needed > in_size) {
9435                 result = WERR_MORE_DATA;
9436                 goto done;
9437         }
9438
9439         /* copy data into the reply */
9440
9441         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9442            response buffer size is != the offered buffer size
9443
9444                 r_u->ctr.size           = r_u->needed;
9445         */
9446         r_u->ctr.size           = in_size;
9447
9448         r_u->ctr.size_of_array  = r_u->returned;
9449         r_u->ctr.values         = enum_values;
9450
9451 done:
9452         if ( printer )
9453         free_a_printer(&printer, 2);
9454
9455         return result;
9456 }
9457
9458 /****************************************************************************
9459 ****************************************************************************/
9460
9461 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9462                                                  const char *servername,
9463                                                  const char *environment,
9464                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9465 {
9466         WERROR werr;
9467         char *path = NULL;
9468
9469         werr = compose_spoolss_server_path(mem_ctx,
9470                                            servername,
9471                                            environment,
9472                                            SPOOLSS_PRTPROCS_PATH,
9473                                            &path);
9474         if (!W_ERROR_IS_OK(werr)) {
9475                 return werr;
9476         }
9477
9478         DEBUG(4,("print processor directory: [%s]\n", path));
9479
9480         r->directory_name = path;
9481
9482         return WERR_OK;
9483 }
9484
9485 /****************************************************************
9486  _spoolss_GetPrintProcessorDirectory
9487 ****************************************************************/
9488
9489 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9490                                            struct spoolss_GetPrintProcessorDirectory *r)
9491 {
9492         WERROR result;
9493
9494         /* that's an [in out] buffer */
9495
9496         if (!r->in.buffer && (r->in.offered != 0)) {
9497                 return WERR_INVALID_PARAM;
9498         }
9499
9500         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9501                 r->in.level));
9502
9503         *r->out.needed = 0;
9504
9505         /* r->in.level is ignored */
9506
9507         result = getprintprocessordirectory_level_1(p->mem_ctx,
9508                                                     r->in.server,
9509                                                     r->in.environment,
9510                                                     &r->out.info->info1);
9511         if (!W_ERROR_IS_OK(result)) {
9512                 TALLOC_FREE(r->out.info);
9513                 return result;
9514         }
9515
9516         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9517                                                r->out.info, r->in.level);
9518         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9519
9520         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9521 }
9522
9523 /*******************************************************************
9524  ********************************************************************/
9525
9526 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9527                                const char *dllname)
9528 {
9529         enum ndr_err_code ndr_err;
9530         struct spoolss_MonitorUi ui;
9531
9532         ui.dll_name = dllname;
9533
9534         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9535                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9536         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9537                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9538         }
9539         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9540 }
9541
9542 /*******************************************************************
9543  Streams the monitor UI DLL name in UNICODE
9544 *******************************************************************/
9545
9546 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9547                                NT_USER_TOKEN *token, DATA_BLOB *in,
9548                                DATA_BLOB *out, uint32_t *needed)
9549 {
9550         const char *dllname = "tcpmonui.dll";
9551
9552         *needed = (strlen(dllname)+1) * 2;
9553
9554         if (out->length < *needed) {
9555                 return WERR_INSUFFICIENT_BUFFER;
9556         }
9557
9558         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9559                 return WERR_NOMEM;
9560         }
9561
9562         return WERR_OK;
9563 }
9564
9565 /*******************************************************************
9566  ********************************************************************/
9567
9568 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9569                              struct spoolss_PortData1 *port1,
9570                              const DATA_BLOB *buf)
9571 {
9572         enum ndr_err_code ndr_err;
9573         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9574                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9575         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9576                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9577         }
9578         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9579 }
9580
9581 /*******************************************************************
9582  ********************************************************************/
9583
9584 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9585                              struct spoolss_PortData2 *port2,
9586                              const DATA_BLOB *buf)
9587 {
9588         enum ndr_err_code ndr_err;
9589         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9590                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9591         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9592                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9593         }
9594         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9595 }
9596
9597 /*******************************************************************
9598  Create a new TCP/IP port
9599 *******************************************************************/
9600
9601 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9602                              NT_USER_TOKEN *token, DATA_BLOB *in,
9603                              DATA_BLOB *out, uint32_t *needed)
9604 {
9605         struct spoolss_PortData1 port1;
9606         struct spoolss_PortData2 port2;
9607         char *device_uri = NULL;
9608         uint32_t version;
9609
9610         const char *portname;
9611         const char *hostaddress;
9612         const char *queue;
9613         uint32_t port_number;
9614         uint32_t protocol;
9615
9616         /* peek for spoolss_PortData version */
9617
9618         if (!in || (in->length < (128 + 4))) {
9619                 return WERR_GENERAL_FAILURE;
9620         }
9621
9622         version = IVAL(in->data, 128);
9623
9624         switch (version) {
9625                 case 1:
9626                         ZERO_STRUCT(port1);
9627
9628                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9629                                 return WERR_NOMEM;
9630                         }
9631
9632                         portname        = port1.portname;
9633                         hostaddress     = port1.hostaddress;
9634                         queue           = port1.queue;
9635                         protocol        = port1.protocol;
9636                         port_number     = port1.port_number;
9637
9638                         break;
9639                 case 2:
9640                         ZERO_STRUCT(port2);
9641
9642                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9643                                 return WERR_NOMEM;
9644                         }
9645
9646                         portname        = port2.portname;
9647                         hostaddress     = port2.hostaddress;
9648                         queue           = port2.queue;
9649                         protocol        = port2.protocol;
9650                         port_number     = port2.port_number;
9651
9652                         break;
9653                 default:
9654                         DEBUG(1,("xcvtcp_addport: "
9655                                 "unknown version of port_data: %d\n", version));
9656                         return WERR_UNKNOWN_PORT;
9657         }
9658
9659         /* create the device URI and call the add_port_hook() */
9660
9661         switch (protocol) {
9662         case PROTOCOL_RAWTCP_TYPE:
9663                 device_uri = talloc_asprintf(mem_ctx,
9664                                 "socket://%s:%d/", hostaddress,
9665                                 port_number);
9666                 break;
9667
9668         case PROTOCOL_LPR_TYPE:
9669                 device_uri = talloc_asprintf(mem_ctx,
9670                         "lpr://%s/%s", hostaddress, queue );
9671                 break;
9672
9673         default:
9674                 return WERR_UNKNOWN_PORT;
9675         }
9676
9677         if (!device_uri) {
9678                 return WERR_NOMEM;
9679         }
9680
9681         return add_port_hook(mem_ctx, token, portname, device_uri);
9682 }
9683
9684 /*******************************************************************
9685 *******************************************************************/
9686
9687 struct xcv_api_table xcvtcp_cmds[] = {
9688         { "MonitorUI",  xcvtcp_monitorui },
9689         { "AddPort",    xcvtcp_addport},
9690         { NULL,         NULL }
9691 };
9692
9693 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9694                                      NT_USER_TOKEN *token, const char *command,
9695                                      DATA_BLOB *inbuf,
9696                                      DATA_BLOB *outbuf,
9697                                      uint32_t *needed )
9698 {
9699         int i;
9700
9701         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9702
9703         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9704                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9705                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9706         }
9707
9708         return WERR_BADFUNC;
9709 }
9710
9711 /*******************************************************************
9712 *******************************************************************/
9713 #if 0   /* don't support management using the "Local Port" monitor */
9714
9715 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9716                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9717                                  DATA_BLOB *out, uint32_t *needed)
9718 {
9719         const char *dllname = "localui.dll";
9720
9721         *needed = (strlen(dllname)+1) * 2;
9722
9723         if (out->length < *needed) {
9724                 return WERR_INSUFFICIENT_BUFFER;
9725         }
9726
9727         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9728                 return WERR_NOMEM;
9729         }
9730
9731         return WERR_OK;
9732 }
9733
9734 /*******************************************************************
9735 *******************************************************************/
9736
9737 struct xcv_api_table xcvlocal_cmds[] = {
9738         { "MonitorUI",  xcvlocal_monitorui },
9739         { NULL,         NULL }
9740 };
9741 #else
9742 struct xcv_api_table xcvlocal_cmds[] = {
9743         { NULL,         NULL }
9744 };
9745 #endif
9746
9747
9748
9749 /*******************************************************************
9750 *******************************************************************/
9751
9752 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9753                                        NT_USER_TOKEN *token, const char *command,
9754                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9755                                        uint32_t *needed)
9756 {
9757         int i;
9758
9759         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9760
9761         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9762                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9763                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9764         }
9765         return WERR_BADFUNC;
9766 }
9767
9768 /****************************************************************
9769  _spoolss_XcvData
9770 ****************************************************************/
9771
9772 WERROR _spoolss_XcvData(pipes_struct *p,
9773                         struct spoolss_XcvData *r)
9774 {
9775         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9776         DATA_BLOB out_data = data_blob_null;
9777         WERROR werror;
9778
9779         if (!Printer) {
9780                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9781                         OUR_HANDLE(r->in.handle)));
9782                 return WERR_BADFID;
9783         }
9784
9785         /* Has to be a handle to the TCP/IP port monitor */
9786
9787         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9788                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9789                 return WERR_BADFID;
9790         }
9791
9792         /* requires administrative access to the server */
9793
9794         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9795                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9796                 return WERR_ACCESS_DENIED;
9797         }
9798
9799         /* Allocate the outgoing buffer */
9800
9801         if (r->in.out_data_size) {
9802                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9803                 if (out_data.data == NULL) {
9804                         return WERR_NOMEM;
9805                 }
9806         }
9807
9808         switch ( Printer->printer_type ) {
9809         case SPLHND_PORTMON_TCP:
9810                 werror = process_xcvtcp_command(p->mem_ctx,
9811                                                 p->server_info->ptok,
9812                                                 r->in.function_name,
9813                                                 &r->in.in_data, &out_data,
9814                                                 r->out.needed);
9815                 break;
9816         case SPLHND_PORTMON_LOCAL:
9817                 werror = process_xcvlocal_command(p->mem_ctx,
9818                                                   p->server_info->ptok,
9819                                                   r->in.function_name,
9820                                                   &r->in.in_data, &out_data,
9821                                                   r->out.needed);
9822                 break;
9823         default:
9824                 werror = WERR_INVALID_PRINT_MONITOR;
9825         }
9826
9827         if (!W_ERROR_IS_OK(werror)) {
9828                 return werror;
9829         }
9830
9831         *r->out.status_code = 0;
9832
9833         memcpy(r->out.out_data, out_data.data, out_data.length);
9834
9835         return WERR_OK;
9836 }
9837
9838 /****************************************************************
9839  _spoolss_AddPrintProcessor
9840 ****************************************************************/
9841
9842 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9843                                   struct spoolss_AddPrintProcessor *r)
9844 {
9845         /* for now, just indicate success and ignore the add.  We'll
9846            automatically set the winprint processor for printer
9847            entries later.  Used to debug the LexMark Optra S 1855 PCL
9848            driver --jerry */
9849
9850         return WERR_OK;
9851 }
9852
9853 /****************************************************************
9854  _spoolss_AddPrinter
9855 ****************************************************************/
9856
9857 WERROR _spoolss_AddPrinter(pipes_struct *p,
9858                            struct spoolss_AddPrinter *r)
9859 {
9860         p->rng_fault_state = true;
9861         return WERR_NOT_SUPPORTED;
9862 }
9863
9864 /****************************************************************
9865  _spoolss_GetPrinterDriver
9866 ****************************************************************/
9867
9868 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9869                                  struct spoolss_GetPrinterDriver *r)
9870 {
9871         p->rng_fault_state = true;
9872         return WERR_NOT_SUPPORTED;
9873 }
9874
9875 /****************************************************************
9876  _spoolss_ReadPrinter
9877 ****************************************************************/
9878
9879 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9880                             struct spoolss_ReadPrinter *r)
9881 {
9882         p->rng_fault_state = true;
9883         return WERR_NOT_SUPPORTED;
9884 }
9885
9886 /****************************************************************
9887  _spoolss_WaitForPrinterChange
9888 ****************************************************************/
9889
9890 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9891                                      struct spoolss_WaitForPrinterChange *r)
9892 {
9893         p->rng_fault_state = true;
9894         return WERR_NOT_SUPPORTED;
9895 }
9896
9897 /****************************************************************
9898  _spoolss_AddPort
9899 ****************************************************************/
9900
9901 WERROR _spoolss_AddPort(pipes_struct *p,
9902                         struct spoolss_AddPort *r)
9903 {
9904         p->rng_fault_state = true;
9905         return WERR_NOT_SUPPORTED;
9906 }
9907
9908 /****************************************************************
9909  _spoolss_ConfigurePort
9910 ****************************************************************/
9911
9912 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9913                               struct spoolss_ConfigurePort *r)
9914 {
9915         p->rng_fault_state = true;
9916         return WERR_NOT_SUPPORTED;
9917 }
9918
9919 /****************************************************************
9920  _spoolss_DeletePort
9921 ****************************************************************/
9922
9923 WERROR _spoolss_DeletePort(pipes_struct *p,
9924                            struct spoolss_DeletePort *r)
9925 {
9926         p->rng_fault_state = true;
9927         return WERR_NOT_SUPPORTED;
9928 }
9929
9930 /****************************************************************
9931  _spoolss_CreatePrinterIC
9932 ****************************************************************/
9933
9934 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9935                                 struct spoolss_CreatePrinterIC *r)
9936 {
9937         p->rng_fault_state = true;
9938         return WERR_NOT_SUPPORTED;
9939 }
9940
9941 /****************************************************************
9942  _spoolss_PlayGDIScriptOnPrinterIC
9943 ****************************************************************/
9944
9945 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9946                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9947 {
9948         p->rng_fault_state = true;
9949         return WERR_NOT_SUPPORTED;
9950 }
9951
9952 /****************************************************************
9953  _spoolss_DeletePrinterIC
9954 ****************************************************************/
9955
9956 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9957                                 struct spoolss_DeletePrinterIC *r)
9958 {
9959         p->rng_fault_state = true;
9960         return WERR_NOT_SUPPORTED;
9961 }
9962
9963 /****************************************************************
9964  _spoolss_AddPrinterConnection
9965 ****************************************************************/
9966
9967 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9968                                      struct spoolss_AddPrinterConnection *r)
9969 {
9970         p->rng_fault_state = true;
9971         return WERR_NOT_SUPPORTED;
9972 }
9973
9974 /****************************************************************
9975  _spoolss_DeletePrinterConnection
9976 ****************************************************************/
9977
9978 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9979                                         struct spoolss_DeletePrinterConnection *r)
9980 {
9981         p->rng_fault_state = true;
9982         return WERR_NOT_SUPPORTED;
9983 }
9984
9985 /****************************************************************
9986  _spoolss_PrinterMessageBox
9987 ****************************************************************/
9988
9989 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9990                                   struct spoolss_PrinterMessageBox *r)
9991 {
9992         p->rng_fault_state = true;
9993         return WERR_NOT_SUPPORTED;
9994 }
9995
9996 /****************************************************************
9997  _spoolss_AddMonitor
9998 ****************************************************************/
9999
10000 WERROR _spoolss_AddMonitor(pipes_struct *p,
10001                            struct spoolss_AddMonitor *r)
10002 {
10003         p->rng_fault_state = true;
10004         return WERR_NOT_SUPPORTED;
10005 }
10006
10007 /****************************************************************
10008  _spoolss_DeleteMonitor
10009 ****************************************************************/
10010
10011 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10012                               struct spoolss_DeleteMonitor *r)
10013 {
10014         p->rng_fault_state = true;
10015         return WERR_NOT_SUPPORTED;
10016 }
10017
10018 /****************************************************************
10019  _spoolss_DeletePrintProcessor
10020 ****************************************************************/
10021
10022 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10023                                      struct spoolss_DeletePrintProcessor *r)
10024 {
10025         p->rng_fault_state = true;
10026         return WERR_NOT_SUPPORTED;
10027 }
10028
10029 /****************************************************************
10030  _spoolss_AddPrintProvidor
10031 ****************************************************************/
10032
10033 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10034                                  struct spoolss_AddPrintProvidor *r)
10035 {
10036         p->rng_fault_state = true;
10037         return WERR_NOT_SUPPORTED;
10038 }
10039
10040 /****************************************************************
10041  _spoolss_DeletePrintProvidor
10042 ****************************************************************/
10043
10044 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10045                                     struct spoolss_DeletePrintProvidor *r)
10046 {
10047         p->rng_fault_state = true;
10048         return WERR_NOT_SUPPORTED;
10049 }
10050
10051 /****************************************************************
10052  _spoolss_FindFirstPrinterChangeNotification
10053 ****************************************************************/
10054
10055 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10056                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10057 {
10058         p->rng_fault_state = true;
10059         return WERR_NOT_SUPPORTED;
10060 }
10061
10062 /****************************************************************
10063  _spoolss_FindNextPrinterChangeNotification
10064 ****************************************************************/
10065
10066 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10067                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10068 {
10069         p->rng_fault_state = true;
10070         return WERR_NOT_SUPPORTED;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10075 ****************************************************************/
10076
10077 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10078                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085  _spoolss_ReplyOpenPrinter
10086 ****************************************************************/
10087
10088 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10089                                  struct spoolss_ReplyOpenPrinter *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_RouterReplyPrinter
10097 ****************************************************************/
10098
10099 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10100                                    struct spoolss_RouterReplyPrinter *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107  _spoolss_ReplyClosePrinter
10108 ****************************************************************/
10109
10110 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10111                                   struct spoolss_ReplyClosePrinter *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118  _spoolss_AddPortEx
10119 ****************************************************************/
10120
10121 WERROR _spoolss_AddPortEx(pipes_struct *p,
10122                           struct spoolss_AddPortEx *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_RouterFindFirstPrinterChangeNotification
10130 ****************************************************************/
10131
10132 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10133                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140  _spoolss_SpoolerInit
10141 ****************************************************************/
10142
10143 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10144                             struct spoolss_SpoolerInit *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151  _spoolss_ResetPrinterEx
10152 ****************************************************************/
10153
10154 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10155                                struct spoolss_ResetPrinterEx *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162  _spoolss_RouterReplyPrinterEx
10163 ****************************************************************/
10164
10165 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10166                                      struct spoolss_RouterReplyPrinterEx *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173  _spoolss_44
10174 ****************************************************************/
10175
10176 WERROR _spoolss_44(pipes_struct *p,
10177                    struct spoolss_44 *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_47
10185 ****************************************************************/
10186
10187 WERROR _spoolss_47(pipes_struct *p,
10188                    struct spoolss_47 *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195  _spoolss_4a
10196 ****************************************************************/
10197
10198 WERROR _spoolss_4a(pipes_struct *p,
10199                    struct spoolss_4a *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206  _spoolss_4b
10207 ****************************************************************/
10208
10209 WERROR _spoolss_4b(pipes_struct *p,
10210                    struct spoolss_4b *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217  _spoolss_4c
10218 ****************************************************************/
10219
10220 WERROR _spoolss_4c(pipes_struct *p,
10221                    struct spoolss_4c *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228  _spoolss_EnumPrinterDataEx
10229 ****************************************************************/
10230
10231 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10232                                   struct spoolss_EnumPrinterDataEx *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239  _spoolss_53
10240 ****************************************************************/
10241
10242 WERROR _spoolss_53(pipes_struct *p,
10243                    struct spoolss_53 *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250  _spoolss_55
10251 ****************************************************************/
10252
10253 WERROR _spoolss_55(pipes_struct *p,
10254                    struct spoolss_55 *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_56
10262 ****************************************************************/
10263
10264 WERROR _spoolss_56(pipes_struct *p,
10265                    struct spoolss_56 *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272  _spoolss_57
10273 ****************************************************************/
10274
10275 WERROR _spoolss_57(pipes_struct *p,
10276                    struct spoolss_57 *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283  _spoolss_5a
10284 ****************************************************************/
10285
10286 WERROR _spoolss_5a(pipes_struct *p,
10287                    struct spoolss_5a *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294  _spoolss_5b
10295 ****************************************************************/
10296
10297 WERROR _spoolss_5b(pipes_struct *p,
10298                    struct spoolss_5b *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305  _spoolss_5c
10306 ****************************************************************/
10307
10308 WERROR _spoolss_5c(pipes_struct *p,
10309                    struct spoolss_5c *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316  _spoolss_5d
10317 ****************************************************************/
10318
10319 WERROR _spoolss_5d(pipes_struct *p,
10320                    struct spoolss_5d *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_5e
10328 ****************************************************************/
10329
10330 WERROR _spoolss_5e(pipes_struct *p,
10331                    struct spoolss_5e *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_5f
10339 ****************************************************************/
10340
10341 WERROR _spoolss_5f(pipes_struct *p,
10342                    struct spoolss_5f *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }
10347