899fed21674bfde0616bb5609dbf83358d4c1653
[metze/samba/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner                 2009.
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 3 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
24  */
25
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27    up, all the errors returned are DOS errors, not NT status codes. */
28
29 #include "includes.h"
30
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33         ((info)?ndr_size_##fn(info, level, ic, 0):0)
34
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36         ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
37
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39         ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
40
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
42
43
44 extern userdom_struct current_user_info;
45
46 #undef DBGC_CLASS
47 #define DBGC_CLASS DBGC_RPC_SRV
48
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
51 #endif
52
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
55
56 static Printer_entry *printers_list;
57
58 typedef struct _counter_printer_0 {
59         struct _counter_printer_0 *next;
60         struct _counter_printer_0 *prev;
61
62         int snum;
63         uint32_t counter;
64 } counter_printer_0;
65
66 static counter_printer_0 *counter_list;
67
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
70
71
72 /* in printing/nt_printing.c */
73
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
75
76 /* API table for Xcv Monitor functions */
77
78 struct xcv_api_table {
79         const char *name;
80         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
81 };
82
83 /********************************************************************
84  * Canonicalize servername.
85  ********************************************************************/
86
87 static const char *canon_servername(const char *servername)
88 {
89         const char *pservername = servername;
90         while (*pservername == '\\') {
91                 pservername++;
92         }
93         return pservername;
94 }
95
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
98 {
99         switch (v) {
100         case LPQ_QUEUED:
101                 return 0;
102         case LPQ_PAUSED:
103                 return JOB_STATUS_PAUSED;
104         case LPQ_SPOOLING:
105                 return JOB_STATUS_SPOOLING;
106         case LPQ_PRINTING:
107                 return JOB_STATUS_PRINTING;
108         case LPQ_ERROR:
109                 return JOB_STATUS_ERROR;
110         case LPQ_DELETING:
111                 return JOB_STATUS_DELETING;
112         case LPQ_OFFLINE:
113                 return JOB_STATUS_OFFLINE;
114         case LPQ_PAPEROUT:
115                 return JOB_STATUS_PAPEROUT;
116         case LPQ_PRINTED:
117                 return JOB_STATUS_PRINTED;
118         case LPQ_DELETED:
119                 return JOB_STATUS_DELETED;
120         case LPQ_BLOCKED:
121                 return JOB_STATUS_BLOCKED_DEVQ;
122         case LPQ_USER_INTERVENTION:
123                 return JOB_STATUS_USER_INTERVENTION;
124         }
125         return 0;
126 }
127
128 static int nt_printq_status(int v)
129 {
130         switch (v) {
131         case LPQ_PAUSED:
132                 return PRINTER_STATUS_PAUSED;
133         case LPQ_QUEUED:
134         case LPQ_SPOOLING:
135         case LPQ_PRINTING:
136                 return 0;
137         }
138         return 0;
139 }
140
141 /***************************************************************************
142  Disconnect from the client
143 ****************************************************************************/
144
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
146 {
147         WERROR result;
148         NTSTATUS status;
149
150         /*
151          * Tell the specific printing tdb we no longer want messages for this printer
152          * by deregistering our PID.
153          */
154
155         if (!print_notify_deregister_pid(snum))
156                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
157
158         /* weird if the test succeds !!! */
159         if (smb_connections==0) {
160                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161                 return;
162         }
163
164         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
165                                                   handle,
166                                                   &result);
167         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169                         win_errstr(result)));
170
171         /* if it's the last connection, deconnect the IPC$ share */
172         if (smb_connections==1) {
173
174                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
176
177                 messaging_deregister(smbd_messaging_context(),
178                                      MSG_PRINTER_NOTIFY2, NULL);
179
180                 /* Tell the connections db we're no longer interested in
181                  * printer notify messages. */
182
183                 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
184         }
185
186         smb_connections--;
187 }
188
189 /****************************************************************************
190  Functions to free a printer entry datastruct.
191 ****************************************************************************/
192
193 static int printer_entry_destructor(Printer_entry *Printer)
194 {
195         if (Printer->notify.client_connected == true) {
196                 int snum = -1;
197
198                 if ( Printer->printer_type == SPLHND_SERVER) {
199                         snum = -1;
200                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201                 } else if (Printer->printer_type == SPLHND_PRINTER) {
202                         snum = print_queue_snum(Printer->sharename);
203                         if (snum != -1)
204                                 srv_spoolss_replycloseprinter(snum,
205                                                 &Printer->notify.client_hnd);
206                 }
207         }
208
209         Printer->notify.flags=0;
210         Printer->notify.options=0;
211         Printer->notify.localmachine[0]='\0';
212         Printer->notify.printerlocal=0;
213         TALLOC_FREE(Printer->notify.option);
214         Printer->notify.client_connected = false;
215
216         free_nt_devicemode( &Printer->nt_devmode );
217         free_a_printer( &Printer->printer_info, 2 );
218
219         /* Remove from the internal list. */
220         DLIST_REMOVE(printers_list, Printer);
221         return 0;
222 }
223
224 /****************************************************************************
225   find printer index by handle
226 ****************************************************************************/
227
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229                                                 struct policy_handle *hnd)
230 {
231         Printer_entry *find_printer = NULL;
232
233         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
235                 return NULL;
236         }
237
238         return find_printer;
239 }
240
241 /****************************************************************************
242  Close printer index by handle.
243 ****************************************************************************/
244
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
246 {
247         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
248
249         if (!Printer) {
250                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
251                         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, struct policy_handle *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",
330                         OUR_HANDLE(hnd)));
331                 return WERR_BADFID;
332         }
333
334         /*
335          * It turns out that Windows allows delete printer on a handle
336          * opened by an admin user, then used on a pipe handle created
337          * by an anonymous user..... but they're working on security.... riiight !
338          * JRA.
339          */
340
341         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
342                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
343                 return WERR_ACCESS_DENIED;
344         }
345
346         /* this does not need a become root since the access check has been
347            done on the handle already */
348
349         if (del_a_printer( Printer->sharename ) != 0) {
350                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
351                 return WERR_BADFID;
352         }
353
354         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
355                                    Printer->sharename );
356 }
357
358 /****************************************************************************
359  Return the snum of a printer corresponding to an handle.
360 ****************************************************************************/
361
362 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
363                              int *number, struct share_params **params)
364 {
365         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
366
367         if (!Printer) {
368                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
369                         OUR_HANDLE(hnd)));
370                 return false;
371         }
372
373         switch (Printer->printer_type) {
374                 case SPLHND_PRINTER:
375                         DEBUG(4,("short name:%s\n", Printer->sharename));
376                         *number = print_queue_snum(Printer->sharename);
377                         return (*number != -1);
378                 case SPLHND_SERVER:
379                         return false;
380                 default:
381                         return false;
382         }
383 }
384
385 /****************************************************************************
386  Set printer handle type.
387  Check if it's \\server or \\server\printer
388 ****************************************************************************/
389
390 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
391 {
392         DEBUG(3,("Setting printer type=%s\n", handlename));
393
394         if ( strlen(handlename) < 3 ) {
395                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
396                 return false;
397         }
398
399         /* it's a print server */
400         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
401                 DEBUGADD(4,("Printer is a print server\n"));
402                 Printer->printer_type = SPLHND_SERVER;
403         }
404         /* it's a printer (set_printer_hnd_name() will handle port monitors */
405         else {
406                 DEBUGADD(4,("Printer is a printer\n"));
407                 Printer->printer_type = SPLHND_PRINTER;
408         }
409
410         return true;
411 }
412
413 /****************************************************************************
414  Set printer handle name..  Accept names like \\server, \\server\printer,
415  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
416  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
417  XcvDataPort() interface.
418 ****************************************************************************/
419
420 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
421 {
422         int snum;
423         int n_services=lp_numservices();
424         char *aprinter, *printername;
425         const char *servername;
426         fstring sname;
427         bool found = false;
428         NT_PRINTER_INFO_LEVEL *printer = NULL;
429         WERROR result;
430
431         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
432                 (unsigned long)strlen(handlename)));
433
434         aprinter = CONST_DISCARD(char *, handlename);
435         if ( *handlename == '\\' ) {
436                 servername = canon_servername(handlename);
437                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
438                         *aprinter = '\0';
439                         aprinter++;
440                 }
441         } else {
442                 servername = global_myname();
443         }
444
445         /* save the servername to fill in replies on this handle */
446
447         if ( !is_myname_or_ipaddr( servername ) )
448                 return false;
449
450         fstrcpy( Printer->servername, servername );
451
452         if ( Printer->printer_type == SPLHND_SERVER )
453                 return true;
454
455         if ( Printer->printer_type != SPLHND_PRINTER )
456                 return false;
457
458         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
459
460         /* check for the Port Monitor Interface */
461
462         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
463                 Printer->printer_type = SPLHND_PORTMON_TCP;
464                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
465                 found = true;
466         }
467         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
468                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
469                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
470                 found = true;
471         }
472
473         /* Search all sharenames first as this is easier than pulling
474            the printer_info_2 off of disk. Don't use find_service() since
475            that calls out to map_username() */
476
477         /* do another loop to look for printernames */
478
479         for (snum=0; !found && snum<n_services; snum++) {
480
481                 /* no point going on if this is not a printer */
482
483                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
484                         continue;
485
486                 fstrcpy(sname, lp_servicename(snum));
487                 if ( strequal( aprinter, sname ) ) {
488                         found = true;
489                         break;
490                 }
491
492                 /* no point looking up the printer object if
493                    we aren't allowing printername != sharename */
494
495                 if ( lp_force_printername(snum) )
496                         continue;
497
498                 fstrcpy(sname, lp_servicename(snum));
499
500                 printer = NULL;
501
502                 /* This call doesn't fill in the location or comment from
503                  * a CUPS server for efficiency with large numbers of printers.
504                  * JRA.
505                  */
506
507                 result = get_a_printer_search( NULL, &printer, 2, sname );
508                 if ( !W_ERROR_IS_OK(result) ) {
509                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
510                                 sname, win_errstr(result)));
511                         continue;
512                 }
513
514                 /* printername is always returned as \\server\printername */
515                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
516                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
517                                 printer->info_2->printername));
518                         free_a_printer( &printer, 2);
519                         continue;
520                 }
521
522                 printername++;
523
524                 if ( strequal(printername, aprinter) ) {
525                         free_a_printer( &printer, 2);
526                         found = true;
527                         break;
528                 }
529
530                 DEBUGADD(10, ("printername: %s\n", printername));
531
532                 free_a_printer( &printer, 2);
533         }
534
535         free_a_printer( &printer, 2);
536
537         if ( !found ) {
538                 DEBUGADD(4,("Printer not found\n"));
539                 return false;
540         }
541
542         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
543
544         fstrcpy(Printer->sharename, sname);
545
546         return true;
547 }
548
549 /****************************************************************************
550  Find first available printer slot. creates a printer handle for you.
551  ****************************************************************************/
552
553 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
554                              const char *name, uint32_t access_granted)
555 {
556         Printer_entry *new_printer;
557
558         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
559
560         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
561         if (new_printer == NULL) {
562                 return false;
563         }
564         talloc_set_destructor(new_printer, printer_entry_destructor);
565
566         if (!create_policy_hnd(p, hnd, new_printer)) {
567                 TALLOC_FREE(new_printer);
568                 return false;
569         }
570
571         /* Add to the internal list. */
572         DLIST_ADD(printers_list, new_printer);
573
574         new_printer->notify.option=NULL;
575
576         if (!set_printer_hnd_printertype(new_printer, name)) {
577                 close_printer_handle(p, hnd);
578                 return false;
579         }
580
581         if (!set_printer_hnd_name(new_printer, name)) {
582                 close_printer_handle(p, hnd);
583                 return false;
584         }
585
586         new_printer->access_granted = access_granted;
587
588         DEBUG(5, ("%d printer handles active\n",
589                   (int)num_pipe_handles(p->pipe_handles)));
590
591         return true;
592 }
593
594 /***************************************************************************
595  check to see if the client motify handle is monitoring the notification
596  given by (notify_type, notify_field).
597  **************************************************************************/
598
599 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
600                                       uint16_t notify_field)
601 {
602         return true;
603 }
604
605 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
606                                 uint16_t notify_field)
607 {
608         struct spoolss_NotifyOption *option = p->notify.option;
609         uint32_t i, j;
610
611         /*
612          * Flags should always be zero when the change notify
613          * is registered by the client's spooler.  A user Win32 app
614          * might use the flags though instead of the NOTIFY_OPTION_INFO
615          * --jerry
616          */
617
618         if (!option) {
619                 return false;
620         }
621
622         if (p->notify.flags)
623                 return is_monitoring_event_flags(
624                         p->notify.flags, notify_type, notify_field);
625
626         for (i = 0; i < option->count; i++) {
627
628                 /* Check match for notify_type */
629
630                 if (option->types[i].type != notify_type)
631                         continue;
632
633                 /* Check match for field */
634
635                 for (j = 0; j < option->types[i].count; j++) {
636                         if (option->types[i].fields[j].field == notify_field) {
637                                 return true;
638                         }
639                 }
640         }
641
642         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
643                    p->servername, p->sharename, notify_type, notify_field));
644
645         return false;
646 }
647
648 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
649         _data->data.integer[0] = _integer; \
650         _data->data.integer[1] = 0;
651
652
653 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
654         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
655         if (!_data->data.string.string) {\
656                 _data->data.string.size = 0; \
657         } \
658         _data->data.string.size = strlen_m_term(_p) * 2;
659
660 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
661         _data->data.devmode.devmode = _devmode;
662
663 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
664         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
665         if (!_data->data.sd.sd) { \
666                 _data->data.sd.sd_size = 0; \
667         } \
668         _data->data.sd.sd_size = _size;
669
670 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
671                                    struct tm *t,
672                                    const char **pp,
673                                    uint32_t *plen)
674 {
675         struct spoolss_Time st;
676         uint32_t len = 16;
677         char *p;
678
679         if (!init_systemtime(&st, t)) {
680                 return;
681         }
682
683         p = talloc_array(mem_ctx, char, len);
684         if (!p) {
685                 return;
686         }
687
688         /*
689          * Systemtime must be linearized as a set of UINT16's.
690          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
691          */
692
693         SSVAL(p, 0, st.year);
694         SSVAL(p, 2, st.month);
695         SSVAL(p, 4, st.day_of_week);
696         SSVAL(p, 6, st.day);
697         SSVAL(p, 8, st.hour);
698         SSVAL(p, 10, st.minute);
699         SSVAL(p, 12, st.second);
700         SSVAL(p, 14, st.millisecond);
701
702         *pp = p;
703         *plen = len;
704 }
705
706 /* Convert a notification message to a struct spoolss_Notify */
707
708 static void notify_one_value(struct spoolss_notify_msg *msg,
709                              struct spoolss_Notify *data,
710                              TALLOC_CTX *mem_ctx)
711 {
712         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
713 }
714
715 static void notify_string(struct spoolss_notify_msg *msg,
716                           struct spoolss_Notify *data,
717                           TALLOC_CTX *mem_ctx)
718 {
719         /* The length of the message includes the trailing \0 */
720
721         data->data.string.size = msg->len * 2;
722         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
723         if (!data->data.string.string) {
724                 data->data.string.size = 0;
725                 return;
726         }
727 }
728
729 static void notify_system_time(struct spoolss_notify_msg *msg,
730                                struct spoolss_Notify *data,
731                                TALLOC_CTX *mem_ctx)
732 {
733         data->data.string.string = NULL;
734         data->data.string.size = 0;
735
736         if (msg->len != sizeof(time_t)) {
737                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
738                           msg->len));
739                 return;
740         }
741
742         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
743                                &data->data.string.string,
744                                &data->data.string.size);
745 }
746
747 struct notify2_message_table {
748         const char *name;
749         void (*fn)(struct spoolss_notify_msg *msg,
750                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
751 };
752
753 static struct notify2_message_table printer_notify_table[] = {
754         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
755         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
756         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
757         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
758         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
759         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
760         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
761         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
762         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
763         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
764         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
765         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
766         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
767         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
768         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
769         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
770         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
771         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
772         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
773 };
774
775 static struct notify2_message_table job_notify_table[] = {
776         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
777         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
778         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
779         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
780         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
781         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
782         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
783         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
784         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
785         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
786         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
787         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
788         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
789         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
790         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
791         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
792         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
793         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
794         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
795         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
796         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
797         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
798         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
799         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
800 };
801
802
803 /***********************************************************************
804  Allocate talloc context for container object
805  **********************************************************************/
806
807 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
808 {
809         if ( !ctr )
810                 return;
811
812         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
813
814         return;
815 }
816
817 /***********************************************************************
818  release all allocated memory and zero out structure
819  **********************************************************************/
820
821 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
822 {
823         if ( !ctr )
824                 return;
825
826         if ( ctr->ctx )
827                 talloc_destroy(ctr->ctx);
828
829         ZERO_STRUCTP(ctr);
830
831         return;
832 }
833
834 /***********************************************************************
835  **********************************************************************/
836
837 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 {
839         if ( !ctr )
840                 return NULL;
841
842         return ctr->ctx;
843 }
844
845 /***********************************************************************
846  **********************************************************************/
847
848 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
849 {
850         if ( !ctr || !ctr->msg_groups )
851                 return NULL;
852
853         if ( idx >= ctr->num_groups )
854                 return NULL;
855
856         return &ctr->msg_groups[idx];
857
858 }
859
860 /***********************************************************************
861  How many groups of change messages do we have ?
862  **********************************************************************/
863
864 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
865 {
866         if ( !ctr )
867                 return 0;
868
869         return ctr->num_groups;
870 }
871
872 /***********************************************************************
873  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
874  **********************************************************************/
875
876 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
877 {
878         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
879         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
880         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
881         int                             i, new_slot;
882
883         if ( !ctr || !msg )
884                 return 0;
885
886         /* loop over all groups looking for a matching printer name */
887
888         for ( i=0; i<ctr->num_groups; i++ ) {
889                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
890                         break;
891         }
892
893         /* add a new group? */
894
895         if ( i == ctr->num_groups ) {
896                 ctr->num_groups++;
897
898                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
899                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
900                         return 0;
901                 }
902                 ctr->msg_groups = groups;
903
904                 /* clear the new entry and set the printer name */
905
906                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
907                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
908         }
909
910         /* add the change messages; 'i' is the correct index now regardless */
911
912         msg_grp = &ctr->msg_groups[i];
913
914         msg_grp->num_msgs++;
915
916         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
917                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
918                 return 0;
919         }
920         msg_grp->msgs = msg_list;
921
922         new_slot = msg_grp->num_msgs-1;
923         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
924
925         /* need to allocate own copy of data */
926
927         if ( msg->len != 0 )
928                 msg_grp->msgs[new_slot].notify.data = (char *)
929                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
930
931         return ctr->num_groups;
932 }
933
934 /***********************************************************************
935  Send a change notication message on all handles which have a call
936  back registered
937  **********************************************************************/
938
939 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
940 {
941         Printer_entry            *p;
942         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
943         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
944         SPOOLSS_NOTIFY_MSG       *messages;
945         int                      sending_msg_count;
946
947         if ( !msg_group ) {
948                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
949                 return;
950         }
951
952         messages = msg_group->msgs;
953
954         if ( !messages ) {
955                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
956                 return;
957         }
958
959         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
960
961         /* loop over all printers */
962
963         for (p = printers_list; p; p = p->next) {
964                 struct spoolss_Notify *notifies;
965                 uint32_t count = 0;
966                 uint32_t id;
967                 int     i;
968
969                 /* Is there notification on this handle? */
970
971                 if ( !p->notify.client_connected )
972                         continue;
973
974                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
975
976                 /* For this printer?  Print servers always receive
977                    notifications. */
978
979                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
980                     ( !strequal(msg_group->printername, p->sharename) ) )
981                         continue;
982
983                 DEBUG(10,("Our printer\n"));
984
985                 /* allocate the max entries possible */
986
987                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
988                 if (!notifies) {
989                         return;
990                 }
991
992                 /* build the array of change notifications */
993
994                 sending_msg_count = 0;
995
996                 for ( i=0; i<msg_group->num_msgs; i++ ) {
997                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
998
999                         /* Are we monitoring this event? */
1000
1001                         if (!is_monitoring_event(p, msg->type, msg->field))
1002                                 continue;
1003
1004                         sending_msg_count++;
1005
1006
1007                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1008                                 msg->type, msg->field, p->sharename));
1009
1010                         /*
1011                          * if the is a printer notification handle and not a job notification
1012                          * type, then set the id to 0.  Other wise just use what was specified
1013                          * in the message.
1014                          *
1015                          * When registering change notification on a print server handle
1016                          * we always need to send back the id (snum) matching the printer
1017                          * for which the change took place.  For change notify registered
1018                          * on a printer handle, this does not matter and the id should be 0.
1019                          *
1020                          * --jerry
1021                          */
1022
1023                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1024                                 id = 0;
1025                         else
1026                                 id = msg->id;
1027
1028
1029                         /* Convert unix jobid to smb jobid */
1030
1031                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1032                                 id = sysjob_to_jobid(msg->id);
1033
1034                                 if (id == -1) {
1035                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1036                                         goto done;
1037                                 }
1038                         }
1039
1040                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1041
1042                         switch(msg->type) {
1043                         case PRINTER_NOTIFY_TYPE:
1044                                 if ( printer_notify_table[msg->field].fn )
1045                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1046                                 break;
1047
1048                         case JOB_NOTIFY_TYPE:
1049                                 if ( job_notify_table[msg->field].fn )
1050                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1051                                 break;
1052
1053                         default:
1054                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1055                                 goto done;
1056                         }
1057
1058                         count++;
1059                 }
1060
1061                 if ( sending_msg_count ) {
1062                         NTSTATUS status;
1063                         WERROR werr;
1064                         union spoolss_ReplyPrinterInfo info;
1065                         struct spoolss_NotifyInfo info0;
1066                         uint32_t reply_result;
1067
1068                         info0.version   = 0x2;
1069                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1070                         info0.count     = count;
1071                         info0.notifies  = notifies;
1072
1073                         info.info0 = &info0;
1074
1075                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1076                                                                      &p->notify.client_hnd,
1077                                                                      p->notify.change, /* color */
1078                                                                      p->notify.flags,
1079                                                                      &reply_result,
1080                                                                      0, /* reply_type, must be 0 */
1081                                                                      info,
1082                                                                      &werr);
1083                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1084                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1085                                         notify_cli_pipe->srv_name_slash,
1086                                         win_errstr(werr)));
1087                         }
1088                         switch (reply_result) {
1089                                 case 0:
1090                                         break;
1091                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1092                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1093                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1094                                         break;
1095                                 default:
1096                                         break;
1097                         }
1098                 }
1099         }
1100
1101 done:
1102         DEBUG(8,("send_notify2_changes: Exit...\n"));
1103         return;
1104 }
1105
1106 /***********************************************************************
1107  **********************************************************************/
1108
1109 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1110 {
1111
1112         uint32_t tv_sec, tv_usec;
1113         size_t offset = 0;
1114
1115         /* Unpack message */
1116
1117         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1118                              msg->printer);
1119
1120         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1121                                 &tv_sec, &tv_usec,
1122                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1123
1124         if (msg->len == 0)
1125                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1126                            &msg->notify.value[0], &msg->notify.value[1]);
1127         else
1128                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1129                            &msg->len, &msg->notify.data);
1130
1131         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1132                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1133
1134         tv->tv_sec = tv_sec;
1135         tv->tv_usec = tv_usec;
1136
1137         if (msg->len == 0)
1138                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1139                           msg->notify.value[1]));
1140         else
1141                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1142
1143         return true;
1144 }
1145
1146 /********************************************************************
1147  Receive a notify2 message list
1148  ********************************************************************/
1149
1150 static void receive_notify2_message_list(struct messaging_context *msg,
1151                                          void *private_data,
1152                                          uint32_t msg_type,
1153                                          struct server_id server_id,
1154                                          DATA_BLOB *data)
1155 {
1156         size_t                  msg_count, i;
1157         char                    *buf = (char *)data->data;
1158         char                    *msg_ptr;
1159         size_t                  msg_len;
1160         SPOOLSS_NOTIFY_MSG      notify;
1161         SPOOLSS_NOTIFY_MSG_CTR  messages;
1162         int                     num_groups;
1163
1164         if (data->length < 4) {
1165                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1166                 return;
1167         }
1168
1169         msg_count = IVAL(buf, 0);
1170         msg_ptr = buf + 4;
1171
1172         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1173
1174         if (msg_count == 0) {
1175                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1176                 return;
1177         }
1178
1179         /* initialize the container */
1180
1181         ZERO_STRUCT( messages );
1182         notify_msg_ctr_init( &messages );
1183
1184         /*
1185          * build message groups for each printer identified
1186          * in a change_notify msg.  Remember that a PCN message
1187          * includes the handle returned for the srv_spoolss_replyopenprinter()
1188          * call.  Therefore messages are grouped according to printer handle.
1189          */
1190
1191         for ( i=0; i<msg_count; i++ ) {
1192                 struct timeval msg_tv;
1193
1194                 if (msg_ptr + 4 - buf > data->length) {
1195                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1196                         return;
1197                 }
1198
1199                 msg_len = IVAL(msg_ptr,0);
1200                 msg_ptr += 4;
1201
1202                 if (msg_ptr + msg_len - buf > data->length) {
1203                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1204                         return;
1205                 }
1206
1207                 /* unpack messages */
1208
1209                 ZERO_STRUCT( notify );
1210                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1211                 msg_ptr += msg_len;
1212
1213                 /* add to correct list in container */
1214
1215                 notify_msg_ctr_addmsg( &messages, &notify );
1216
1217                 /* free memory that might have been allocated by notify2_unpack_msg() */
1218
1219                 if ( notify.len != 0 )
1220                         SAFE_FREE( notify.notify.data );
1221         }
1222
1223         /* process each group of messages */
1224
1225         num_groups = notify_msg_ctr_numgroups( &messages );
1226         for ( i=0; i<num_groups; i++ )
1227                 send_notify2_changes( &messages, i );
1228
1229
1230         /* cleanup */
1231
1232         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1233                 (uint32_t)msg_count ));
1234
1235         notify_msg_ctr_destroy( &messages );
1236
1237         return;
1238 }
1239
1240 /********************************************************************
1241  Send a message to ourself about new driver being installed
1242  so we can upgrade the information for each printer bound to this
1243  driver
1244  ********************************************************************/
1245
1246 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1247 {
1248         int len = strlen(drivername);
1249
1250         if (!len)
1251                 return false;
1252
1253         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1254                 drivername));
1255
1256         messaging_send_buf(smbd_messaging_context(), procid_self(),
1257                            MSG_PRINTER_DRVUPGRADE,
1258                            (uint8_t *)drivername, len+1);
1259
1260         return true;
1261 }
1262
1263 /**********************************************************************
1264  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1265  over all printers, upgrading ones as necessary
1266  **********************************************************************/
1267
1268 void do_drv_upgrade_printer(struct messaging_context *msg,
1269                             void *private_data,
1270                             uint32_t msg_type,
1271                             struct server_id server_id,
1272                             DATA_BLOB *data)
1273 {
1274         fstring drivername;
1275         int snum;
1276         int n_services = lp_numservices();
1277         size_t len;
1278
1279         len = MIN(data->length,sizeof(drivername)-1);
1280         strncpy(drivername, (const char *)data->data, len);
1281
1282         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1283
1284         /* Iterate the printer list */
1285
1286         for (snum=0; snum<n_services; snum++)
1287         {
1288                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1289                 {
1290                         WERROR result;
1291                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1292
1293                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1294                         if (!W_ERROR_IS_OK(result))
1295                                 continue;
1296
1297                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1298                         {
1299                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1300
1301                                 /* all we care about currently is the change_id */
1302
1303                                 result = mod_a_printer(printer, 2);
1304                                 if (!W_ERROR_IS_OK(result)) {
1305                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1306                                                 win_errstr(result)));
1307                                 }
1308                         }
1309
1310                         free_a_printer(&printer, 2);
1311                 }
1312         }
1313
1314         /* all done */
1315 }
1316
1317 /********************************************************************
1318  Update the cache for all printq's with a registered client
1319  connection
1320  ********************************************************************/
1321
1322 void update_monitored_printq_cache( void )
1323 {
1324         Printer_entry *printer = printers_list;
1325         int snum;
1326
1327         /* loop through all printers and update the cache where
1328            client_connected == true */
1329         while ( printer )
1330         {
1331                 if ( (printer->printer_type == SPLHND_PRINTER)
1332                         && printer->notify.client_connected )
1333                 {
1334                         snum = print_queue_snum(printer->sharename);
1335                         print_queue_status( snum, NULL, NULL );
1336                 }
1337
1338                 printer = printer->next;
1339         }
1340
1341         return;
1342 }
1343 /********************************************************************
1344  Send a message to ourself about new driver being installed
1345  so we can upgrade the information for each printer bound to this
1346  driver
1347  ********************************************************************/
1348
1349 static bool srv_spoolss_reset_printerdata(char* drivername)
1350 {
1351         int len = strlen(drivername);
1352
1353         if (!len)
1354                 return false;
1355
1356         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1357                 drivername));
1358
1359         messaging_send_buf(smbd_messaging_context(), procid_self(),
1360                            MSG_PRINTERDATA_INIT_RESET,
1361                            (uint8_t *)drivername, len+1);
1362
1363         return true;
1364 }
1365
1366 /**********************************************************************
1367  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1368  over all printers, resetting printer data as neessary
1369  **********************************************************************/
1370
1371 void reset_all_printerdata(struct messaging_context *msg,
1372                            void *private_data,
1373                            uint32_t msg_type,
1374                            struct server_id server_id,
1375                            DATA_BLOB *data)
1376 {
1377         fstring drivername;
1378         int snum;
1379         int n_services = lp_numservices();
1380         size_t len;
1381
1382         len = MIN( data->length, sizeof(drivername)-1 );
1383         strncpy( drivername, (const char *)data->data, len );
1384
1385         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1386
1387         /* Iterate the printer list */
1388
1389         for ( snum=0; snum<n_services; snum++ )
1390         {
1391                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1392                 {
1393                         WERROR result;
1394                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1395
1396                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1397                         if ( !W_ERROR_IS_OK(result) )
1398                                 continue;
1399
1400                         /*
1401                          * if the printer is bound to the driver,
1402                          * then reset to the new driver initdata
1403                          */
1404
1405                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1406                         {
1407                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1408
1409                                 if ( !set_driver_init(printer, 2) ) {
1410                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1411                                                 printer->info_2->printername, printer->info_2->drivername));
1412                                 }
1413
1414                                 result = mod_a_printer( printer, 2 );
1415                                 if ( !W_ERROR_IS_OK(result) ) {
1416                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1417                                                 get_dos_error_msg(result)));
1418                                 }
1419                         }
1420
1421                         free_a_printer( &printer, 2 );
1422                 }
1423         }
1424
1425         /* all done */
1426
1427         return;
1428 }
1429
1430 /****************************************************************
1431  _spoolss_OpenPrinter
1432 ****************************************************************/
1433
1434 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1435                             struct spoolss_OpenPrinter *r)
1436 {
1437         struct spoolss_OpenPrinterEx e;
1438         WERROR werr;
1439
1440         ZERO_STRUCT(e.in.userlevel);
1441
1442         e.in.printername        = r->in.printername;
1443         e.in.datatype           = r->in.datatype;
1444         e.in.devmode_ctr        = r->in.devmode_ctr;
1445         e.in.access_mask        = r->in.access_mask;
1446         e.in.level              = 0;
1447
1448         e.out.handle            = r->out.handle;
1449
1450         werr = _spoolss_OpenPrinterEx(p, &e);
1451
1452         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1453                 /* OpenPrinterEx returns this for a bad
1454                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1455                  * instead.
1456                  */
1457                 werr = WERR_INVALID_PRINTER_NAME;
1458         }
1459
1460         return werr;
1461 }
1462
1463 /********************************************************************
1464  ********************************************************************/
1465
1466 bool convert_devicemode(const char *printername,
1467                         const struct spoolss_DeviceMode *devmode,
1468                         NT_DEVICEMODE **pp_nt_devmode)
1469 {
1470         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1471
1472         /*
1473          * Ensure nt_devmode is a valid pointer
1474          * as we will be overwriting it.
1475          */
1476
1477         if (nt_devmode == NULL) {
1478                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1479                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1480                         return false;
1481         }
1482
1483         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1484         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1485
1486         nt_devmode->specversion         = devmode->specversion;
1487         nt_devmode->driverversion       = devmode->driverversion;
1488         nt_devmode->size                = devmode->size;
1489         nt_devmode->fields              = devmode->fields;
1490         nt_devmode->orientation         = devmode->orientation;
1491         nt_devmode->papersize           = devmode->papersize;
1492         nt_devmode->paperlength         = devmode->paperlength;
1493         nt_devmode->paperwidth          = devmode->paperwidth;
1494         nt_devmode->scale               = devmode->scale;
1495         nt_devmode->copies              = devmode->copies;
1496         nt_devmode->defaultsource       = devmode->defaultsource;
1497         nt_devmode->printquality        = devmode->printquality;
1498         nt_devmode->color               = devmode->color;
1499         nt_devmode->duplex              = devmode->duplex;
1500         nt_devmode->yresolution         = devmode->yresolution;
1501         nt_devmode->ttoption            = devmode->ttoption;
1502         nt_devmode->collate             = devmode->collate;
1503
1504         nt_devmode->logpixels           = devmode->logpixels;
1505         nt_devmode->bitsperpel          = devmode->bitsperpel;
1506         nt_devmode->pelswidth           = devmode->pelswidth;
1507         nt_devmode->pelsheight          = devmode->pelsheight;
1508         nt_devmode->displayflags        = devmode->displayflags;
1509         nt_devmode->displayfrequency    = devmode->displayfrequency;
1510         nt_devmode->icmmethod           = devmode->icmmethod;
1511         nt_devmode->icmintent           = devmode->icmintent;
1512         nt_devmode->mediatype           = devmode->mediatype;
1513         nt_devmode->dithertype          = devmode->dithertype;
1514         nt_devmode->reserved1           = devmode->reserved1;
1515         nt_devmode->reserved2           = devmode->reserved2;
1516         nt_devmode->panningwidth        = devmode->panningwidth;
1517         nt_devmode->panningheight       = devmode->panningheight;
1518
1519         /*
1520          * Only change private and driverextra if the incoming devmode
1521          * has a new one. JRA.
1522          */
1523
1524         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1525                 SAFE_FREE(nt_devmode->nt_dev_private);
1526                 nt_devmode->driverextra = devmode->__driverextra_length;
1527                 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1528                         return false;
1529                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1530         }
1531
1532         *pp_nt_devmode = nt_devmode;
1533
1534         return true;
1535 }
1536
1537 /****************************************************************
1538  _spoolss_OpenPrinterEx
1539 ****************************************************************/
1540
1541 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1542                               struct spoolss_OpenPrinterEx *r)
1543 {
1544         int snum;
1545         Printer_entry *Printer=NULL;
1546
1547         if (!r->in.printername) {
1548                 return WERR_INVALID_PARAM;
1549         }
1550
1551         /* some sanity check because you can open a printer or a print server */
1552         /* aka: \\server\printer or \\server */
1553
1554         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1555
1556         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1557                 ZERO_STRUCTP(r->out.handle);
1558                 return WERR_INVALID_PARAM;
1559         }
1560
1561         Printer = find_printer_index_by_hnd(p, r->out.handle);
1562         if ( !Printer ) {
1563                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1564                         "handle we created for printer %s\n", r->in.printername));
1565                 close_printer_handle(p, r->out.handle);
1566                 ZERO_STRUCTP(r->out.handle);
1567                 return WERR_INVALID_PARAM;
1568         }
1569
1570         /*
1571          * First case: the user is opening the print server:
1572          *
1573          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1574          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1575          *
1576          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1577          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1578          * or if the user is listed in the smb.conf printer admin parameter.
1579          *
1580          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1581          * client view printer folder, but does not show the MSAPW.
1582          *
1583          * Note: this test needs code to check access rights here too. Jeremy
1584          * could you look at this?
1585          *
1586          * Second case: the user is opening a printer:
1587          * NT doesn't let us connect to a printer if the connecting user
1588          * doesn't have print permission.
1589          *
1590          * Third case: user is opening a Port Monitor
1591          * access checks same as opening a handle to the print server.
1592          */
1593
1594         switch (Printer->printer_type )
1595         {
1596         case SPLHND_SERVER:
1597         case SPLHND_PORTMON_TCP:
1598         case SPLHND_PORTMON_LOCAL:
1599                 /* Printserver handles use global struct... */
1600
1601                 snum = -1;
1602
1603                 /* Map standard access rights to object specific access rights */
1604
1605                 se_map_standard(&r->in.access_mask,
1606                                 &printserver_std_mapping);
1607
1608                 /* Deny any object specific bits that don't apply to print
1609                    servers (i.e printer and job specific bits) */
1610
1611                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1612
1613                 if (r->in.access_mask &
1614                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1615                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1616                         close_printer_handle(p, r->out.handle);
1617                         ZERO_STRUCTP(r->out.handle);
1618                         return WERR_ACCESS_DENIED;
1619                 }
1620
1621                 /* Allow admin access */
1622
1623                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1624                 {
1625                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1626
1627                         if (!lp_ms_add_printer_wizard()) {
1628                                 close_printer_handle(p, r->out.handle);
1629                                 ZERO_STRUCTP(r->out.handle);
1630                                 return WERR_ACCESS_DENIED;
1631                         }
1632
1633                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1634                            and not a printer admin, then fail */
1635
1636                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1637                             !user_has_privileges(p->server_info->ptok,
1638                                                  &se_printop ) &&
1639                             !token_contains_name_in_list(
1640                                     uidtoname(p->server_info->utok.uid),
1641                                     NULL, NULL,
1642                                     p->server_info->ptok,
1643                                     lp_printer_admin(snum))) {
1644                                 close_printer_handle(p, r->out.handle);
1645                                 ZERO_STRUCTP(r->out.handle);
1646                                 return WERR_ACCESS_DENIED;
1647                         }
1648
1649                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1650                 }
1651                 else
1652                 {
1653                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1654                 }
1655
1656                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1657                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1658
1659                 /* We fall through to return WERR_OK */
1660                 break;
1661
1662         case SPLHND_PRINTER:
1663                 /* NT doesn't let us connect to a printer if the connecting user
1664                    doesn't have print permission.  */
1665
1666                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1667                         close_printer_handle(p, r->out.handle);
1668                         ZERO_STRUCTP(r->out.handle);
1669                         return WERR_BADFID;
1670                 }
1671
1672                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1673
1674                 /* map an empty access mask to the minimum access mask */
1675                 if (r->in.access_mask == 0x0)
1676                         r->in.access_mask = PRINTER_ACCESS_USE;
1677
1678                 /*
1679                  * If we are not serving the printer driver for this printer,
1680                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1681                  * will keep NT clients happy  --jerry
1682                  */
1683
1684                 if (lp_use_client_driver(snum)
1685                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1686                 {
1687                         r->in.access_mask = PRINTER_ACCESS_USE;
1688                 }
1689
1690                 /* check smb.conf parameters and the the sec_desc */
1691
1692                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1693                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1694                         ZERO_STRUCTP(r->out.handle);
1695                         return WERR_ACCESS_DENIED;
1696                 }
1697
1698                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1699                                    p->server_info->ptok, snum) ||
1700                     !print_access_check(p->server_info, snum,
1701                                         r->in.access_mask)) {
1702                         DEBUG(3, ("access DENIED for printer open\n"));
1703                         close_printer_handle(p, r->out.handle);
1704                         ZERO_STRUCTP(r->out.handle);
1705                         return WERR_ACCESS_DENIED;
1706                 }
1707
1708                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1709                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1710                         close_printer_handle(p, r->out.handle);
1711                         ZERO_STRUCTP(r->out.handle);
1712                         return WERR_ACCESS_DENIED;
1713                 }
1714
1715                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1716                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1717                 else
1718                         r->in.access_mask = PRINTER_ACCESS_USE;
1719
1720                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1721                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1722
1723                 break;
1724
1725         default:
1726                 /* sanity check to prevent programmer error */
1727                 ZERO_STRUCTP(r->out.handle);
1728                 return WERR_BADFID;
1729         }
1730
1731         Printer->access_granted = r->in.access_mask;
1732
1733         /*
1734          * If the client sent a devmode in the OpenPrinter() call, then
1735          * save it here in case we get a job submission on this handle
1736          */
1737
1738          if ((Printer->printer_type != SPLHND_SERVER) &&
1739              r->in.devmode_ctr.devmode) {
1740                 convert_devicemode(Printer->sharename,
1741                                    r->in.devmode_ctr.devmode,
1742                                    &Printer->nt_devmode);
1743          }
1744
1745 #if 0   /* JERRY -- I'm doubtful this is really effective */
1746         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1747            optimization in Windows 2000 clients  --jerry */
1748
1749         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1750                 && (RA_WIN2K == get_remote_arch()) )
1751         {
1752                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1753                 sys_usleep( 500000 );
1754         }
1755 #endif
1756
1757         return WERR_OK;
1758 }
1759
1760 /****************************************************************************
1761 ****************************************************************************/
1762
1763 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1764                                               NT_PRINTER_INFO_LEVEL_2 *d)
1765 {
1766         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1767
1768         if (!r || !d) {
1769                 return false;
1770         }
1771
1772         d->attributes           = r->attributes;
1773         d->priority             = r->priority;
1774         d->default_priority     = r->defaultpriority;
1775         d->starttime            = r->starttime;
1776         d->untiltime            = r->untiltime;
1777         d->status               = r->status;
1778         d->cjobs                = r->cjobs;
1779
1780         fstrcpy(d->servername,  r->servername);
1781         fstrcpy(d->printername, r->printername);
1782         fstrcpy(d->sharename,   r->sharename);
1783         fstrcpy(d->portname,    r->portname);
1784         fstrcpy(d->drivername,  r->drivername);
1785         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1786         fstrcpy(d->location,    r->location);
1787         fstrcpy(d->sepfile,     r->sepfile);
1788         fstrcpy(d->printprocessor, r->printprocessor);
1789         fstrcpy(d->datatype,    r->datatype);
1790         fstrcpy(d->parameters,  r->parameters);
1791
1792         return true;
1793 }
1794
1795 /****************************************************************************
1796 ****************************************************************************/
1797
1798 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1799                                  NT_PRINTER_INFO_LEVEL *printer)
1800 {
1801         bool ret;
1802
1803         switch (info_ctr->level) {
1804         case 2:
1805                 /* allocate memory if needed.  Messy because
1806                    convert_printer_info is used to update an existing
1807                    printer or build a new one */
1808
1809                 if (!printer->info_2) {
1810                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1811                         if (!printer->info_2) {
1812                                 DEBUG(0,("convert_printer_info: "
1813                                         "talloc() failed!\n"));
1814                                 return false;
1815                         }
1816                 }
1817
1818                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1819                                                         printer->info_2);
1820                 printer->info_2->setuptime = time(NULL);
1821                 return ret;
1822         }
1823
1824         return false;
1825 }
1826
1827 /*******************************************************************
1828 ********************************************************************/
1829
1830 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1831 {
1832         int i;
1833
1834         if (!sarray) {
1835                 *farray = NULL;
1836                 return true;
1837         }
1838
1839         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1840         if (!*farray) {
1841                 return false;
1842         }
1843
1844         for (i=0; sarray[i] != NULL; i++) {
1845                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1846                 if (!*farray) {
1847                         return false;
1848                 }
1849                 fstrcpy((*farray)[i], sarray[i]);
1850         }
1851
1852         fstrcpy((*farray)[i], "");
1853
1854         return true;
1855 }
1856
1857 /*******************************************************************
1858 ********************************************************************/
1859
1860 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1861                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1862 {
1863         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1864
1865         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1866
1867         if (*p == NULL) {
1868                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1869                 if (*p == NULL) {
1870                         return false;
1871                 }
1872                 ZERO_STRUCTP(*p);
1873         }
1874
1875         d = *p;
1876
1877         d->cversion =                   r->version;
1878
1879         fstrcpy(d->name,                r->driver_name);
1880         fstrcpy(d->environment,         r->architecture);
1881         fstrcpy(d->driverpath,          r->driver_path);
1882         fstrcpy(d->datafile,            r->data_file);
1883         fstrcpy(d->configfile,          r->config_file);
1884         fstrcpy(d->helpfile,            r->help_file);
1885         fstrcpy(d->monitorname,         r->monitor_name);
1886         fstrcpy(d->defaultdatatype,     r->default_datatype);
1887
1888         DEBUGADD(8,( "version:         %d\n", d->cversion));
1889         DEBUGADD(8,( "name:            %s\n", d->name));
1890         DEBUGADD(8,( "environment:     %s\n", d->environment));
1891         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1892         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1893         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1894         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1895         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1896         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1897
1898         if (r->dependent_files) {
1899                 if (!string_array_to_fstring_array(r->dependent_files->string,
1900                                                    &d->dependentfiles)) {
1901                         SAFE_FREE(*p);
1902                         return false;
1903                 }
1904         }
1905
1906         return true;
1907 }
1908
1909 /*******************************************************************
1910 ********************************************************************/
1911
1912 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1913                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1914 {
1915         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1916
1917         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1918
1919         if (*p == NULL) {
1920                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1921                 if (*p == NULL) {
1922                         return false;
1923                 }
1924                 ZERO_STRUCTP(*p);
1925         }
1926
1927         d = *p;
1928
1929         d->version =                    r->version;
1930
1931         fstrcpy(d->name,                r->driver_name);
1932         fstrcpy(d->environment,         r->architecture);
1933         fstrcpy(d->driverpath,          r->driver_path);
1934         fstrcpy(d->datafile,            r->data_file);
1935         fstrcpy(d->configfile,          r->config_file);
1936         fstrcpy(d->helpfile,            r->help_file);
1937         fstrcpy(d->monitorname,         r->monitor_name);
1938         fstrcpy(d->defaultdatatype,     r->default_datatype);
1939
1940         DEBUGADD(8,( "version:         %d\n", d->version));
1941         DEBUGADD(8,( "name:            %s\n", d->name));
1942         DEBUGADD(8,( "environment:     %s\n", d->environment));
1943         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1944         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1945         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1946         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1947         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1948         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1949
1950         if (r->dependent_files) {
1951                 if (!string_array_to_fstring_array(r->dependent_files->string,
1952                                                    &d->dependentfiles)) {
1953                         goto error;
1954                 }
1955         }
1956
1957         if (r->previous_names) {
1958                 if (!string_array_to_fstring_array(r->previous_names->string,
1959                                                    &d->previousnames)) {
1960                         goto error;
1961                 }
1962         }
1963
1964         return true;
1965
1966  error:
1967         SAFE_FREE(*p);
1968         return false;
1969 }
1970
1971 /********************************************************************
1972  ********************************************************************/
1973
1974 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1975                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1976                                         uint32_t level)
1977 {
1978         switch (level) {
1979         case 3:
1980                 printer->info_3 = NULL;
1981                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1982                         return false;
1983                 }
1984                 break;
1985         case 6:
1986                 printer->info_6 = NULL;
1987                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1988                         return false;
1989                 }
1990                 break;
1991         default:
1992                 return false;
1993         }
1994
1995         return true;
1996 }
1997
1998 /****************************************************************
1999  _spoolss_ClosePrinter
2000 ****************************************************************/
2001
2002 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2003                              struct spoolss_ClosePrinter *r)
2004 {
2005         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2006
2007         if (Printer && Printer->document_started) {
2008                 struct spoolss_EndDocPrinter e;
2009
2010                 e.in.handle = r->in.handle;
2011
2012                 _spoolss_EndDocPrinter(p, &e);
2013         }
2014
2015         if (!close_printer_handle(p, r->in.handle))
2016                 return WERR_BADFID;
2017
2018         /* clear the returned printer handle.  Observed behavior
2019            from Win2k server.  Don't think this really matters.
2020            Previous code just copied the value of the closed
2021            handle.    --jerry */
2022
2023         ZERO_STRUCTP(r->out.handle);
2024
2025         return WERR_OK;
2026 }
2027
2028 /****************************************************************
2029  _spoolss_DeletePrinter
2030 ****************************************************************/
2031
2032 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2033                               struct spoolss_DeletePrinter *r)
2034 {
2035         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2036         WERROR result;
2037
2038         if (Printer && Printer->document_started) {
2039                 struct spoolss_EndDocPrinter e;
2040
2041                 e.in.handle = r->in.handle;
2042
2043                 _spoolss_EndDocPrinter(p, &e);
2044         }
2045
2046         result = delete_printer_handle(p, r->in.handle);
2047
2048         update_c_setprinter(false);
2049
2050         return result;
2051 }
2052
2053 /*******************************************************************
2054  * static function to lookup the version id corresponding to an
2055  * long architecture string
2056  ******************************************************************/
2057
2058 static int get_version_id(const char *arch)
2059 {
2060         int i;
2061         struct print_architecture_table_node archi_table[]= {
2062
2063                 {"Windows 4.0",          "WIN40",       0 },
2064                 {"Windows NT x86",       "W32X86",      2 },
2065                 {"Windows NT R4000",     "W32MIPS",     2 },
2066                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2067                 {"Windows NT PowerPC",   "W32PPC",      2 },
2068                 {"Windows IA64",         "IA64",        3 },
2069                 {"Windows x64",          "x64",         3 },
2070                 {NULL,                   "",            -1 }
2071         };
2072
2073         for (i=0; archi_table[i].long_archi != NULL; i++)
2074         {
2075                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2076                         return (archi_table[i].version);
2077         }
2078
2079         return -1;
2080 }
2081
2082 /****************************************************************
2083  _spoolss_DeletePrinterDriver
2084 ****************************************************************/
2085
2086 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2087                                     struct spoolss_DeletePrinterDriver *r)
2088 {
2089         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2090         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2091         int                             version;
2092         WERROR                          status;
2093         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2094         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2095
2096         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2097            and not a printer admin, then fail */
2098
2099         if ( (p->server_info->utok.uid != sec_initial_uid())
2100                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2101                 && !token_contains_name_in_list(
2102                         uidtoname(p->server_info->utok.uid), NULL,
2103                         NULL, p->server_info->ptok,
2104                         lp_printer_admin(-1)) )
2105         {
2106                 return WERR_ACCESS_DENIED;
2107         }
2108
2109         /* check that we have a valid driver name first */
2110
2111         if ((version = get_version_id(r->in.architecture)) == -1)
2112                 return WERR_INVALID_ENVIRONMENT;
2113
2114         ZERO_STRUCT(info);
2115         ZERO_STRUCT(info_win2k);
2116
2117         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2118                                                 r->in.architecture,
2119                                                 version)))
2120         {
2121                 /* try for Win2k driver if "Windows NT x86" */
2122
2123                 if ( version == 2 ) {
2124                         version = 3;
2125                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2126                                                                 r->in.driver,
2127                                                                 r->in.architecture,
2128                                                                 version))) {
2129                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130                                 goto done;
2131                         }
2132                 }
2133                 /* otherwise it was a failure */
2134                 else {
2135                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2136                         goto done;
2137                 }
2138
2139         }
2140
2141         if (printer_driver_in_use(info.info_3)) {
2142                 status = WERR_PRINTER_DRIVER_IN_USE;
2143                 goto done;
2144         }
2145
2146         if ( version == 2 )
2147         {
2148                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2149                                                        r->in.driver,
2150                                                        r->in.architecture, 3)))
2151                 {
2152                         /* if we get to here, we now have 2 driver info structures to remove */
2153                         /* remove the Win2k driver first*/
2154
2155                         status_win2k = delete_printer_driver(
2156                                 p, info_win2k.info_3, 3, false);
2157                         free_a_printer_driver( info_win2k, 3 );
2158
2159                         /* this should not have failed---if it did, report to client */
2160                         if ( !W_ERROR_IS_OK(status_win2k) )
2161                         {
2162                                 status = status_win2k;
2163                                 goto done;
2164                         }
2165                 }
2166         }
2167
2168         status = delete_printer_driver(p, info.info_3, version, false);
2169
2170         /* if at least one of the deletes succeeded return OK */
2171
2172         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2173                 status = WERR_OK;
2174
2175 done:
2176         free_a_printer_driver( info, 3 );
2177
2178         return status;
2179 }
2180
2181 /****************************************************************
2182  _spoolss_DeletePrinterDriverEx
2183 ****************************************************************/
2184
2185 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2186                                       struct spoolss_DeletePrinterDriverEx *r)
2187 {
2188         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2189         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2190         int                             version;
2191         bool                            delete_files;
2192         WERROR                          status;
2193         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2194         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2195
2196         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2197            and not a printer admin, then fail */
2198
2199         if ( (p->server_info->utok.uid != sec_initial_uid())
2200                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2201                 && !token_contains_name_in_list(
2202                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2203                         p->server_info->ptok, lp_printer_admin(-1)) )
2204         {
2205                 return WERR_ACCESS_DENIED;
2206         }
2207
2208         /* check that we have a valid driver name first */
2209         if ((version = get_version_id(r->in.architecture)) == -1) {
2210                 /* this is what NT returns */
2211                 return WERR_INVALID_ENVIRONMENT;
2212         }
2213
2214         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2215                 version = r->in.version;
2216
2217         ZERO_STRUCT(info);
2218         ZERO_STRUCT(info_win2k);
2219
2220         status = get_a_printer_driver(&info, 3, r->in.driver,
2221                                       r->in.architecture, version);
2222
2223         if ( !W_ERROR_IS_OK(status) )
2224         {
2225                 /*
2226                  * if the client asked for a specific version,
2227                  * or this is something other than Windows NT x86,
2228                  * then we've failed
2229                  */
2230
2231                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2232                         goto done;
2233
2234                 /* try for Win2k driver if "Windows NT x86" */
2235
2236                 version = 3;
2237                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2238                                                         r->in.architecture,
2239                                                         version))) {
2240                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2241                         goto done;
2242                 }
2243         }
2244
2245         if ( printer_driver_in_use(info.info_3) ) {
2246                 status = WERR_PRINTER_DRIVER_IN_USE;
2247                 goto done;
2248         }
2249
2250         /*
2251          * we have a couple of cases to consider.
2252          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2253          *     then the delete should fail if **any** files overlap with
2254          *     other drivers
2255          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2256          *     non-overlapping files
2257          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2258          *     is set, the do not delete any files
2259          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2260          */
2261
2262         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2263
2264         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2265
2266         if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2267                 /* no idea of the correct error here */
2268                 status = WERR_ACCESS_DENIED;
2269                 goto done;
2270         }
2271
2272
2273         /* also check for W32X86/3 if necessary; maybe we already have? */
2274
2275         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2276                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2277                                                        r->in.driver,
2278                                                        r->in.architecture, 3)))
2279                 {
2280
2281                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2282                                 /* no idea of the correct error here */
2283                                 free_a_printer_driver( info_win2k, 3 );
2284                                 status = WERR_ACCESS_DENIED;
2285                                 goto done;
2286                         }
2287
2288                         /* if we get to here, we now have 2 driver info structures to remove */
2289                         /* remove the Win2k driver first*/
2290
2291                         status_win2k = delete_printer_driver(
2292                                 p, info_win2k.info_3, 3, delete_files);
2293                         free_a_printer_driver( info_win2k, 3 );
2294
2295                         /* this should not have failed---if it did, report to client */
2296
2297                         if ( !W_ERROR_IS_OK(status_win2k) )
2298                                 goto done;
2299                 }
2300         }
2301
2302         status = delete_printer_driver(p, info.info_3, version, delete_files);
2303
2304         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2305                 status = WERR_OK;
2306 done:
2307         free_a_printer_driver( info, 3 );
2308
2309         return status;
2310 }
2311
2312
2313 /****************************************************************************
2314  Internal routine for removing printerdata
2315  ***************************************************************************/
2316
2317 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2318 {
2319         return delete_printer_data( printer->info_2, key, value );
2320 }
2321
2322 /****************************************************************************
2323  Internal routine for storing printerdata
2324  ***************************************************************************/
2325
2326 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2327                           const char *key, const char *value,
2328                           uint32_t type, uint8_t *data, int real_len)
2329 {
2330         /* the registry objects enforce uniqueness based on value name */
2331
2332         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2333 }
2334
2335 /********************************************************************
2336  GetPrinterData on a printer server Handle.
2337 ********************************************************************/
2338
2339 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2340                                             const char *value,
2341                                             enum winreg_Type *type,
2342                                             union spoolss_PrinterData *data)
2343 {
2344         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2345
2346         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2347                 *type = REG_DWORD;
2348                 data->value = 0x00;
2349                 return WERR_OK;
2350         }
2351
2352         if (!StrCaseCmp(value, "BeepEnabled")) {
2353                 *type = REG_DWORD;
2354                 data->value = 0x00;
2355                 return WERR_OK;
2356         }
2357
2358         if (!StrCaseCmp(value, "EventLog")) {
2359                 *type = REG_DWORD;
2360                 /* formally was 0x1b */
2361                 data->value = 0x00;
2362                 return WERR_OK;
2363         }
2364
2365         if (!StrCaseCmp(value, "NetPopup")) {
2366                 *type = REG_DWORD;
2367                 data->value = 0x00;
2368                 return WERR_OK;
2369         }
2370
2371         if (!StrCaseCmp(value, "MajorVersion")) {
2372                 *type = REG_DWORD;
2373
2374                 /* Windows NT 4.0 seems to not allow uploading of drivers
2375                    to a server that reports 0x3 as the MajorVersion.
2376                    need to investigate more how Win2k gets around this .
2377                    -- jerry */
2378
2379                 if (RA_WINNT == get_remote_arch()) {
2380                         data->value = 0x02;
2381                 } else {
2382                         data->value = 0x03;
2383                 }
2384
2385                 return WERR_OK;
2386         }
2387
2388         if (!StrCaseCmp(value, "MinorVersion")) {
2389                 *type = REG_DWORD;
2390                 data->value = 0x00;
2391                 return WERR_OK;
2392         }
2393
2394         /* REG_BINARY
2395          *  uint32_t size        = 0x114
2396          *  uint32_t major       = 5
2397          *  uint32_t minor       = [0|1]
2398          *  uint32_t build       = [2195|2600]
2399          *  extra unicode string = e.g. "Service Pack 3"
2400          */
2401         if (!StrCaseCmp(value, "OSVersion")) {
2402                 DATA_BLOB blob;
2403                 enum ndr_err_code ndr_err;
2404                 struct spoolss_OSVersion os;
2405
2406                 os.major                = 5;    /* Windows 2000 == 5.0 */
2407                 os.minor                = 0;
2408                 os.build                = 2195; /* build */
2409                 os.extra_string         = "";   /* leave extra string empty */
2410
2411                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2412                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2413                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2414                         return WERR_GENERAL_FAILURE;
2415                 }
2416
2417                 *type = REG_BINARY;
2418                 data->binary = blob;
2419
2420                 return WERR_OK;
2421         }
2422
2423
2424         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2425                 *type = REG_SZ;
2426
2427                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2428                 W_ERROR_HAVE_NO_MEMORY(data->string);
2429
2430                 return WERR_OK;
2431         }
2432
2433         if (!StrCaseCmp(value, "Architecture")) {
2434                 *type = REG_SZ;
2435
2436                 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2437                 W_ERROR_HAVE_NO_MEMORY(data->string);
2438
2439                 return WERR_OK;
2440         }
2441
2442         if (!StrCaseCmp(value, "DsPresent")) {
2443                 *type = REG_DWORD;
2444
2445                 /* only show the publish check box if we are a
2446                    member of a AD domain */
2447
2448                 if (lp_security() == SEC_ADS) {
2449                         data->value = 0x01;
2450                 } else {
2451                         data->value = 0x00;
2452                 }
2453                 return WERR_OK;
2454         }
2455
2456         if (!StrCaseCmp(value, "DNSMachineName")) {
2457                 const char *hostname = get_mydnsfullname();
2458
2459                 if (!hostname) {
2460                         return WERR_BADFILE;
2461                 }
2462
2463                 *type = REG_SZ;
2464                 data->string = talloc_strdup(mem_ctx, hostname);
2465                 W_ERROR_HAVE_NO_MEMORY(data->string);
2466
2467                 return WERR_OK;
2468         }
2469
2470         return WERR_INVALID_PARAM;
2471 }
2472
2473 /****************************************************************
2474  _spoolss_GetPrinterData
2475 ****************************************************************/
2476
2477 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2478                                struct spoolss_GetPrinterData *r)
2479 {
2480         WERROR result;
2481         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2482         NT_PRINTER_INFO_LEVEL *printer = NULL;
2483         int snum = 0;
2484
2485         /*
2486          * Reminder: when it's a string, the length is in BYTES
2487          * even if UNICODE is negociated.
2488          *
2489          * JFM, 4/19/1999
2490          */
2491
2492         /* in case of problem, return some default values */
2493
2494         *r->out.needed  = 0;
2495         *r->out.type    = 0;
2496
2497         DEBUG(4,("_spoolss_GetPrinterData\n"));
2498
2499         if (!Printer) {
2500                 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2501                         OUR_HANDLE(r->in.handle)));
2502                 result = WERR_BADFID;
2503                 goto done;
2504         }
2505
2506         if (Printer->printer_type == SPLHND_SERVER) {
2507                 result = getprinterdata_printer_server(p->mem_ctx,
2508                                                        r->in.value_name,
2509                                                        r->out.type,
2510                                                        r->out.data);
2511         } else {
2512                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2513                         result = WERR_BADFID;
2514                         goto done;
2515                 }
2516
2517                 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2518                 if (!W_ERROR_IS_OK(result)) {
2519                         goto done;
2520                 }
2521
2522                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2523
2524                 if (strequal(r->in.value_name, "ChangeId")) {
2525                         *r->out.type = REG_DWORD;
2526                         r->out.data->value = printer->info_2->changeid;
2527                         result = WERR_OK;
2528                 } else {
2529                         struct regval_blob *v;
2530                         DATA_BLOB blob;
2531
2532                         v = get_printer_data(printer->info_2,
2533                                              SPOOL_PRINTERDATA_KEY,
2534                                              r->in.value_name);
2535                         if (!v) {
2536                                 result = WERR_BADFILE;
2537                                 goto done;
2538                         }
2539
2540                         *r->out.type = v->type;
2541
2542                         blob = data_blob_const(v->data_p, v->size);
2543
2544                         result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2545                                                           r->out.data,
2546                                                           *r->out.type);
2547                 }
2548         }
2549
2550  done:
2551         /* cleanup & exit */
2552
2553         if (printer) {
2554                 free_a_printer(&printer, 2);
2555         }
2556
2557         if (!W_ERROR_IS_OK(result)) {
2558                 return result;
2559         }
2560
2561         *r->out.needed  = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2562         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2563         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2564
2565         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2566 }
2567
2568 /*********************************************************
2569  Connect to the client machine.
2570 **********************************************************/
2571
2572 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2573                         struct sockaddr_storage *client_ss, const char *remote_machine)
2574 {
2575         NTSTATUS ret;
2576         struct cli_state *the_cli;
2577         struct sockaddr_storage rm_addr;
2578
2579         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2580                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2581                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2582                         return false;
2583                 }
2584
2585                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2586                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2587                         return false;
2588                 }
2589         } else {
2590                 char addr[INET6_ADDRSTRLEN];
2591                 rm_addr = *client_ss;
2592                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2593                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2594                         addr));
2595         }
2596
2597         /* setup the connection */
2598
2599         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2600                 &rm_addr, 0, "IPC$", "IPC",
2601                 "", /* username */
2602                 "", /* domain */
2603                 "", /* password */
2604                 0, lp_client_signing(), NULL );
2605
2606         if ( !NT_STATUS_IS_OK( ret ) ) {
2607                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2608                         remote_machine ));
2609                 return false;
2610         }
2611
2612         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2613                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2614                 cli_shutdown(the_cli);
2615                 return false;
2616         }
2617
2618         /*
2619          * Ok - we have an anonymous connection to the IPC$ share.
2620          * Now start the NT Domain stuff :-).
2621          */
2622
2623         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2624         if (!NT_STATUS_IS_OK(ret)) {
2625                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2626                         remote_machine, nt_errstr(ret)));
2627                 cli_shutdown(the_cli);
2628                 return false;
2629         }
2630
2631         return true;
2632 }
2633
2634 /***************************************************************************
2635  Connect to the client.
2636 ****************************************************************************/
2637
2638 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2639                                         uint32_t localprinter, uint32_t type,
2640                                         struct policy_handle *handle,
2641                                         struct sockaddr_storage *client_ss)
2642 {
2643         WERROR result;
2644         NTSTATUS status;
2645
2646         /*
2647          * If it's the first connection, contact the client
2648          * and connect to the IPC$ share anonymously
2649          */
2650         if (smb_connections==0) {
2651                 fstring unix_printer;
2652
2653                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2654
2655                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2656                         return false;
2657
2658                 messaging_register(smbd_messaging_context(), NULL,
2659                                    MSG_PRINTER_NOTIFY2,
2660                                    receive_notify2_message_list);
2661                 /* Tell the connections db we're now interested in printer
2662                  * notify messages. */
2663                 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2664         }
2665
2666         /*
2667          * Tell the specific printing tdb we want messages for this printer
2668          * by registering our PID.
2669          */
2670
2671         if (!print_notify_register_pid(snum))
2672                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2673
2674         smb_connections++;
2675
2676         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2677                                                  printer,
2678                                                  localprinter,
2679                                                  type,
2680                                                  0,
2681                                                  NULL,
2682                                                  handle,
2683                                                  &result);
2684         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2685                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2686                         win_errstr(result)));
2687
2688         return (W_ERROR_IS_OK(result));
2689 }
2690
2691 /****************************************************************
2692  ****************************************************************/
2693
2694 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2695                                                              const struct spoolss_NotifyOption *r)
2696 {
2697         struct spoolss_NotifyOption *option;
2698         uint32_t i,k;
2699
2700         if (!r) {
2701                 return NULL;
2702         }
2703
2704         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2705         if (!option) {
2706                 return NULL;
2707         }
2708
2709         *option = *r;
2710
2711         if (!option->count) {
2712                 return option;
2713         }
2714
2715         option->types = talloc_zero_array(option,
2716                 struct spoolss_NotifyOptionType, option->count);
2717         if (!option->types) {
2718                 talloc_free(option);
2719                 return NULL;
2720         }
2721
2722         for (i=0; i < option->count; i++) {
2723                 option->types[i] = r->types[i];
2724
2725                 if (option->types[i].count) {
2726                         option->types[i].fields = talloc_zero_array(option,
2727                                 union spoolss_Field, option->types[i].count);
2728                         if (!option->types[i].fields) {
2729                                 talloc_free(option);
2730                                 return NULL;
2731                         }
2732                         for (k=0; k<option->types[i].count; k++) {
2733                                 option->types[i].fields[k] =
2734                                         r->types[i].fields[k];
2735                         }
2736                 }
2737         }
2738
2739         return option;
2740 }
2741
2742 /****************************************************************
2743  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2744  *
2745  * before replying OK: status=0 a rpc call is made to the workstation
2746  * asking ReplyOpenPrinter
2747  *
2748  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2749  * called from api_spoolss_rffpcnex
2750 ****************************************************************/
2751
2752 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2753                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2754 {
2755         int snum = -1;
2756         struct spoolss_NotifyOption *option = r->in.notify_options;
2757         struct sockaddr_storage client_ss;
2758
2759         /* store the notify value in the printer struct */
2760
2761         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2762
2763         if (!Printer) {
2764                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2765                         "Invalid handle (%s:%u:%u).\n",
2766                         OUR_HANDLE(r->in.handle)));
2767                 return WERR_BADFID;
2768         }
2769
2770         Printer->notify.flags           = r->in.flags;
2771         Printer->notify.options         = r->in.options;
2772         Printer->notify.printerlocal    = r->in.printer_local;
2773
2774         TALLOC_FREE(Printer->notify.option);
2775         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2776
2777         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2778
2779         /* Connect to the client machine and send a ReplyOpenPrinter */
2780
2781         if ( Printer->printer_type == SPLHND_SERVER)
2782                 snum = -1;
2783         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2784                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2785                 return WERR_BADFID;
2786
2787         if (!interpret_string_addr(&client_ss, p->client_address,
2788                                    AI_NUMERICHOST)) {
2789                 return WERR_SERVER_UNAVAILABLE;
2790         }
2791
2792         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2793                                         Printer->notify.printerlocal, 1,
2794                                         &Printer->notify.client_hnd, &client_ss))
2795                 return WERR_SERVER_UNAVAILABLE;
2796
2797         Printer->notify.client_connected = true;
2798
2799         return WERR_OK;
2800 }
2801
2802 /*******************************************************************
2803  * fill a notify_info_data with the servername
2804  ********************************************************************/
2805
2806 void spoolss_notify_server_name(int snum,
2807                                        struct spoolss_Notify *data,
2808                                        print_queue_struct *queue,
2809                                        NT_PRINTER_INFO_LEVEL *printer,
2810                                        TALLOC_CTX *mem_ctx)
2811 {
2812         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2813 }
2814
2815 /*******************************************************************
2816  * fill a notify_info_data with the printername (not including the servername).
2817  ********************************************************************/
2818
2819 void spoolss_notify_printer_name(int snum,
2820                                         struct spoolss_Notify *data,
2821                                         print_queue_struct *queue,
2822                                         NT_PRINTER_INFO_LEVEL *printer,
2823                                         TALLOC_CTX *mem_ctx)
2824 {
2825         /* the notify name should not contain the \\server\ part */
2826         char *p = strrchr(printer->info_2->printername, '\\');
2827
2828         if (!p) {
2829                 p = printer->info_2->printername;
2830         } else {
2831                 p++;
2832         }
2833
2834         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2835 }
2836
2837 /*******************************************************************
2838  * fill a notify_info_data with the servicename
2839  ********************************************************************/
2840
2841 void spoolss_notify_share_name(int snum,
2842                                       struct spoolss_Notify *data,
2843                                       print_queue_struct *queue,
2844                                       NT_PRINTER_INFO_LEVEL *printer,
2845                                       TALLOC_CTX *mem_ctx)
2846 {
2847         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2848 }
2849
2850 /*******************************************************************
2851  * fill a notify_info_data with the port name
2852  ********************************************************************/
2853
2854 void spoolss_notify_port_name(int snum,
2855                                      struct spoolss_Notify *data,
2856                                      print_queue_struct *queue,
2857                                      NT_PRINTER_INFO_LEVEL *printer,
2858                                      TALLOC_CTX *mem_ctx)
2859 {
2860         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2861 }
2862
2863 /*******************************************************************
2864  * fill a notify_info_data with the printername
2865  * but it doesn't exist, have to see what to do
2866  ********************************************************************/
2867
2868 void spoolss_notify_driver_name(int snum,
2869                                        struct spoolss_Notify *data,
2870                                        print_queue_struct *queue,
2871                                        NT_PRINTER_INFO_LEVEL *printer,
2872                                        TALLOC_CTX *mem_ctx)
2873 {
2874         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2875 }
2876
2877 /*******************************************************************
2878  * fill a notify_info_data with the comment
2879  ********************************************************************/
2880
2881 void spoolss_notify_comment(int snum,
2882                                    struct spoolss_Notify *data,
2883                                    print_queue_struct *queue,
2884                                    NT_PRINTER_INFO_LEVEL *printer,
2885                                    TALLOC_CTX *mem_ctx)
2886 {
2887         char *p;
2888
2889         if (*printer->info_2->comment == '\0') {
2890                 p = lp_comment(snum);
2891         } else {
2892                 p = printer->info_2->comment;
2893         }
2894
2895         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2896 }
2897
2898 /*******************************************************************
2899  * fill a notify_info_data with the comment
2900  * location = "Room 1, floor 2, building 3"
2901  ********************************************************************/
2902
2903 void spoolss_notify_location(int snum,
2904                                     struct spoolss_Notify *data,
2905                                     print_queue_struct *queue,
2906                                     NT_PRINTER_INFO_LEVEL *printer,
2907                                     TALLOC_CTX *mem_ctx)
2908 {
2909         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2910 }
2911
2912 /*******************************************************************
2913  * fill a notify_info_data with the device mode
2914  * jfm:xxxx don't to it for know but that's a real problem !!!
2915  ********************************************************************/
2916
2917 static void spoolss_notify_devmode(int snum,
2918                                    struct spoolss_Notify *data,
2919                                    print_queue_struct *queue,
2920                                    NT_PRINTER_INFO_LEVEL *printer,
2921                                    TALLOC_CTX *mem_ctx)
2922 {
2923         /* for a dummy implementation we have to zero the fields */
2924         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2925 }
2926
2927 /*******************************************************************
2928  * fill a notify_info_data with the separator file name
2929  ********************************************************************/
2930
2931 void spoolss_notify_sepfile(int snum,
2932                                    struct spoolss_Notify *data,
2933                                    print_queue_struct *queue,
2934                                    NT_PRINTER_INFO_LEVEL *printer,
2935                                    TALLOC_CTX *mem_ctx)
2936 {
2937         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2938 }
2939
2940 /*******************************************************************
2941  * fill a notify_info_data with the print processor
2942  * jfm:xxxx return always winprint to indicate we don't do anything to it
2943  ********************************************************************/
2944
2945 void spoolss_notify_print_processor(int snum,
2946                                            struct spoolss_Notify *data,
2947                                            print_queue_struct *queue,
2948                                            NT_PRINTER_INFO_LEVEL *printer,
2949                                            TALLOC_CTX *mem_ctx)
2950 {
2951         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2952 }
2953
2954 /*******************************************************************
2955  * fill a notify_info_data with the print processor options
2956  * jfm:xxxx send an empty string
2957  ********************************************************************/
2958
2959 void spoolss_notify_parameters(int snum,
2960                                       struct spoolss_Notify *data,
2961                                       print_queue_struct *queue,
2962                                       NT_PRINTER_INFO_LEVEL *printer,
2963                                       TALLOC_CTX *mem_ctx)
2964 {
2965         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2966 }
2967
2968 /*******************************************************************
2969  * fill a notify_info_data with the data type
2970  * jfm:xxxx always send RAW as data type
2971  ********************************************************************/
2972
2973 void spoolss_notify_datatype(int snum,
2974                                     struct spoolss_Notify *data,
2975                                     print_queue_struct *queue,
2976                                     NT_PRINTER_INFO_LEVEL *printer,
2977                                     TALLOC_CTX *mem_ctx)
2978 {
2979         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2980 }
2981
2982 /*******************************************************************
2983  * fill a notify_info_data with the security descriptor
2984  * jfm:xxxx send an null pointer to say no security desc
2985  * have to implement security before !
2986  ********************************************************************/
2987
2988 static void spoolss_notify_security_desc(int snum,
2989                                          struct spoolss_Notify *data,
2990                                          print_queue_struct *queue,
2991                                          NT_PRINTER_INFO_LEVEL *printer,
2992                                          TALLOC_CTX *mem_ctx)
2993 {
2994         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2995                                           printer->info_2->secdesc_buf->sd_size,
2996                                           printer->info_2->secdesc_buf->sd);
2997 }
2998
2999 /*******************************************************************
3000  * fill a notify_info_data with the attributes
3001  * jfm:xxxx a samba printer is always shared
3002  ********************************************************************/
3003
3004 void spoolss_notify_attributes(int snum,
3005                                       struct spoolss_Notify *data,
3006                                       print_queue_struct *queue,
3007                                       NT_PRINTER_INFO_LEVEL *printer,
3008                                       TALLOC_CTX *mem_ctx)
3009 {
3010         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3011 }
3012
3013 /*******************************************************************
3014  * fill a notify_info_data with the priority
3015  ********************************************************************/
3016
3017 static void spoolss_notify_priority(int snum,
3018                                     struct spoolss_Notify *data,
3019                                     print_queue_struct *queue,
3020                                     NT_PRINTER_INFO_LEVEL *printer,
3021                                     TALLOC_CTX *mem_ctx)
3022 {
3023         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3024 }
3025
3026 /*******************************************************************
3027  * fill a notify_info_data with the default priority
3028  ********************************************************************/
3029
3030 static void spoolss_notify_default_priority(int snum,
3031                                             struct spoolss_Notify *data,
3032                                             print_queue_struct *queue,
3033                                             NT_PRINTER_INFO_LEVEL *printer,
3034                                             TALLOC_CTX *mem_ctx)
3035 {
3036         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3037 }
3038
3039 /*******************************************************************
3040  * fill a notify_info_data with the start time
3041  ********************************************************************/
3042
3043 static void spoolss_notify_start_time(int snum,
3044                                       struct spoolss_Notify *data,
3045                                       print_queue_struct *queue,
3046                                       NT_PRINTER_INFO_LEVEL *printer,
3047                                       TALLOC_CTX *mem_ctx)
3048 {
3049         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the until time
3054  ********************************************************************/
3055
3056 static void spoolss_notify_until_time(int snum,
3057                                       struct spoolss_Notify *data,
3058                                       print_queue_struct *queue,
3059                                       NT_PRINTER_INFO_LEVEL *printer,
3060                                       TALLOC_CTX *mem_ctx)
3061 {
3062         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3063 }
3064
3065 /*******************************************************************
3066  * fill a notify_info_data with the status
3067  ********************************************************************/
3068
3069 static void spoolss_notify_status(int snum,
3070                                   struct spoolss_Notify *data,
3071                                   print_queue_struct *queue,
3072                                   NT_PRINTER_INFO_LEVEL *printer,
3073                                   TALLOC_CTX *mem_ctx)
3074 {
3075         print_status_struct status;
3076
3077         print_queue_length(snum, &status);
3078         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with the number of jobs queued
3083  ********************************************************************/
3084
3085 void spoolss_notify_cjobs(int snum,
3086                                  struct spoolss_Notify *data,
3087                                  print_queue_struct *queue,
3088                                  NT_PRINTER_INFO_LEVEL *printer,
3089                                  TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the average ppm
3096  ********************************************************************/
3097
3098 static void spoolss_notify_average_ppm(int snum,
3099                                        struct spoolss_Notify *data,
3100                                        print_queue_struct *queue,
3101                                        NT_PRINTER_INFO_LEVEL *printer,
3102                                        TALLOC_CTX *mem_ctx)
3103 {
3104         /* always respond 8 pages per minutes */
3105         /* a little hard ! */
3106         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with username
3111  ********************************************************************/
3112
3113 static void spoolss_notify_username(int snum,
3114                                     struct spoolss_Notify *data,
3115                                     print_queue_struct *queue,
3116                                     NT_PRINTER_INFO_LEVEL *printer,
3117                                     TALLOC_CTX *mem_ctx)
3118 {
3119         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3120 }
3121
3122 /*******************************************************************
3123  * fill a notify_info_data with job status
3124  ********************************************************************/
3125
3126 static void spoolss_notify_job_status(int snum,
3127                                       struct spoolss_Notify *data,
3128                                       print_queue_struct *queue,
3129                                       NT_PRINTER_INFO_LEVEL *printer,
3130                                       TALLOC_CTX *mem_ctx)
3131 {
3132         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3133 }
3134
3135 /*******************************************************************
3136  * fill a notify_info_data with job name
3137  ********************************************************************/
3138
3139 static void spoolss_notify_job_name(int snum,
3140                                     struct spoolss_Notify *data,
3141                                     print_queue_struct *queue,
3142                                     NT_PRINTER_INFO_LEVEL *printer,
3143                                     TALLOC_CTX *mem_ctx)
3144 {
3145         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3146 }
3147
3148 /*******************************************************************
3149  * fill a notify_info_data with job status
3150  ********************************************************************/
3151
3152 static void spoolss_notify_job_status_string(int snum,
3153                                              struct spoolss_Notify *data,
3154                                              print_queue_struct *queue,
3155                                              NT_PRINTER_INFO_LEVEL *printer,
3156                                              TALLOC_CTX *mem_ctx)
3157 {
3158         /*
3159          * Now we're returning job status codes we just return a "" here. JRA.
3160          */
3161
3162         const char *p = "";
3163
3164 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3165         p = "unknown";
3166
3167         switch (queue->status) {
3168         case LPQ_QUEUED:
3169                 p = "Queued";
3170                 break;
3171         case LPQ_PAUSED:
3172                 p = "";    /* NT provides the paused string */
3173                 break;
3174         case LPQ_SPOOLING:
3175                 p = "Spooling";
3176                 break;
3177         case LPQ_PRINTING:
3178                 p = "Printing";
3179                 break;
3180         }
3181 #endif /* NO LONGER NEEDED. */
3182
3183         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3184 }
3185
3186 /*******************************************************************
3187  * fill a notify_info_data with job time
3188  ********************************************************************/
3189
3190 static void spoolss_notify_job_time(int snum,
3191                                     struct spoolss_Notify *data,
3192                                     print_queue_struct *queue,
3193                                     NT_PRINTER_INFO_LEVEL *printer,
3194                                     TALLOC_CTX *mem_ctx)
3195 {
3196         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3197 }
3198
3199 /*******************************************************************
3200  * fill a notify_info_data with job size
3201  ********************************************************************/
3202
3203 static void spoolss_notify_job_size(int snum,
3204                                     struct spoolss_Notify *data,
3205                                     print_queue_struct *queue,
3206                                     NT_PRINTER_INFO_LEVEL *printer,
3207                                     TALLOC_CTX *mem_ctx)
3208 {
3209         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3210 }
3211
3212 /*******************************************************************
3213  * fill a notify_info_data with page info
3214  ********************************************************************/
3215 static void spoolss_notify_total_pages(int snum,
3216                                 struct spoolss_Notify *data,
3217                                 print_queue_struct *queue,
3218                                 NT_PRINTER_INFO_LEVEL *printer,
3219                                 TALLOC_CTX *mem_ctx)
3220 {
3221         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3222 }
3223
3224 /*******************************************************************
3225  * fill a notify_info_data with pages printed info.
3226  ********************************************************************/
3227 static void spoolss_notify_pages_printed(int snum,
3228                                 struct spoolss_Notify *data,
3229                                 print_queue_struct *queue,
3230                                 NT_PRINTER_INFO_LEVEL *printer,
3231                                 TALLOC_CTX *mem_ctx)
3232 {
3233         /* Add code when back-end tracks this */
3234         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3235 }
3236
3237 /*******************************************************************
3238  Fill a notify_info_data with job position.
3239  ********************************************************************/
3240
3241 static void spoolss_notify_job_position(int snum,
3242                                         struct spoolss_Notify *data,
3243                                         print_queue_struct *queue,
3244                                         NT_PRINTER_INFO_LEVEL *printer,
3245                                         TALLOC_CTX *mem_ctx)
3246 {
3247         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3248 }
3249
3250 /*******************************************************************
3251  Fill a notify_info_data with submitted time.
3252  ********************************************************************/
3253
3254 static void spoolss_notify_submitted_time(int snum,
3255                                           struct spoolss_Notify *data,
3256                                           print_queue_struct *queue,
3257                                           NT_PRINTER_INFO_LEVEL *printer,
3258                                           TALLOC_CTX *mem_ctx)
3259 {
3260         data->data.string.string = NULL;
3261         data->data.string.size = 0;
3262
3263         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3264                                &data->data.string.string,
3265                                &data->data.string.size);
3266
3267 }
3268
3269 struct s_notify_info_data_table
3270 {
3271         enum spoolss_NotifyType type;
3272         uint16_t field;
3273         const char *name;
3274         enum spoolss_NotifyTable variable_type;
3275         void (*fn) (int snum, struct spoolss_Notify *data,
3276                     print_queue_struct *queue,
3277                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3278 };
3279
3280 /* A table describing the various print notification constants and
3281    whether the notification data is a pointer to a variable sized
3282    buffer, a one value uint32_t or a two value uint32_t. */
3283
3284 static const struct s_notify_info_data_table notify_info_data_table[] =
3285 {
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3326 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3327 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3328 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3329 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3330 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3331 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3332 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3333 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3334 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3335 };
3336
3337 /*******************************************************************
3338  Return the variable_type of info_data structure.
3339 ********************************************************************/
3340
3341 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3342                                                   uint16_t field)
3343 {
3344         int i=0;
3345
3346         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3347                 if ( (notify_info_data_table[i].type == type) &&
3348                      (notify_info_data_table[i].field == field) ) {
3349                         return notify_info_data_table[i].variable_type;
3350                 }
3351         }
3352
3353         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3354
3355         return 0;
3356 }
3357
3358 /****************************************************************************
3359 ****************************************************************************/
3360
3361 static bool search_notify(enum spoolss_NotifyType type,
3362                           uint16_t field,
3363                           int *value)
3364 {
3365         int i;
3366
3367         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3368                 if (notify_info_data_table[i].type == type &&
3369                     notify_info_data_table[i].field == field &&
3370                     notify_info_data_table[i].fn != NULL) {
3371                         *value = i;
3372                         return true;
3373                 }
3374         }
3375
3376         return false;
3377 }
3378
3379 /****************************************************************************
3380 ****************************************************************************/
3381
3382 void construct_info_data(struct spoolss_Notify *info_data,
3383                          enum spoolss_NotifyType type,
3384                          uint16_t field,
3385                          int id)
3386 {
3387         info_data->type                 = type;
3388         info_data->field.field          = field;
3389         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3390         info_data->job_id               = id;
3391 }
3392
3393 /*******************************************************************
3394  *
3395  * fill a notify_info struct with info asked
3396  *
3397  ********************************************************************/
3398
3399 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3400                                           struct spoolss_NotifyInfo *info,
3401                                           int snum,
3402                                           const struct spoolss_NotifyOptionType *option_type,
3403                                           uint32_t id,
3404                                           TALLOC_CTX *mem_ctx)
3405 {
3406         int field_num,j;
3407         enum spoolss_NotifyType type;
3408         uint16_t field;
3409
3410         struct spoolss_Notify *current_data;
3411         NT_PRINTER_INFO_LEVEL *printer = NULL;
3412         print_queue_struct *queue=NULL;
3413
3414         type = option_type->type;
3415
3416         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3417                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3418                 option_type->count, lp_servicename(snum)));
3419
3420         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3421                 return false;
3422
3423         for(field_num=0; field_num < option_type->count; field_num++) {
3424                 field = option_type->fields[field_num].field;
3425
3426                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3427
3428                 if (!search_notify(type, field, &j) )
3429                         continue;
3430
3431                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3432                                                       struct spoolss_Notify,
3433                                                       info->count + 1);
3434                 if (info->notifies == NULL) {
3435                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3436                         free_a_printer(&printer, 2);
3437                         return false;
3438                 }
3439
3440                 current_data = &info->notifies[info->count];
3441
3442                 construct_info_data(current_data, type, field, id);
3443
3444                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3445                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3446
3447                 notify_info_data_table[j].fn(snum, current_data, queue,
3448                                              printer, mem_ctx);
3449
3450                 info->count++;
3451         }
3452
3453         free_a_printer(&printer, 2);
3454         return true;
3455 }
3456
3457 /*******************************************************************
3458  *
3459  * fill a notify_info struct with info asked
3460  *
3461  ********************************************************************/
3462
3463 static bool construct_notify_jobs_info(print_queue_struct *queue,
3464                                        struct spoolss_NotifyInfo *info,
3465                                        NT_PRINTER_INFO_LEVEL *printer,
3466                                        int snum,
3467                                        const struct spoolss_NotifyOptionType *option_type,
3468                                        uint32_t id,
3469                                        TALLOC_CTX *mem_ctx)
3470 {
3471         int field_num,j;
3472         enum spoolss_NotifyType type;
3473         uint16_t field;
3474         struct spoolss_Notify *current_data;
3475
3476         DEBUG(4,("construct_notify_jobs_info\n"));
3477
3478         type = option_type->type;
3479
3480         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3481                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3482                 option_type->count));
3483
3484         for(field_num=0; field_num<option_type->count; field_num++) {
3485                 field = option_type->fields[field_num].field;
3486
3487                 if (!search_notify(type, field, &j) )
3488                         continue;
3489
3490                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3491                                                       struct spoolss_Notify,
3492                                                       info->count + 1);
3493                 if (info->notifies == NULL) {
3494                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3495                         return false;
3496                 }
3497
3498                 current_data=&(info->notifies[info->count]);
3499
3500                 construct_info_data(current_data, type, field, id);
3501                 notify_info_data_table[j].fn(snum, current_data, queue,
3502                                              printer, mem_ctx);
3503                 info->count++;
3504         }
3505
3506         return true;
3507 }
3508
3509 /*
3510  * JFM: The enumeration is not that simple, it's even non obvious.
3511  *
3512  * let's take an example: I want to monitor the PRINTER SERVER for
3513  * the printer's name and the number of jobs currently queued.
3514  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3515  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3516  *
3517  * I have 3 printers on the back of my server.
3518  *
3519  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3520  * structures.
3521  *   Number     Data                    Id
3522  *      1       printer 1 name          1
3523  *      2       printer 1 cjob          1
3524  *      3       printer 2 name          2
3525  *      4       printer 2 cjob          2
3526  *      5       printer 3 name          3
3527  *      6       printer 3 name          3
3528  *
3529  * that's the print server case, the printer case is even worse.
3530  */
3531
3532 /*******************************************************************
3533  *
3534  * enumerate all printers on the printserver
3535  * fill a notify_info struct with info asked
3536  *
3537  ********************************************************************/
3538
3539 static WERROR printserver_notify_info(pipes_struct *p,
3540                                       struct policy_handle *hnd,
3541                                       struct spoolss_NotifyInfo *info,
3542                                       TALLOC_CTX *mem_ctx)
3543 {
3544         int snum;
3545         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3546         int n_services=lp_numservices();
3547         int i;
3548         struct spoolss_NotifyOption *option;
3549         struct spoolss_NotifyOptionType option_type;
3550
3551         DEBUG(4,("printserver_notify_info\n"));
3552
3553         if (!Printer)
3554                 return WERR_BADFID;
3555
3556         option = Printer->notify.option;
3557
3558         info->version   = 2;
3559         info->notifies  = NULL;
3560         info->count     = 0;
3561
3562         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3563            sending a ffpcn() request first */
3564
3565         if ( !option )
3566                 return WERR_BADFID;
3567
3568         for (i=0; i<option->count; i++) {
3569                 option_type = option->types[i];
3570
3571                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3572                         continue;
3573
3574                 for (snum=0; snum<n_services; snum++)
3575                 {
3576                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3577                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3578                 }
3579         }
3580
3581 #if 0
3582         /*
3583          * Debugging information, don't delete.
3584          */
3585
3586         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3587         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3588         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3589
3590         for (i=0; i<info->count; i++) {
3591                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3592                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3593                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3594         }
3595 #endif
3596
3597         return WERR_OK;
3598 }
3599
3600 /*******************************************************************
3601  *
3602  * fill a notify_info struct with info asked
3603  *
3604  ********************************************************************/
3605
3606 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3607                                   struct spoolss_NotifyInfo *info,
3608                                   TALLOC_CTX *mem_ctx)
3609 {
3610         int snum;
3611         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3612         int i;
3613         uint32_t id;
3614         struct spoolss_NotifyOption *option;
3615         struct spoolss_NotifyOptionType option_type;
3616         int count,j;
3617         print_queue_struct *queue=NULL;
3618         print_status_struct status;
3619
3620         DEBUG(4,("printer_notify_info\n"));
3621
3622         if (!Printer)
3623                 return WERR_BADFID;
3624
3625         option = Printer->notify.option;
3626         id = 0x0;
3627
3628         info->version   = 2;
3629         info->notifies  = NULL;
3630         info->count     = 0;
3631
3632         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3633            sending a ffpcn() request first */
3634
3635         if ( !option )
3636                 return WERR_BADFID;
3637
3638         get_printer_snum(p, hnd, &snum, NULL);
3639
3640         for (i=0; i<option->count; i++) {
3641                 option_type = option->types[i];
3642
3643                 switch (option_type.type) {
3644                 case PRINTER_NOTIFY_TYPE:
3645                         if(construct_notify_printer_info(Printer, info, snum,
3646                                                          &option_type, id,
3647                                                          mem_ctx))
3648                                 id--;
3649                         break;
3650
3651                 case JOB_NOTIFY_TYPE: {
3652                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3653
3654                         count = print_queue_status(snum, &queue, &status);
3655
3656                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3657                                 goto done;
3658
3659                         for (j=0; j<count; j++) {
3660                                 construct_notify_jobs_info(&queue[j], info,
3661                                                            printer, snum,
3662                                                            &option_type,
3663                                                            queue[j].job,
3664                                                            mem_ctx);
3665                         }
3666
3667                         free_a_printer(&printer, 2);
3668
3669                 done:
3670                         SAFE_FREE(queue);
3671                         break;
3672                 }
3673                 }
3674         }
3675
3676         /*
3677          * Debugging information, don't delete.
3678          */
3679         /*
3680         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3681         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3682         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3683
3684         for (i=0; i<info->count; i++) {
3685                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3686                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3687                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3688         }
3689         */
3690         return WERR_OK;
3691 }
3692
3693 /****************************************************************
3694  _spoolss_RouterRefreshPrinterChangeNotify
3695 ****************************************************************/
3696
3697 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3698                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3699 {
3700         struct spoolss_NotifyInfo *info;
3701
3702         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3703         WERROR result = WERR_BADFID;
3704
3705         /* we always have a spoolss_NotifyInfo struct */
3706         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3707         if (!info) {
3708                 result = WERR_NOMEM;
3709                 goto done;
3710         }
3711
3712         *r->out.info = info;
3713
3714         if (!Printer) {
3715                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3716                         "Invalid handle (%s:%u:%u).\n",
3717                         OUR_HANDLE(r->in.handle)));
3718                 goto done;
3719         }
3720
3721         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3722
3723         /*
3724          *      We are now using the change value, and
3725          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3726          *      I don't have a global notification system, I'm sending back all the
3727          *      informations even when _NOTHING_ has changed.
3728          */
3729
3730         /* We need to keep track of the change value to send back in
3731            RRPCN replies otherwise our updates are ignored. */
3732
3733         Printer->notify.fnpcn = true;
3734
3735         if (Printer->notify.client_connected) {
3736                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3737                         "Saving change value in request [%x]\n",
3738                         r->in.change_low));
3739                 Printer->notify.change = r->in.change_low;
3740         }
3741
3742         /* just ignore the spoolss_NotifyOption */
3743
3744         switch (Printer->printer_type) {
3745                 case SPLHND_SERVER:
3746                         result = printserver_notify_info(p, r->in.handle,
3747                                                          info, p->mem_ctx);
3748                         break;
3749
3750                 case SPLHND_PRINTER:
3751                         result = printer_notify_info(p, r->in.handle,
3752                                                      info, p->mem_ctx);
3753                         break;
3754         }
3755
3756         Printer->notify.fnpcn = false;
3757
3758 done:
3759         return result;
3760 }
3761
3762 /********************************************************************
3763  * construct_printer_info_0
3764  * fill a printer_info_0 struct
3765  ********************************************************************/
3766
3767 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3768                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3769                                       struct spoolss_PrinterInfo0 *r,
3770                                       int snum)
3771 {
3772         int count;
3773         counter_printer_0 *session_counter;
3774         time_t setuptime;
3775         print_status_struct status;
3776
3777         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3778         W_ERROR_HAVE_NO_MEMORY(r->printername);
3779
3780         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3781         W_ERROR_HAVE_NO_MEMORY(r->servername);
3782
3783         count = print_queue_length(snum, &status);
3784
3785         /* check if we already have a counter for this printer */
3786         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3787                 if (session_counter->snum == snum)
3788                         break;
3789         }
3790
3791         /* it's the first time, add it to the list */
3792         if (session_counter == NULL) {
3793                 session_counter = SMB_MALLOC_P(counter_printer_0);
3794                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3795                 ZERO_STRUCTP(session_counter);
3796                 session_counter->snum           = snum;
3797                 session_counter->counter        = 0;
3798                 DLIST_ADD(counter_list, session_counter);
3799         }
3800
3801         /* increment it */
3802         session_counter->counter++;
3803
3804         r->cjobs                        = count;
3805         r->total_jobs                   = 0;
3806         r->total_bytes                  = 0;
3807
3808         setuptime = (time_t)ntprinter->info_2->setuptime;
3809
3810         init_systemtime(&r->time, gmtime(&setuptime));
3811
3812         /* JFM:
3813          * the global_counter should be stored in a TDB as it's common to all the clients
3814          * and should be zeroed on samba startup
3815          */
3816         r->global_counter               = session_counter->counter;
3817         r->total_pages                  = 0;
3818         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3819         r->version                      = 0x0005;       /* NT 5 */
3820         r->free_build                   = 0x0893;       /* build 2195 */
3821         r->spooling                     = 0;
3822         r->max_spooling                 = 0;
3823         r->session_counter              = session_counter->counter;
3824         r->num_error_out_of_paper       = 0x0;
3825         r->num_error_not_ready          = 0x0;          /* number of print failure */
3826         r->job_error                    = 0x0;
3827         r->number_of_processors         = 0x1;
3828         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3829         r->high_part_total_bytes        = 0x0;
3830         r->change_id                    = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3831         r->last_error                   = WERR_OK;
3832         r->status                       = nt_printq_status(status.status);
3833         r->enumerate_network_printers   = 0x0;
3834         r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3835         r->processor_architecture       = 0x0;
3836         r->processor_level              = 0x6;          /* 6  ???*/
3837         r->ref_ic                       = 0;
3838         r->reserved2                    = 0;
3839         r->reserved3                    = 0;
3840
3841         return WERR_OK;
3842 }
3843
3844 /****************************************************************************
3845  Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure.  Both pointers
3846  should be valid upon entry
3847 ****************************************************************************/
3848
3849 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3850                                     struct spoolss_DeviceMode *r,
3851                                     const NT_DEVICEMODE *ntdevmode)
3852 {
3853         if (!r || !ntdevmode) {
3854                 return WERR_INVALID_PARAM;
3855         }
3856
3857         r->devicename           = talloc_strdup(mem_ctx, ntdevmode->devicename);
3858         W_ERROR_HAVE_NO_MEMORY(r->devicename);
3859
3860         r->specversion          = ntdevmode->specversion;
3861         r->driverversion        = ntdevmode->driverversion;
3862         r->size                 = ntdevmode->size;
3863         r->__driverextra_length = ntdevmode->driverextra;
3864         r->fields               = ntdevmode->fields;
3865
3866         r->orientation          = ntdevmode->orientation;
3867         r->papersize            = ntdevmode->papersize;
3868         r->paperlength          = ntdevmode->paperlength;
3869         r->paperwidth           = ntdevmode->paperwidth;
3870         r->scale                = ntdevmode->scale;
3871         r->copies               = ntdevmode->copies;
3872         r->defaultsource        = ntdevmode->defaultsource;
3873         r->printquality         = ntdevmode->printquality;
3874         r->color                = ntdevmode->color;
3875         r->duplex               = ntdevmode->duplex;
3876         r->yresolution          = ntdevmode->yresolution;
3877         r->ttoption             = ntdevmode->ttoption;
3878         r->collate              = ntdevmode->collate;
3879
3880         r->formname             = talloc_strdup(mem_ctx, ntdevmode->formname);
3881         W_ERROR_HAVE_NO_MEMORY(r->formname);
3882
3883         /* all 0 below are values that have not been set in the old parsing/copy
3884          * function, maybe they should... - gd */
3885
3886         r->logpixels            = 0;
3887         r->bitsperpel           = 0;
3888         r->pelswidth            = 0;
3889         r->pelsheight           = 0;
3890         r->displayflags         = 0;
3891         r->displayfrequency     = 0;
3892         r->icmmethod            = ntdevmode->icmmethod;
3893         r->icmintent            = ntdevmode->icmintent;
3894         r->mediatype            = ntdevmode->mediatype;
3895         r->dithertype           = ntdevmode->dithertype;
3896         r->reserved1            = 0;
3897         r->reserved2            = 0;
3898         r->panningwidth         = 0;
3899         r->panningheight        = 0;
3900
3901         if (ntdevmode->nt_dev_private != NULL) {
3902                 r->driverextra_data = data_blob_talloc(mem_ctx,
3903                         ntdevmode->nt_dev_private,
3904                         ntdevmode->driverextra);
3905                 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3906         }
3907
3908         return WERR_OK;
3909 }
3910
3911
3912 /****************************************************************************
3913  Create a spoolss_DeviceMode struct. Returns talloced memory.
3914 ****************************************************************************/
3915
3916 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3917                                               const char *servicename)
3918 {
3919         WERROR result;
3920         NT_PRINTER_INFO_LEVEL   *printer = NULL;
3921         struct spoolss_DeviceMode *devmode = NULL;
3922
3923         DEBUG(7,("construct_dev_mode\n"));
3924
3925         DEBUGADD(8,("getting printer characteristics\n"));
3926
3927         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3928                 return NULL;
3929
3930         if (!printer->info_2->devmode) {
3931                 DEBUG(5, ("BONG! There was no device mode!\n"));
3932                 goto done;
3933         }
3934
3935         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3936         if (!devmode) {
3937                 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3938                 goto done;
3939         }
3940
3941         DEBUGADD(8,("loading DEVICEMODE\n"));
3942
3943         result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3944         if (!W_ERROR_IS_OK(result)) {
3945                 TALLOC_FREE(devmode);
3946         }
3947
3948 done:
3949         free_a_printer(&printer,2);
3950
3951         return devmode;
3952 }
3953
3954 /********************************************************************
3955  * construct_printer_info3
3956  * fill a spoolss_PrinterInfo3 struct
3957  ********************************************************************/
3958
3959 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3960                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3961                                       struct spoolss_PrinterInfo3 *r,
3962                                       int snum)
3963 {
3964         /* These are the components of the SD we are returning. */
3965
3966         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3967                 /* don't use talloc_steal() here unless you do a deep steal of all
3968                    the SEC_DESC members */
3969
3970                 r->secdesc = dup_sec_desc(mem_ctx,
3971                                           ntprinter->info_2->secdesc_buf->sd);
3972                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3973         }
3974
3975         return WERR_OK;
3976 }
3977
3978 /********************************************************************
3979  * construct_printer_info4
3980  * fill a spoolss_PrinterInfo4 struct
3981  ********************************************************************/
3982
3983 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3984                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
3985                                       struct spoolss_PrinterInfo4 *r,
3986                                       int snum)
3987 {
3988         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3989         W_ERROR_HAVE_NO_MEMORY(r->printername);
3990         r->servername   = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3991         W_ERROR_HAVE_NO_MEMORY(r->servername);
3992
3993         r->attributes   = ntprinter->info_2->attributes;
3994
3995         return WERR_OK;
3996 }
3997
3998 /********************************************************************
3999  * construct_printer_info5
4000  * fill a spoolss_PrinterInfo5 struct
4001  ********************************************************************/
4002
4003 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4004                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4005                                       struct spoolss_PrinterInfo5 *r,
4006                                       int snum)
4007 {
4008         r->printername  = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4009         W_ERROR_HAVE_NO_MEMORY(r->printername);
4010         r->portname     = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4011         W_ERROR_HAVE_NO_MEMORY(r->portname);
4012
4013         r->attributes   = ntprinter->info_2->attributes;
4014
4015         /* these two are not used by NT+ according to MSDN */
4016
4017         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4018         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4019
4020         return WERR_OK;
4021 }
4022
4023 /********************************************************************
4024  * construct_printer_info_6
4025  * fill a spoolss_PrinterInfo6 struct
4026  ********************************************************************/
4027
4028 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4029                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4030                                       struct spoolss_PrinterInfo6 *r,
4031                                       int snum)
4032 {
4033         int count;
4034         print_status_struct status;
4035
4036         count = print_queue_length(snum, &status);
4037
4038         r->status = nt_printq_status(status.status);
4039
4040         return WERR_OK;
4041 }
4042
4043 /********************************************************************
4044  * construct_printer_info7
4045  * fill a spoolss_PrinterInfo7 struct
4046  ********************************************************************/
4047
4048 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4049                                       Printer_entry *print_hnd,
4050                                       struct spoolss_PrinterInfo7 *r,
4051                                       int snum)
4052 {
4053         struct GUID guid;
4054
4055         if (is_printer_published(print_hnd, snum, &guid)) {
4056                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4057                 r->action = DSPRINT_PUBLISH;
4058         } else {
4059                 r->guid = talloc_strdup(mem_ctx, "");
4060                 r->action = DSPRINT_UNPUBLISH;
4061         }
4062         W_ERROR_HAVE_NO_MEMORY(r->guid);
4063
4064         return WERR_OK;
4065 }
4066
4067 /********************************************************************
4068  * construct_printer_info8
4069  * fill a spoolss_PrinterInfo8 struct
4070  ********************************************************************/
4071
4072 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4073                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4074                                       struct spoolss_DeviceModeInfo *r,
4075                                       int snum)
4076 {
4077         struct spoolss_DeviceMode *devmode;
4078         WERROR result;
4079
4080         if (!ntprinter->info_2->devmode) {
4081                 r->devmode = NULL;
4082                 return WERR_OK;
4083         }
4084
4085         devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4086         W_ERROR_HAVE_NO_MEMORY(devmode);
4087
4088         result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4089         if (!W_ERROR_IS_OK(result)) {
4090                 TALLOC_FREE(devmode);
4091                 return result;
4092         }
4093
4094         r->devmode      = devmode;
4095
4096         return WERR_OK;
4097 }
4098
4099
4100 /********************************************************************
4101  * construct_printer_info1
4102  * fill a spoolss_PrinterInfo1 struct
4103 ********************************************************************/
4104
4105 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4106                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4107                                       uint32_t flags,
4108                                       struct spoolss_PrinterInfo1 *r,
4109                                       int snum)
4110 {
4111         r->flags                = flags;
4112
4113         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4114                                                   ntprinter->info_2->printername,
4115                                                   ntprinter->info_2->drivername,
4116                                                   ntprinter->info_2->location);
4117         W_ERROR_HAVE_NO_MEMORY(r->description);
4118
4119         if (*ntprinter->info_2->comment == '\0') {
4120                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4121         } else {
4122                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4123         }
4124         W_ERROR_HAVE_NO_MEMORY(r->comment);
4125
4126         r->name                 = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4127         W_ERROR_HAVE_NO_MEMORY(r->name);
4128
4129         return WERR_OK;
4130 }
4131
4132 /********************************************************************
4133  * construct_printer_info2
4134  * fill a spoolss_PrinterInfo2 struct
4135 ********************************************************************/
4136
4137 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4138                                       const NT_PRINTER_INFO_LEVEL *ntprinter,
4139                                       struct spoolss_PrinterInfo2 *r,
4140                                       int snum)
4141 {
4142         int count;
4143
4144         print_status_struct status;
4145
4146         count = print_queue_length(snum, &status);
4147
4148         r->servername           = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4149         W_ERROR_HAVE_NO_MEMORY(r->servername);
4150         r->printername          = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4151         W_ERROR_HAVE_NO_MEMORY(r->printername);
4152         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4153         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4154         r->portname             = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4155         W_ERROR_HAVE_NO_MEMORY(r->portname);
4156         r->drivername           = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4157         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4158
4159         if (*ntprinter->info_2->comment == '\0') {
4160                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4161         } else {
4162                 r->comment      = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4163         }
4164         W_ERROR_HAVE_NO_MEMORY(r->comment);
4165
4166         r->location             = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4167         W_ERROR_HAVE_NO_MEMORY(r->location);
4168         r->sepfile              = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4169         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4170         r->printprocessor       = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4171         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4172         r->datatype             = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4173         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4174         r->parameters           = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4175         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4176
4177         r->attributes           = ntprinter->info_2->attributes;
4178
4179         r->priority             = ntprinter->info_2->priority;
4180         r->defaultpriority      = ntprinter->info_2->default_priority;
4181         r->starttime            = ntprinter->info_2->starttime;
4182         r->untiltime            = ntprinter->info_2->untiltime;
4183         r->status               = nt_printq_status(status.status);
4184         r->cjobs                = count;
4185         r->averageppm           = ntprinter->info_2->averageppm;
4186
4187         r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4188         if (!r->devmode) {
4189                 DEBUG(8,("Returning NULL Devicemode!\n"));
4190         }
4191
4192         r->secdesc              = NULL;
4193
4194         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4195                 /* don't use talloc_steal() here unless you do a deep steal of all
4196                    the SEC_DESC members */
4197
4198                 r->secdesc      = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4199         }
4200
4201         return WERR_OK;
4202 }
4203
4204 /********************************************************************
4205 ********************************************************************/
4206
4207 static bool snum_is_shared_printer(int snum)
4208 {
4209         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4210 }
4211
4212 /********************************************************************
4213  Spoolss_enumprinters.
4214 ********************************************************************/
4215
4216 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4217                                            uint32_t level,
4218                                            uint32_t flags,
4219                                            union spoolss_PrinterInfo **info_p,
4220                                            uint32_t *count_p)
4221 {
4222         int snum;
4223         int n_services = lp_numservices();
4224         union spoolss_PrinterInfo *info = NULL;
4225         uint32_t count = 0;
4226         WERROR result = WERR_OK;
4227
4228         *count_p = 0;
4229         *info_p = NULL;
4230
4231         for (snum = 0; snum < n_services; snum++) {
4232
4233                 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4234
4235                 if (!snum_is_shared_printer(snum)) {
4236                         continue;
4237                 }
4238
4239                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4240                         lp_servicename(snum), snum));
4241
4242                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4243                                             union spoolss_PrinterInfo,
4244                                             count + 1);
4245                 if (!info) {
4246                         result = WERR_NOMEM;
4247                         goto out;
4248                 }
4249
4250                 result = get_a_printer(NULL, &ntprinter, 2,
4251                                        lp_const_servicename(snum));
4252                 if (!W_ERROR_IS_OK(result)) {
4253                         goto out;
4254                 }
4255
4256                 switch (level) {
4257                 case 0:
4258                         result = construct_printer_info0(info, ntprinter,
4259                                                          &info[count].info0, snum);
4260                         break;
4261                 case 1:
4262                         result = construct_printer_info1(info, ntprinter, flags,
4263                                                          &info[count].info1, snum);
4264                         break;
4265                 case 2:
4266                         result = construct_printer_info2(info, ntprinter,
4267                                                          &info[count].info2, snum);
4268                         break;
4269                 case 4:
4270                         result = construct_printer_info4(info, ntprinter,
4271                                                          &info[count].info4, snum);
4272                         break;
4273                 case 5:
4274                         result = construct_printer_info5(info, ntprinter,
4275                                                          &info[count].info5, snum);
4276                         break;
4277
4278                 default:
4279                         result = WERR_UNKNOWN_LEVEL;
4280                         free_a_printer(&ntprinter, 2);
4281                         goto out;
4282                 }
4283
4284                 free_a_printer(&ntprinter, 2);
4285                 if (!W_ERROR_IS_OK(result)) {
4286                         goto out;
4287                 }
4288
4289                 count++;
4290         }
4291
4292         *count_p = count;
4293         *info_p = info;
4294
4295  out:
4296         if (!W_ERROR_IS_OK(result)) {
4297                 TALLOC_FREE(info);
4298                 return result;
4299         }
4300
4301         *info_p = info;
4302
4303         return WERR_OK;
4304 }
4305
4306 /********************************************************************
4307  * handle enumeration of printers at level 0
4308  ********************************************************************/
4309
4310 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4311                                   uint32_t flags,
4312                                   const char *servername,
4313                                   union spoolss_PrinterInfo **info,
4314                                   uint32_t *count)
4315 {
4316         DEBUG(4,("enum_all_printers_info_0\n"));
4317
4318         return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4319 }
4320
4321
4322 /********************************************************************
4323 ********************************************************************/
4324
4325 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4326                                        uint32_t flags,
4327                                        union spoolss_PrinterInfo **info,
4328                                        uint32_t *count)
4329 {
4330         DEBUG(4,("enum_all_printers_info_1\n"));
4331
4332         return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4333 }
4334
4335 /********************************************************************
4336  enum_all_printers_info_1_local.
4337 *********************************************************************/
4338
4339 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4340                                              union spoolss_PrinterInfo **info,
4341                                              uint32_t *count)
4342 {
4343         DEBUG(4,("enum_all_printers_info_1_local\n"));
4344
4345         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4346 }
4347
4348 /********************************************************************
4349  enum_all_printers_info_1_name.
4350 *********************************************************************/
4351
4352 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4353                                             const char *name,
4354                                             union spoolss_PrinterInfo **info,
4355                                             uint32_t *count)
4356 {
4357         const char *s = name;
4358
4359         DEBUG(4,("enum_all_printers_info_1_name\n"));
4360
4361         if ((name[0] == '\\') && (name[1] == '\\')) {
4362                 s = name + 2;
4363         }
4364
4365         if (!is_myname_or_ipaddr(s)) {
4366                 return WERR_INVALID_NAME;
4367         }
4368
4369         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4370 }
4371
4372 /********************************************************************
4373  enum_all_printers_info_1_network.
4374 *********************************************************************/
4375
4376 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4377                                                const char *name,
4378                                                union spoolss_PrinterInfo **info,
4379                                                uint32_t *count)
4380 {
4381         const char *s = name;
4382
4383         DEBUG(4,("enum_all_printers_info_1_network\n"));
4384
4385         /* If we respond to a enum_printers level 1 on our name with flags
4386            set to PRINTER_ENUM_REMOTE with a list of printers then these
4387            printers incorrectly appear in the APW browse list.
4388            Specifically the printers for the server appear at the workgroup
4389            level where all the other servers in the domain are
4390            listed. Windows responds to this call with a
4391            WERR_CAN_NOT_COMPLETE so we should do the same. */
4392
4393         if (name[0] == '\\' && name[1] == '\\') {
4394                  s = name + 2;
4395         }
4396
4397         if (is_myname_or_ipaddr(s)) {
4398                  return WERR_CAN_NOT_COMPLETE;
4399         }
4400
4401         return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4402 }
4403
4404 /********************************************************************
4405  * api_spoolss_enumprinters
4406  *
4407  * called from api_spoolss_enumprinters (see this to understand)
4408  ********************************************************************/
4409
4410 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4411                                        union spoolss_PrinterInfo **info,
4412                                        uint32_t *count)
4413 {
4414         DEBUG(4,("enum_all_printers_info_2\n"));
4415
4416         return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4417 }
4418
4419 /********************************************************************
4420  * handle enumeration of printers at level 1
4421  ********************************************************************/
4422
4423 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4424                                   uint32_t flags,
4425                                   const char *name,
4426                                   union spoolss_PrinterInfo **info,
4427                                   uint32_t *count)
4428 {
4429         /* Not all the flags are equals */
4430
4431         if (flags & PRINTER_ENUM_LOCAL) {
4432                 return enum_all_printers_info_1_local(mem_ctx, info, count);
4433         }
4434
4435         if (flags & PRINTER_ENUM_NAME) {
4436                 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4437         }
4438
4439         if (flags & PRINTER_ENUM_NETWORK) {
4440                 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4441         }
4442
4443         return WERR_OK; /* NT4sp5 does that */
4444 }
4445
4446 /********************************************************************
4447  * handle enumeration of printers at level 2
4448  ********************************************************************/
4449
4450 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4451                                   uint32_t flags,
4452                                   const char *servername,
4453                                   union spoolss_PrinterInfo **info,
4454                                   uint32_t *count)
4455 {
4456         if (flags & PRINTER_ENUM_LOCAL) {
4457                 return enum_all_printers_info_2(mem_ctx, info, count);
4458         }
4459
4460         if (flags & PRINTER_ENUM_NAME) {
4461                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4462                         return WERR_INVALID_NAME;
4463                 }
4464
4465                 return enum_all_printers_info_2(mem_ctx, info, count);
4466         }
4467
4468         if (flags & PRINTER_ENUM_REMOTE) {
4469                 return WERR_UNKNOWN_LEVEL;
4470         }
4471
4472         return WERR_OK;
4473 }
4474
4475 /********************************************************************
4476  * handle enumeration of printers at level 4
4477  ********************************************************************/
4478
4479 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4480                                   uint32_t flags,
4481                                   const char *servername,
4482                                   union spoolss_PrinterInfo **info,
4483                                   uint32_t *count)
4484 {
4485         DEBUG(4,("enum_all_printers_info_4\n"));
4486
4487         return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4488 }
4489
4490
4491 /********************************************************************
4492  * handle enumeration of printers at level 5
4493  ********************************************************************/
4494
4495 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4496                                   uint32_t flags,
4497                                   const char *servername,
4498                                   union spoolss_PrinterInfo **info,
4499                                   uint32_t *count)
4500 {
4501         DEBUG(4,("enum_all_printers_info_5\n"));
4502
4503         return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4504 }
4505
4506 /****************************************************************
4507  _spoolss_EnumPrinters
4508 ****************************************************************/
4509
4510 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4511                              struct spoolss_EnumPrinters *r)
4512 {
4513         const char *name;
4514         WERROR result;
4515
4516         /* that's an [in out] buffer */
4517
4518         if (!r->in.buffer && (r->in.offered != 0)) {
4519                 return WERR_INVALID_PARAM;
4520         }
4521
4522         DEBUG(4,("_spoolss_EnumPrinters\n"));
4523
4524         *r->out.needed = 0;
4525         *r->out.count = 0;
4526         *r->out.info = NULL;
4527
4528         /*
4529          * Level 1:
4530          *          flags==PRINTER_ENUM_NAME
4531          *           if name=="" then enumerates all printers
4532          *           if name!="" then enumerate the printer
4533          *          flags==PRINTER_ENUM_REMOTE
4534          *          name is NULL, enumerate printers
4535          * Level 2: name!="" enumerates printers, name can't be NULL
4536          * Level 3: doesn't exist
4537          * Level 4: does a local registry lookup
4538          * Level 5: same as Level 2
4539          */
4540
4541         name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4542         W_ERROR_HAVE_NO_MEMORY(name);
4543
4544         switch (r->in.level) {
4545         case 0:
4546                 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4547                                              r->out.info, r->out.count);
4548                 break;
4549         case 1:
4550                 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4551                                              r->out.info, r->out.count);
4552                 break;
4553         case 2:
4554                 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4555                                              r->out.info, r->out.count);
4556                 break;
4557         case 4:
4558                 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4559                                              r->out.info, r->out.count);
4560                 break;
4561         case 5:
4562                 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4563                                              r->out.info, r->out.count);
4564                 break;
4565         default:
4566                 return WERR_UNKNOWN_LEVEL;
4567         }
4568
4569         if (!W_ERROR_IS_OK(result)) {
4570                 return result;
4571         }
4572
4573         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4574                                                      spoolss_EnumPrinters, NULL,
4575                                                      *r->out.info, r->in.level,
4576                                                      *r->out.count);
4577         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4578         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4579
4580         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4581 }
4582
4583 /****************************************************************
4584  _spoolss_GetPrinter
4585 ****************************************************************/
4586
4587 WERROR _spoolss_GetPrinter(pipes_struct *p,
4588                            struct spoolss_GetPrinter *r)
4589 {
4590         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4591         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4592         WERROR result = WERR_OK;
4593
4594         int snum;
4595
4596         /* that's an [in out] buffer */
4597
4598         if (!r->in.buffer && (r->in.offered != 0)) {
4599                 return WERR_INVALID_PARAM;
4600         }
4601
4602         *r->out.needed = 0;
4603
4604         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4605                 return WERR_BADFID;
4606         }
4607
4608         result = get_a_printer(Printer, &ntprinter, 2,
4609                                lp_const_servicename(snum));
4610         if (!W_ERROR_IS_OK(result)) {
4611                 return result;
4612         }
4613
4614         switch (r->in.level) {
4615         case 0:
4616                 result = construct_printer_info0(p->mem_ctx, ntprinter,
4617                                                  &r->out.info->info0, snum);
4618                 break;
4619         case 1:
4620                 result = construct_printer_info1(p->mem_ctx, ntprinter,
4621                                                  PRINTER_ENUM_ICON8,
4622                                                  &r->out.info->info1, snum);
4623                 break;
4624         case 2:
4625                 result = construct_printer_info2(p->mem_ctx, ntprinter,
4626                                                  &r->out.info->info2, snum);
4627                 break;
4628         case 3:
4629                 result = construct_printer_info3(p->mem_ctx, ntprinter,
4630                                                  &r->out.info->info3, snum);
4631                 break;
4632         case 4:
4633                 result = construct_printer_info4(p->mem_ctx, ntprinter,
4634                                                  &r->out.info->info4, snum);
4635                 break;
4636         case 5:
4637                 result = construct_printer_info5(p->mem_ctx, ntprinter,
4638                                                  &r->out.info->info5, snum);
4639                 break;
4640         case 6:
4641                 result = construct_printer_info6(p->mem_ctx, ntprinter,
4642                                                  &r->out.info->info6, snum);
4643                 break;
4644         case 7:
4645                 result = construct_printer_info7(p->mem_ctx, Printer,
4646                                                  &r->out.info->info7, snum);
4647                 break;
4648         case 8:
4649                 result = construct_printer_info8(p->mem_ctx, ntprinter,
4650                                                  &r->out.info->info8, snum);
4651                 break;
4652         default:
4653                 result = WERR_UNKNOWN_LEVEL;
4654                 break;
4655         }
4656
4657         free_a_printer(&ntprinter, 2);
4658
4659         if (!W_ERROR_IS_OK(result)) {
4660                 TALLOC_FREE(r->out.info);
4661                 return result;
4662         }
4663
4664         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4665                                                r->out.info, r->in.level);
4666         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4667
4668         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4669 }
4670
4671 /********************************************************************
4672  ********************************************************************/
4673
4674 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4675                                                   fstring *fstring_array,
4676                                                   const char *cservername)
4677 {
4678         int i, num_strings = 0;
4679         const char **array = NULL;
4680
4681         for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4682
4683                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4684                                                   cservername, fstring_array[i]);
4685                 if (!str) {
4686                         TALLOC_FREE(array);
4687                         return NULL;
4688                 }
4689
4690
4691                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4692                         TALLOC_FREE(array);
4693                         return NULL;
4694                 }
4695         }
4696
4697         if (i > 0) {
4698                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4699                              &array, &num_strings);
4700         }
4701
4702         return array;
4703 }
4704
4705 /********************************************************************
4706  * fill a spoolss_DriverInfo1 struct
4707  ********************************************************************/
4708
4709 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4710                                         struct spoolss_DriverInfo1 *r,
4711                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4712                                         const char *servername,
4713                                         const char *architecture)
4714 {
4715         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4716         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4717
4718         return WERR_OK;
4719 }
4720
4721 /********************************************************************
4722  * fill a spoolss_DriverInfo2 struct
4723  ********************************************************************/
4724
4725 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4726                                         struct spoolss_DriverInfo2 *r,
4727                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4728                                         const char *servername)
4729
4730 {
4731         const char *cservername = canon_servername(servername);
4732
4733         r->version              = driver->info_3->cversion;
4734
4735         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4736         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4737         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4738         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4739
4740         if (strlen(driver->info_3->driverpath)) {
4741                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4742                                 cservername, driver->info_3->driverpath);
4743         } else {
4744                 r->driver_path  = talloc_strdup(mem_ctx, "");
4745         }
4746         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4747
4748         if (strlen(driver->info_3->datafile)) {
4749                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4750                                 cservername, driver->info_3->datafile);
4751         } else {
4752                 r->data_file    = talloc_strdup(mem_ctx, "");
4753         }
4754         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4755
4756         if (strlen(driver->info_3->configfile)) {
4757                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4758                                 cservername, driver->info_3->configfile);
4759         } else {
4760                 r->config_file  = talloc_strdup(mem_ctx, "");
4761         }
4762         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4763
4764         return WERR_OK;
4765 }
4766
4767 /********************************************************************
4768  * fill a spoolss_DriverInfo3 struct
4769  ********************************************************************/
4770
4771 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4772                                         struct spoolss_DriverInfo3 *r,
4773                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4774                                         const char *servername)
4775 {
4776         const char *cservername = canon_servername(servername);
4777
4778         r->version              = driver->info_3->cversion;
4779
4780         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4781         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4782         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4783         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4784
4785         if (strlen(driver->info_3->driverpath)) {
4786                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4787                                 cservername, driver->info_3->driverpath);
4788         } else {
4789                 r->driver_path  = talloc_strdup(mem_ctx, "");
4790         }
4791         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4792
4793         if (strlen(driver->info_3->datafile)) {
4794                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4795                                 cservername, driver->info_3->datafile);
4796         } else {
4797                 r->data_file    = talloc_strdup(mem_ctx, "");
4798         }
4799         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4800
4801         if (strlen(driver->info_3->configfile)) {
4802                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4803                                 cservername, driver->info_3->configfile);
4804         } else {
4805                 r->config_file  = talloc_strdup(mem_ctx, "");
4806         }
4807         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4808
4809         if (strlen(driver->info_3->helpfile)) {
4810                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4811                                 cservername, driver->info_3->helpfile);
4812         } else {
4813                 r->help_file    = talloc_strdup(mem_ctx, "");
4814         }
4815         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4816
4817         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4818         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4819         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4820         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4821
4822         r->dependent_files = string_array_from_driver_info(mem_ctx,
4823                                                            driver->info_3->dependentfiles,
4824                                                            cservername);
4825         return WERR_OK;
4826 }
4827
4828 /********************************************************************
4829  * fill a spoolss_DriverInfo4 struct
4830  ********************************************************************/
4831
4832 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4833                                         struct spoolss_DriverInfo4 *r,
4834                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4835                                         const char *servername)
4836 {
4837         const char *cservername = canon_servername(servername);
4838
4839         r->version              = driver->info_3->cversion;
4840
4841         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4842         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4843         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4844         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4845
4846         if (strlen(driver->info_3->driverpath)) {
4847                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4848                                 cservername, driver->info_3->driverpath);
4849         } else {
4850                 r->driver_path  = talloc_strdup(mem_ctx, "");
4851         }
4852         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4853
4854         if (strlen(driver->info_3->datafile)) {
4855                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4856                                 cservername, driver->info_3->datafile);
4857         } else {
4858                 r->data_file    = talloc_strdup(mem_ctx, "");
4859         }
4860         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4861
4862         if (strlen(driver->info_3->configfile)) {
4863                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4864                                 cservername, driver->info_3->configfile);
4865         } else {
4866                 r->config_file  = talloc_strdup(mem_ctx, "");
4867         }
4868         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4869
4870         if (strlen(driver->info_3->helpfile)) {
4871                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4872                                 cservername, driver->info_3->helpfile);
4873         } else {
4874                 r->help_file    = talloc_strdup(mem_ctx, "");
4875         }
4876         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4877
4878         r->dependent_files = string_array_from_driver_info(mem_ctx,
4879                                                            driver->info_3->dependentfiles,
4880                                                            cservername);
4881
4882
4883         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4884         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4885         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4886         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4887
4888         r->previous_names = string_array_from_driver_info(mem_ctx,
4889                                                           NULL,
4890                                                           cservername);
4891
4892         return WERR_OK;
4893 }
4894
4895 /********************************************************************
4896  * fill a spoolss_DriverInfo5 struct
4897  ********************************************************************/
4898
4899 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4900                                         struct spoolss_DriverInfo5 *r,
4901                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4902                                         const char *servername)
4903 {
4904         const char *cservername = canon_servername(servername);
4905
4906         r->version              = driver->info_3->cversion;
4907
4908         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4909         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4910         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4911         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4912
4913         if (strlen(driver->info_3->driverpath)) {
4914                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4915                                 cservername, driver->info_3->driverpath);
4916         } else {
4917                 r->driver_path  = talloc_strdup(mem_ctx, "");
4918         }
4919         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4920
4921         if (strlen(driver->info_3->datafile)) {
4922                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4923                                 cservername, driver->info_3->datafile);
4924         } else {
4925                 r->data_file    = talloc_strdup(mem_ctx, "");
4926         }
4927         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4928
4929         if (strlen(driver->info_3->configfile)) {
4930                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4931                                 cservername, driver->info_3->configfile);
4932         } else {
4933                 r->config_file  = talloc_strdup(mem_ctx, "");
4934         }
4935         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4936
4937         r->driver_attributes    = 0;
4938         r->config_version       = 0;
4939         r->driver_version       = 0;
4940
4941         return WERR_OK;
4942 }
4943 /********************************************************************
4944  * fill a spoolss_DriverInfo6 struct
4945  ********************************************************************/
4946
4947 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4948                                         struct spoolss_DriverInfo6 *r,
4949                                         const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4950                                         const char *servername)
4951 {
4952         const char *cservername = canon_servername(servername);
4953
4954         r->version              = driver->info_3->cversion;
4955
4956         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
4957         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4958         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
4959         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4960
4961         if (strlen(driver->info_3->driverpath)) {
4962                 r->driver_path  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4963                                 cservername, driver->info_3->driverpath);
4964         } else {
4965                 r->driver_path  = talloc_strdup(mem_ctx, "");
4966         }
4967         W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4968
4969         if (strlen(driver->info_3->datafile)) {
4970                 r->data_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4971                                 cservername, driver->info_3->datafile);
4972         } else {
4973                 r->data_file    = talloc_strdup(mem_ctx, "");
4974         }
4975         W_ERROR_HAVE_NO_MEMORY(r->data_file);
4976
4977         if (strlen(driver->info_3->configfile)) {
4978                 r->config_file  = talloc_asprintf(mem_ctx, "\\\\%s%s",
4979                                 cservername, driver->info_3->configfile);
4980         } else {
4981                 r->config_file  = talloc_strdup(mem_ctx, "");
4982         }
4983         W_ERROR_HAVE_NO_MEMORY(r->config_file);
4984
4985         if (strlen(driver->info_3->helpfile)) {
4986                 r->help_file    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4987                                 cservername, driver->info_3->helpfile);
4988         } else {
4989                 r->help_file    = talloc_strdup(mem_ctx, "");
4990         }
4991         W_ERROR_HAVE_NO_MEMORY(r->help_file);
4992
4993         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4994         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4995         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4996         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4997
4998         r->dependent_files = string_array_from_driver_info(mem_ctx,
4999                                                            driver->info_3->dependentfiles,
5000                                                            cservername);
5001         r->previous_names = string_array_from_driver_info(mem_ctx,
5002                                                           NULL,
5003                                                           cservername);
5004
5005         r->driver_date          = 0;
5006         r->driver_version       = 0;
5007
5008         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5009         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5010         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5011         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5012         r->hardware_id          = talloc_strdup(mem_ctx, "");
5013         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5014         r->provider             = talloc_strdup(mem_ctx, "");
5015         W_ERROR_HAVE_NO_MEMORY(r->provider);
5016
5017         return WERR_OK;
5018 }
5019
5020 /********************************************************************
5021  ********************************************************************/
5022
5023 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5024                                           struct spoolss_DriverFileInfo *r,
5025                                           const char *cservername,
5026                                           const char *file_name,
5027                                           enum spoolss_DriverFileType file_type,
5028                                           uint32_t file_version)
5029 {
5030         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5031                                           cservername, file_name);
5032         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5033         r->file_type    = file_type;
5034         r->file_version = file_version;
5035
5036         return WERR_OK;
5037 }
5038
5039 /********************************************************************
5040  ********************************************************************/
5041
5042 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5043                                                  const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5044                                                  const char *cservername,
5045                                                  struct spoolss_DriverFileInfo **info_p,
5046                                                  uint32_t *count_p)
5047 {
5048         struct spoolss_DriverFileInfo *info = NULL;
5049         uint32_t count = 0;
5050         WERROR result;
5051         uint32_t i;
5052
5053         *info_p = NULL;
5054         *count_p = 0;
5055
5056         if (strlen(driver->info_3->driverpath)) {
5057                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5058                                             struct spoolss_DriverFileInfo,
5059                                             count + 1);
5060                 W_ERROR_HAVE_NO_MEMORY(info);
5061                 result = fill_spoolss_DriverFileInfo(info,
5062                                                      &info[count],
5063                                                      cservername,
5064                                                      driver->info_3->driverpath,
5065                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5066                                                      0);
5067                 W_ERROR_NOT_OK_RETURN(result);
5068                 count++;
5069         }
5070
5071         if (strlen(driver->info_3->configfile)) {
5072                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5073                                             struct spoolss_DriverFileInfo,
5074                                             count + 1);
5075                 W_ERROR_HAVE_NO_MEMORY(info);
5076                 result = fill_spoolss_DriverFileInfo(info,
5077                                                      &info[count],
5078                                                      cservername,
5079                                                      driver->info_3->configfile,
5080                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5081                                                      0);
5082                 W_ERROR_NOT_OK_RETURN(result);
5083                 count++;
5084         }
5085
5086         if (strlen(driver->info_3->datafile)) {
5087                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5088                                             struct spoolss_DriverFileInfo,
5089                                             count + 1);
5090                 W_ERROR_HAVE_NO_MEMORY(info);
5091                 result = fill_spoolss_DriverFileInfo(info,
5092                                                      &info[count],
5093                                                      cservername,
5094                                                      driver->info_3->datafile,
5095                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5096                                                      0);
5097                 W_ERROR_NOT_OK_RETURN(result);
5098                 count++;
5099         }
5100
5101         if (strlen(driver->info_3->helpfile)) {
5102                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5103                                             struct spoolss_DriverFileInfo,
5104                                             count + 1);
5105                 W_ERROR_HAVE_NO_MEMORY(info);
5106                 result = fill_spoolss_DriverFileInfo(info,
5107                                                      &info[count],
5108                                                      cservername,
5109                                                      driver->info_3->helpfile,
5110                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5111                                                      0);
5112                 W_ERROR_NOT_OK_RETURN(result);
5113                 count++;
5114         }
5115
5116         for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5117                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5118                                             struct spoolss_DriverFileInfo,
5119                                             count + 1);
5120                 W_ERROR_HAVE_NO_MEMORY(info);
5121                 result = fill_spoolss_DriverFileInfo(info,
5122                                                      &info[count],
5123                                                      cservername,
5124                                                      driver->info_3->dependentfiles[i],
5125                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5126                                                      0);
5127                 W_ERROR_NOT_OK_RETURN(result);
5128                 count++;
5129         }
5130
5131         *info_p = info;
5132         *count_p = count;
5133
5134         return WERR_OK;
5135 }
5136
5137 /********************************************************************
5138  * fill a spoolss_DriverInfo101 sttruct
5139  ********************************************************************/
5140
5141 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5142                                           struct spoolss_DriverInfo101 *r,
5143                                           const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5144                                           const char *servername)
5145 {
5146         const char *cservername = canon_servername(servername);
5147         WERROR result;
5148
5149         r->version              = driver->info_3->cversion;
5150
5151         r->driver_name          = talloc_strdup(mem_ctx, driver->info_3->name);
5152         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5153         r->architecture         = talloc_strdup(mem_ctx, driver->info_3->environment);
5154         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5155
5156         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5157                                                     cservername,
5158                                                     &r->file_info,
5159                                                     &r->file_count);
5160         if (!W_ERROR_IS_OK(result)) {
5161                 return result;
5162         }
5163
5164         r->monitor_name         = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5165         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5166
5167         r->default_datatype     = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5168         W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5169
5170         r->previous_names = string_array_from_driver_info(mem_ctx,
5171                                                           NULL,
5172                                                           cservername);
5173         r->driver_date          = 0;
5174         r->driver_version       = 0;
5175
5176         r->manufacturer_name    = talloc_strdup(mem_ctx, "");
5177         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5178         r->manufacturer_url     = talloc_strdup(mem_ctx, "");
5179         W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5180         r->hardware_id          = talloc_strdup(mem_ctx, "");
5181         W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5182         r->provider             = talloc_strdup(mem_ctx, "");
5183         W_ERROR_HAVE_NO_MEMORY(r->provider);
5184
5185         return WERR_OK;
5186 }
5187
5188 /********************************************************************
5189  * construct_printer_driver_info_1
5190  ********************************************************************/
5191
5192 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5193                                               struct spoolss_DriverInfo1 *r,
5194                                               int snum,
5195                                               const char *servername,
5196                                               const char *architecture,
5197                                               uint32_t version)
5198 {
5199         NT_PRINTER_INFO_LEVEL *printer = NULL;
5200         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5201         WERROR result;
5202
5203         ZERO_STRUCT(driver);
5204
5205         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5206                 return WERR_INVALID_PRINTER_NAME;
5207
5208         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5209                 free_a_printer(&printer, 2);
5210                 return WERR_UNKNOWN_PRINTER_DRIVER;
5211         }
5212
5213         result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5214
5215         free_a_printer(&printer,2);
5216
5217         return result;
5218 }
5219
5220 /********************************************************************
5221  * construct_printer_driver_info_2
5222  * fill a printer_info_2 struct
5223  ********************************************************************/
5224
5225 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5226                                               struct spoolss_DriverInfo2 *r,
5227                                               int snum,
5228                                               const char *servername,
5229                                               const char *architecture,
5230                                               uint32_t version)
5231 {
5232         NT_PRINTER_INFO_LEVEL *printer = NULL;
5233         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5234         WERROR result;
5235
5236         ZERO_STRUCT(printer);
5237         ZERO_STRUCT(driver);
5238
5239         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5240                 return WERR_INVALID_PRINTER_NAME;
5241
5242         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5243                 free_a_printer(&printer, 2);
5244                 return WERR_UNKNOWN_PRINTER_DRIVER;
5245         }
5246
5247         result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5248
5249         free_a_printer(&printer,2);
5250
5251         return result;
5252 }
5253
5254 /********************************************************************
5255  * construct_printer_info_3
5256  * fill a printer_info_3 struct
5257  ********************************************************************/
5258
5259 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5260                                               struct spoolss_DriverInfo3 *r,
5261                                               int snum,
5262                                               const char *servername,
5263                                               const char *architecture,
5264                                               uint32_t version)
5265 {
5266         NT_PRINTER_INFO_LEVEL *printer = NULL;
5267         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5268         WERROR status;
5269         ZERO_STRUCT(driver);
5270
5271         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5272         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5273         if (!W_ERROR_IS_OK(status))
5274                 return WERR_INVALID_PRINTER_NAME;
5275
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 #if 0   /* JERRY */
5280
5281         /*
5282          * I put this code in during testing.  Helpful when commenting out the
5283          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5284          * as win2k always queries the driver using an infor level of 6.
5285          * I've left it in (but ifdef'd out) because I'll probably
5286          * use it in experimentation again in the future.   --jerry 22/01/2002
5287          */
5288
5289         if (!W_ERROR_IS_OK(status)) {
5290                 /*
5291                  * Is this a W2k client ?
5292                  */
5293                 if (version == 3) {
5294                         /* Yes - try again with a WinNT driver. */
5295                         version = 2;
5296                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5297                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5298                 }
5299 #endif
5300
5301                 if (!W_ERROR_IS_OK(status)) {
5302                         free_a_printer(&printer,2);
5303                         return WERR_UNKNOWN_PRINTER_DRIVER;
5304                 }
5305
5306 #if 0   /* JERRY */
5307         }
5308 #endif
5309
5310
5311         status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5312
5313         free_a_printer(&printer,2);
5314
5315         return status;
5316 }
5317
5318 /********************************************************************
5319  * construct_printer_info_6
5320  * fill a printer_info_6 struct
5321  ********************************************************************/
5322
5323 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5324                                               struct spoolss_DriverInfo6 *r,
5325                                               int snum,
5326                                               const char *servername,
5327                                               const char *architecture,
5328                                               uint32_t version)
5329 {
5330         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5331         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5332         WERROR                          status;
5333
5334         ZERO_STRUCT(driver);
5335
5336         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5337
5338         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5339
5340         if (!W_ERROR_IS_OK(status))
5341                 return WERR_INVALID_PRINTER_NAME;
5342
5343         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5344
5345         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5346
5347         if (!W_ERROR_IS_OK(status))
5348         {
5349                 /*
5350                  * Is this a W2k client ?
5351                  */
5352
5353                 if (version < 3) {
5354                         free_a_printer(&printer,2);
5355                         return WERR_UNKNOWN_PRINTER_DRIVER;
5356                 }
5357
5358                 /* Yes - try again with a WinNT driver. */
5359                 version = 2;
5360                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5361                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5362                 if (!W_ERROR_IS_OK(status)) {
5363                         free_a_printer(&printer,2);
5364                         return WERR_UNKNOWN_PRINTER_DRIVER;
5365                 }
5366         }
5367
5368         status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5369
5370         free_a_printer(&printer,2);
5371         free_a_printer_driver(driver, 3);
5372
5373         return status;
5374 }
5375
5376 /********************************************************************
5377  * construct_printer_info_101
5378  * fill a printer_info_101 struct
5379  ********************************************************************/
5380
5381 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5382                                                 struct spoolss_DriverInfo101 *r,
5383                                                 int snum,
5384                                                 const char *servername,
5385                                                 const char *architecture,
5386                                                 uint32_t version)
5387 {
5388         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5389         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5390         WERROR                          result;
5391
5392         ZERO_STRUCT(driver);
5393
5394         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5395
5396         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5397                 win_errstr(result)));
5398
5399         if (!W_ERROR_IS_OK(result)) {
5400                 return WERR_INVALID_PRINTER_NAME;
5401         }
5402
5403         result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5404                                       architecture, version);
5405
5406         DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5407                 win_errstr(result)));
5408
5409         if (!W_ERROR_IS_OK(result)) {
5410                 /*
5411                  * Is this a W2k client ?
5412                  */
5413
5414                 if (version < 3) {
5415                         free_a_printer(&printer, 2);
5416                         return WERR_UNKNOWN_PRINTER_DRIVER;
5417                 }
5418
5419                 /* Yes - try again with a WinNT driver. */
5420                 version = 2;
5421                 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5422                                               architecture, version);
5423                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5424                         win_errstr(result)));
5425                 if (!W_ERROR_IS_OK(result)) {
5426                         free_a_printer(&printer, 2);
5427                         return WERR_UNKNOWN_PRINTER_DRIVER;
5428                 }
5429         }
5430
5431         result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5432
5433         free_a_printer(&printer, 2);
5434         free_a_printer_driver(driver, 3);
5435
5436         return result;
5437 }
5438
5439 /****************************************************************
5440  _spoolss_GetPrinterDriver2
5441 ****************************************************************/
5442
5443 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5444                                   struct spoolss_GetPrinterDriver2 *r)
5445 {
5446         Printer_entry *printer;
5447         WERROR result;
5448
5449         const char *servername;
5450         int snum;
5451
5452         /* that's an [in out] buffer */
5453
5454         if (!r->in.buffer && (r->in.offered != 0)) {
5455                 return WERR_INVALID_PARAM;
5456         }
5457
5458         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5459
5460         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5461                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5462                 return WERR_INVALID_PRINTER_NAME;
5463         }
5464
5465         *r->out.needed = 0;
5466         *r->out.server_major_version = 0;
5467         *r->out.server_minor_version = 0;
5468
5469         servername = get_server_name(printer);
5470
5471         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5472                 return WERR_BADFID;
5473         }
5474
5475         switch (r->in.level) {
5476         case 1:
5477                 result = construct_printer_driver_info_1(p->mem_ctx,
5478                                                          &r->out.info->info1,
5479                                                          snum,
5480                                                          servername,
5481                                                          r->in.architecture,
5482                                                          r->in.client_major_version);
5483                 break;
5484         case 2:
5485                 result = construct_printer_driver_info_2(p->mem_ctx,
5486                                                          &r->out.info->info2,
5487                                                          snum,
5488                                                          servername,
5489                                                          r->in.architecture,
5490                                                          r->in.client_major_version);
5491                 break;
5492         case 3:
5493                 result = construct_printer_driver_info_3(p->mem_ctx,
5494                                                          &r->out.info->info3,
5495                                                          snum,
5496                                                          servername,
5497                                                          r->in.architecture,
5498                                                          r->in.client_major_version);
5499                 break;
5500         case 6:
5501                 result = construct_printer_driver_info_6(p->mem_ctx,
5502                                                          &r->out.info->info6,
5503                                                          snum,
5504                                                          servername,
5505                                                          r->in.architecture,
5506                                                          r->in.client_major_version);
5507                 break;
5508         case 101:
5509                 result = construct_printer_driver_info_101(p->mem_ctx,
5510                                                            &r->out.info->info101,
5511                                                            snum,
5512                                                            servername,
5513                                                            r->in.architecture,
5514                                                            r->in.client_major_version);
5515                 break;
5516         default:
5517                 result = WERR_UNKNOWN_LEVEL;
5518                 break;
5519         }
5520
5521         if (!W_ERROR_IS_OK(result)) {
5522                 TALLOC_FREE(r->out.info);
5523                 return result;
5524         }
5525
5526         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5527                                                r->out.info, r->in.level);
5528         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5529
5530         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5531 }
5532
5533
5534 /****************************************************************
5535  _spoolss_StartPagePrinter
5536 ****************************************************************/
5537
5538 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5539                                  struct spoolss_StartPagePrinter *r)
5540 {
5541         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5542
5543         if (!Printer) {
5544                 DEBUG(3,("_spoolss_StartPagePrinter: "
5545                         "Error in startpageprinter printer handle\n"));
5546                 return WERR_BADFID;
5547         }
5548
5549         Printer->page_started = true;
5550         return WERR_OK;
5551 }
5552
5553 /****************************************************************
5554  _spoolss_EndPagePrinter
5555 ****************************************************************/
5556
5557 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5558                                struct spoolss_EndPagePrinter *r)
5559 {
5560         int snum;
5561
5562         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5563
5564         if (!Printer) {
5565                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5566                         OUR_HANDLE(r->in.handle)));
5567                 return WERR_BADFID;
5568         }
5569
5570         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5571                 return WERR_BADFID;
5572
5573         Printer->page_started = false;
5574         print_job_endpage(snum, Printer->jobid);
5575
5576         return WERR_OK;
5577 }
5578
5579 /****************************************************************
5580  _spoolss_StartDocPrinter
5581 ****************************************************************/
5582
5583 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5584                                 struct spoolss_StartDocPrinter *r)
5585 {
5586         struct spoolss_DocumentInfo1 *info_1;
5587         int snum;
5588         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5589
5590         if (!Printer) {
5591                 DEBUG(2,("_spoolss_StartDocPrinter: "
5592                         "Invalid handle (%s:%u:%u)\n",
5593                         OUR_HANDLE(r->in.handle)));
5594                 return WERR_BADFID;
5595         }
5596
5597         if (r->in.level != 1) {
5598                 return WERR_UNKNOWN_LEVEL;
5599         }
5600
5601         info_1 = r->in.info.info1;
5602
5603         /*
5604          * a nice thing with NT is it doesn't listen to what you tell it.
5605          * when asked to send _only_ RAW datas, it tries to send datas
5606          * in EMF format.
5607          *
5608          * So I add checks like in NT Server ...
5609          */
5610
5611         if (info_1->datatype) {
5612                 if (strcmp(info_1->datatype, "RAW") != 0) {
5613                         *r->out.job_id = 0;
5614                         return WERR_INVALID_DATATYPE;
5615                 }
5616         }
5617
5618         /* get the share number of the printer */
5619         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5620                 return WERR_BADFID;
5621         }
5622
5623         Printer->jobid = print_job_start(p->server_info, snum,
5624                                          info_1->document_name,
5625                                          Printer->nt_devmode);
5626
5627         /* An error occured in print_job_start() so return an appropriate
5628            NT error code. */
5629
5630         if (Printer->jobid == -1) {
5631                 return map_werror_from_unix(errno);
5632         }
5633
5634         Printer->document_started = true;
5635         *r->out.job_id = Printer->jobid;
5636
5637         return WERR_OK;
5638 }
5639
5640 /****************************************************************
5641  _spoolss_EndDocPrinter
5642 ****************************************************************/
5643
5644 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5645                               struct spoolss_EndDocPrinter *r)
5646 {
5647         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5648         int snum;
5649
5650         if (!Printer) {
5651                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5652                         OUR_HANDLE(r->in.handle)));
5653                 return WERR_BADFID;
5654         }
5655
5656         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5657                 return WERR_BADFID;
5658         }
5659
5660         Printer->document_started = false;
5661         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5662         /* error codes unhandled so far ... */
5663
5664         return WERR_OK;
5665 }
5666
5667 /****************************************************************
5668  _spoolss_WritePrinter
5669 ****************************************************************/
5670
5671 WERROR _spoolss_WritePrinter(pipes_struct *p,
5672                              struct spoolss_WritePrinter *r)
5673 {
5674         uint32_t buffer_written;
5675         int snum;
5676         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5677
5678         if (!Printer) {
5679                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5680                         OUR_HANDLE(r->in.handle)));
5681                 *r->out.num_written = r->in._data_size;
5682                 return WERR_BADFID;
5683         }
5684
5685         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5686                 return WERR_BADFID;
5687
5688         buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5689                                                    (const char *)r->in.data.data,
5690                                                    (SMB_OFF_T)-1,
5691                                                    (size_t)r->in._data_size);
5692         if (buffer_written == (uint32_t)-1) {
5693                 *r->out.num_written = 0;
5694                 if (errno == ENOSPC)
5695                         return WERR_NO_SPOOL_SPACE;
5696                 else
5697                         return WERR_ACCESS_DENIED;
5698         }
5699
5700         *r->out.num_written = r->in._data_size;
5701
5702         return WERR_OK;
5703 }
5704
5705 /********************************************************************
5706  * api_spoolss_getprinter
5707  * called from the spoolss dispatcher
5708  *
5709  ********************************************************************/
5710
5711 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5712                               pipes_struct *p)
5713 {
5714         int snum;
5715         WERROR errcode = WERR_BADFUNC;
5716         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5717
5718         if (!Printer) {
5719                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5720                         OUR_HANDLE(handle)));
5721                 return WERR_BADFID;
5722         }
5723
5724         if (!get_printer_snum(p, handle, &snum, NULL))
5725                 return WERR_BADFID;
5726
5727         switch (command) {
5728         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5729                 errcode = print_queue_pause(p->server_info, snum);
5730                 break;
5731         case SPOOLSS_PRINTER_CONTROL_RESUME:
5732         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5733                 errcode = print_queue_resume(p->server_info, snum);
5734                 break;
5735         case SPOOLSS_PRINTER_CONTROL_PURGE:
5736                 errcode = print_queue_purge(p->server_info, snum);
5737                 break;
5738         default:
5739                 return WERR_UNKNOWN_LEVEL;
5740         }
5741
5742         return errcode;
5743 }
5744
5745
5746 /****************************************************************
5747  _spoolss_AbortPrinter
5748  * From MSDN: "Deletes printer's spool file if printer is configured
5749  * for spooling"
5750 ****************************************************************/
5751
5752 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5753                              struct spoolss_AbortPrinter *r)
5754 {
5755         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5756         int             snum;
5757         WERROR          errcode = WERR_OK;
5758
5759         if (!Printer) {
5760                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5761                         OUR_HANDLE(r->in.handle)));
5762                 return WERR_BADFID;
5763         }
5764
5765         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5766                 return WERR_BADFID;
5767
5768         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5769
5770         return errcode;
5771 }
5772
5773 /********************************************************************
5774  * called by spoolss_api_setprinter
5775  * when updating a printer description
5776  ********************************************************************/
5777
5778 static WERROR update_printer_sec(struct policy_handle *handle,
5779                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5780 {
5781         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5782         WERROR result;
5783         int snum;
5784
5785         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5786
5787         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5788                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5789                          OUR_HANDLE(handle)));
5790
5791                 result = WERR_BADFID;
5792                 goto done;
5793         }
5794
5795         if (!secdesc_ctr) {
5796                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5797                 result = WERR_INVALID_PARAM;
5798                 goto done;
5799         }
5800
5801         /* Check the user has permissions to change the security
5802            descriptor.  By experimentation with two NT machines, the user
5803            requires Full Access to the printer to change security
5804            information. */
5805
5806         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5807                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5808                 result = WERR_ACCESS_DENIED;
5809                 goto done;
5810         }
5811
5812         /* NT seems to like setting the security descriptor even though
5813            nothing may have actually changed. */
5814
5815         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5816                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5817                 result = WERR_BADFID;
5818                 goto done;
5819         }
5820
5821         if (DEBUGLEVEL >= 10) {
5822                 SEC_ACL *the_acl;
5823                 int i;
5824
5825                 the_acl = old_secdesc_ctr->sd->dacl;
5826                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5827                            PRINTERNAME(snum), the_acl->num_aces));
5828
5829                 for (i = 0; i < the_acl->num_aces; i++) {
5830                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5831                                            &the_acl->aces[i].trustee),
5832                                   the_acl->aces[i].access_mask));
5833                 }
5834
5835                 the_acl = secdesc_ctr->sd->dacl;
5836
5837                 if (the_acl) {
5838                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5839                                    PRINTERNAME(snum), the_acl->num_aces));
5840
5841                         for (i = 0; i < the_acl->num_aces; i++) {
5842                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5843                                                    &the_acl->aces[i].trustee),
5844                                            the_acl->aces[i].access_mask));
5845                         }
5846                 } else {
5847                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5848                 }
5849         }
5850
5851         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5852         if (!new_secdesc_ctr) {
5853                 result = WERR_NOMEM;
5854                 goto done;
5855         }
5856
5857         if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5858                 result = WERR_OK;
5859                 goto done;
5860         }
5861
5862         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5863
5864  done:
5865
5866         return result;
5867 }
5868
5869 /********************************************************************
5870  Canonicalize printer info from a client
5871
5872  ATTN: It does not matter what we set the servername to hear
5873  since we do the necessary work in get_a_printer() to set it to
5874  the correct value based on what the client sent in the
5875  _spoolss_open_printer_ex().
5876  ********************************************************************/
5877
5878 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5879 {
5880         fstring printername;
5881         const char *p;
5882
5883         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5884                 "portname=%s drivername=%s comment=%s location=%s\n",
5885                 info->servername, info->printername, info->sharename,
5886                 info->portname, info->drivername, info->comment, info->location));
5887
5888         /* we force some elements to "correct" values */
5889         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5890         fstrcpy(info->sharename, lp_servicename(snum));
5891
5892         /* check to see if we allow printername != sharename */
5893
5894         if ( lp_force_printername(snum) ) {
5895                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5896                         global_myname(), info->sharename );
5897         } else {
5898
5899                 /* make sure printername is in \\server\printername format */
5900
5901                 fstrcpy( printername, info->printername );
5902                 p = printername;
5903                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5904                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5905                                 p++;
5906                 }
5907
5908                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5909                          global_myname(), p );
5910         }
5911
5912         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5913         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5914
5915
5916
5917         return true;
5918 }
5919
5920 /****************************************************************************
5921 ****************************************************************************/
5922
5923 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
5924 {
5925         char *cmd = lp_addport_cmd();
5926         char *command = NULL;
5927         int ret;
5928         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5929         bool is_print_op = false;
5930
5931         if ( !*cmd ) {
5932                 return WERR_ACCESS_DENIED;
5933         }
5934
5935         command = talloc_asprintf(ctx,
5936                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5937         if (!command) {
5938                 return WERR_NOMEM;
5939         }
5940
5941         if ( token )
5942                 is_print_op = user_has_privileges( token, &se_printop );
5943
5944         DEBUG(10,("Running [%s]\n", command));
5945
5946         /********* BEGIN SePrintOperatorPrivilege **********/
5947
5948         if ( is_print_op )
5949                 become_root();
5950
5951         ret = smbrun(command, NULL);
5952
5953         if ( is_print_op )
5954                 unbecome_root();
5955
5956         /********* END SePrintOperatorPrivilege **********/
5957
5958         DEBUGADD(10,("returned [%d]\n", ret));
5959
5960         TALLOC_FREE(command);
5961
5962         if ( ret != 0 ) {
5963                 return WERR_ACCESS_DENIED;
5964         }
5965
5966         return WERR_OK;
5967 }
5968
5969 /****************************************************************************
5970 ****************************************************************************/
5971
5972 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5973 {
5974         char *cmd = lp_addprinter_cmd();
5975         char **qlines;
5976         char *command = NULL;
5977         int numlines;
5978         int ret;
5979         int fd;
5980         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5981         bool is_print_op = false;
5982         char *remote_machine = talloc_strdup(ctx, "%m");
5983
5984         if (!remote_machine) {
5985                 return false;
5986         }
5987         remote_machine = talloc_sub_basic(ctx,
5988                                 current_user_info.smb_name,
5989                                 current_user_info.domain,
5990                                 remote_machine);
5991         if (!remote_machine) {
5992                 return false;
5993         }
5994
5995         command = talloc_asprintf(ctx,
5996                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5997                         cmd, printer->info_2->printername, printer->info_2->sharename,
5998                         printer->info_2->portname, printer->info_2->drivername,
5999                         printer->info_2->location, printer->info_2->comment, remote_machine);
6000         if (!command) {
6001                 return false;
6002         }
6003
6004         if ( token )
6005                 is_print_op = user_has_privileges( token, &se_printop );
6006
6007         DEBUG(10,("Running [%s]\n", command));
6008
6009         /********* BEGIN SePrintOperatorPrivilege **********/
6010
6011         if ( is_print_op )
6012                 become_root();
6013
6014         if ( (ret = smbrun(command, &fd)) == 0 ) {
6015                 /* Tell everyone we updated smb.conf. */
6016                 message_send_all(smbd_messaging_context(),
6017                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6018         }
6019
6020         if ( is_print_op )
6021                 unbecome_root();
6022
6023         /********* END SePrintOperatorPrivilege **********/
6024
6025         DEBUGADD(10,("returned [%d]\n", ret));
6026
6027         TALLOC_FREE(command);
6028         TALLOC_FREE(remote_machine);
6029
6030         if ( ret != 0 ) {
6031                 if (fd != -1)
6032                         close(fd);
6033                 return false;
6034         }
6035
6036         /* reload our services immediately */
6037         reload_services(false);
6038
6039         numlines = 0;
6040         /* Get lines and convert them back to dos-codepage */
6041         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6042         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6043         close(fd);
6044
6045         /* Set the portname to what the script says the portname should be. */
6046         /* but don't require anything to be return from the script exit a good error code */
6047
6048         if (numlines) {
6049                 /* Set the portname to what the script says the portname should be. */
6050                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6051                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6052         }
6053
6054         TALLOC_FREE(qlines);
6055         return true;
6056 }
6057
6058
6059 /********************************************************************
6060  * Called by spoolss_api_setprinter
6061  * when updating a printer description.
6062  ********************************************************************/
6063
6064 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6065                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6066                              struct spoolss_DeviceMode *devmode)
6067 {
6068         int snum;
6069         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6070         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6071         WERROR result;
6072         UNISTR2 buffer;
6073         fstring asc_buffer;
6074
6075         DEBUG(8,("update_printer\n"));
6076
6077         result = WERR_OK;
6078
6079         if (!Printer) {
6080                 result = WERR_BADFID;
6081                 goto done;
6082         }
6083
6084         if (!get_printer_snum(p, handle, &snum, NULL)) {
6085                 result = WERR_BADFID;
6086                 goto done;
6087         }
6088
6089         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6090             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6091                 result = WERR_BADFID;
6092                 goto done;
6093         }
6094
6095         DEBUGADD(8,("Converting info_2 struct\n"));
6096
6097         /*
6098          * convert_printer_info converts the incoming
6099          * info from the client and overwrites the info
6100          * just read from the tdb in the pointer 'printer'.
6101          */
6102
6103         if (!convert_printer_info(info_ctr, printer)) {
6104                 result =  WERR_NOMEM;
6105                 goto done;
6106         }
6107
6108         if (devmode) {
6109                 /* we have a valid devmode
6110                    convert it and link it*/
6111
6112                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6113                 if (!convert_devicemode(printer->info_2->printername, devmode,
6114                                         &printer->info_2->devmode)) {
6115                         result =  WERR_NOMEM;
6116                         goto done;
6117                 }
6118         }
6119
6120         /* Do sanity check on the requested changes for Samba */
6121
6122         if (!check_printer_ok(printer->info_2, snum)) {
6123                 result = WERR_INVALID_PARAM;
6124                 goto done;
6125         }
6126
6127         /* FIXME!!! If the driver has changed we really should verify that
6128            it is installed before doing much else   --jerry */
6129
6130         /* Check calling user has permission to update printer description */
6131
6132         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6133                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6134                 result = WERR_ACCESS_DENIED;
6135                 goto done;
6136         }
6137
6138         /* Call addprinter hook */
6139         /* Check changes to see if this is really needed */
6140
6141         if ( *lp_addprinter_cmd()
6142                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6143                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6144                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6145                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6146         {
6147                 /* add_printer_hook() will call reload_services() */
6148
6149                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6150                                        printer) ) {
6151                         result = WERR_ACCESS_DENIED;
6152                         goto done;
6153                 }
6154         }
6155
6156         /*
6157          * When a *new* driver is bound to a printer, the drivername is used to
6158          * lookup previously saved driver initialization info, which is then
6159          * bound to the printer, simulating what happens in the Windows arch.
6160          */
6161         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6162         {
6163                 if (!set_driver_init(printer, 2))
6164                 {
6165                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6166                                 printer->info_2->drivername));
6167                 }
6168
6169                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6170                         printer->info_2->drivername));
6171
6172                 notify_printer_driver(snum, printer->info_2->drivername);
6173         }
6174
6175         /*
6176          * flag which changes actually occured.  This is a small subset of
6177          * all the possible changes.  We also have to update things in the
6178          * DsSpooler key.
6179          */
6180
6181         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6182                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6183                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6184                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6185
6186                 notify_printer_comment(snum, printer->info_2->comment);
6187         }
6188
6189         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6190                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6191                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6192                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6193
6194                 notify_printer_sharename(snum, printer->info_2->sharename);
6195         }
6196
6197         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6198                 char *pname;
6199
6200                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6201                         pname++;
6202                 else
6203                         pname = printer->info_2->printername;
6204
6205
6206                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6207                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6208                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6209
6210                 notify_printer_printername( snum, pname );
6211         }
6212
6213         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6214                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6215                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6216                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6217
6218                 notify_printer_port(snum, printer->info_2->portname);
6219         }
6220
6221         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6222                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6223                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6224                         REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6225
6226                 notify_printer_location(snum, printer->info_2->location);
6227         }
6228
6229         /* here we need to update some more DsSpooler keys */
6230         /* uNCName, serverName, shortServerName */
6231
6232         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6233         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6234                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6235         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6236                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6237
6238         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6239                  global_myname(), printer->info_2->sharename );
6240         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6241         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6242                 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6243
6244         /* Update printer info */
6245         result = mod_a_printer(printer, 2);
6246
6247 done:
6248         free_a_printer(&printer, 2);
6249         free_a_printer(&old_printer, 2);
6250
6251
6252         return result;
6253 }
6254
6255 /****************************************************************************
6256 ****************************************************************************/
6257 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6258                                            struct policy_handle *handle,
6259                                            struct spoolss_SetPrinterInfo7 *info7)
6260 {
6261 #ifdef HAVE_ADS
6262         int snum;
6263         Printer_entry *Printer;
6264
6265         if ( lp_security() != SEC_ADS ) {
6266                 return WERR_UNKNOWN_LEVEL;
6267         }
6268
6269         Printer = find_printer_index_by_hnd(p, handle);
6270
6271         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6272
6273         if (!Printer)
6274                 return WERR_BADFID;
6275
6276         if (!get_printer_snum(p, handle, &snum, NULL))
6277                 return WERR_BADFID;
6278
6279         nt_printer_publish(Printer, snum, info7->action);
6280
6281         return WERR_OK;
6282 #else
6283         return WERR_UNKNOWN_LEVEL;
6284 #endif
6285 }
6286
6287 /****************************************************************
6288  _spoolss_SetPrinter
6289 ****************************************************************/
6290
6291 WERROR _spoolss_SetPrinter(pipes_struct *p,
6292                            struct spoolss_SetPrinter *r)
6293 {
6294         WERROR result;
6295
6296         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6297
6298         if (!Printer) {
6299                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6300                         OUR_HANDLE(r->in.handle)));
6301                 return WERR_BADFID;
6302         }
6303
6304         /* check the level */
6305         switch (r->in.info_ctr->level) {
6306                 case 0:
6307                         return control_printer(r->in.handle, r->in.command, p);
6308                 case 2:
6309                         result = update_printer(p, r->in.handle,
6310                                                 r->in.info_ctr,
6311                                                 r->in.devmode_ctr->devmode);
6312                         if (!W_ERROR_IS_OK(result))
6313                                 return result;
6314                         if (r->in.secdesc_ctr->sd)
6315                                 result = update_printer_sec(r->in.handle, p,
6316                                                             r->in.secdesc_ctr);
6317                         return result;
6318                 case 3:
6319                         return update_printer_sec(r->in.handle, p,
6320                                                   r->in.secdesc_ctr);
6321                 case 7:
6322                         return publish_or_unpublish_printer(p, r->in.handle,
6323                                                             r->in.info_ctr->info.info7);
6324                 default:
6325                         return WERR_UNKNOWN_LEVEL;
6326         }
6327 }
6328
6329 /****************************************************************
6330  _spoolss_FindClosePrinterNotify
6331 ****************************************************************/
6332
6333 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6334                                        struct spoolss_FindClosePrinterNotify *r)
6335 {
6336         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6337
6338         if (!Printer) {
6339                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6340                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6341                 return WERR_BADFID;
6342         }
6343
6344         if (Printer->notify.client_connected == true) {
6345                 int snum = -1;
6346
6347                 if ( Printer->printer_type == SPLHND_SERVER)
6348                         snum = -1;
6349                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6350                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6351                         return WERR_BADFID;
6352
6353                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6354         }
6355
6356         Printer->notify.flags=0;
6357         Printer->notify.options=0;
6358         Printer->notify.localmachine[0]='\0';
6359         Printer->notify.printerlocal=0;
6360         TALLOC_FREE(Printer->notify.option);
6361         Printer->notify.client_connected = false;
6362
6363         return WERR_OK;
6364 }
6365
6366 /****************************************************************
6367  _spoolss_AddJob
6368 ****************************************************************/
6369
6370 WERROR _spoolss_AddJob(pipes_struct *p,
6371                        struct spoolss_AddJob *r)
6372 {
6373         if (!r->in.buffer && (r->in.offered != 0)) {
6374                 return WERR_INVALID_PARAM;
6375         }
6376
6377         /* this is what a NT server returns for AddJob. AddJob must fail on
6378          * non-local printers */
6379
6380         if (r->in.level != 1) {
6381                 return WERR_UNKNOWN_LEVEL;
6382         }
6383
6384         return WERR_INVALID_PARAM;
6385 }
6386
6387 /****************************************************************************
6388 fill_job_info1
6389 ****************************************************************************/
6390
6391 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6392                              struct spoolss_JobInfo1 *r,
6393                              const print_queue_struct *queue,
6394                              int position, int snum,
6395                              const NT_PRINTER_INFO_LEVEL *ntprinter)
6396 {
6397         struct tm *t;
6398
6399         t = gmtime(&queue->time);
6400
6401         r->job_id               = queue->job;
6402
6403         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6404         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6405         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6406         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6407         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6408         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6409         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6410         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6411         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6412         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6413         r->text_status          = talloc_strdup(mem_ctx, "");
6414         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6415
6416         r->status               = nt_printj_status(queue->status);
6417         r->priority             = queue->priority;
6418         r->position             = position;
6419         r->total_pages          = queue->page_count;
6420         r->pages_printed        = 0; /* ??? */
6421
6422         init_systemtime(&r->submitted, t);
6423
6424         return WERR_OK;
6425 }
6426
6427 /****************************************************************************
6428 fill_job_info2
6429 ****************************************************************************/
6430
6431 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6432                              struct spoolss_JobInfo2 *r,
6433                              const print_queue_struct *queue,
6434                              int position, int snum,
6435                              const NT_PRINTER_INFO_LEVEL *ntprinter,
6436                              struct spoolss_DeviceMode *devmode)
6437 {
6438         struct tm *t;
6439
6440         t = gmtime(&queue->time);
6441
6442         r->job_id               = queue->job;
6443
6444         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6445         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6446         r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6447         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6448         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6449         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6450         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6451         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6452         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6453         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6454         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6455         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6456         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6457         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6458         r->parameters           = talloc_strdup(mem_ctx, "");
6459         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6460         r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6461         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6462
6463         r->devmode              = devmode;
6464
6465         r->text_status          = talloc_strdup(mem_ctx, "");
6466         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6467
6468         r->secdesc              = NULL;
6469
6470         r->status               = nt_printj_status(queue->status);
6471         r->priority             = queue->priority;
6472         r->position             = position;
6473         r->start_time           = 0;
6474         r->until_time           = 0;
6475         r->total_pages          = queue->page_count;
6476         r->size                 = queue->size;
6477         init_systemtime(&r->submitted, t);
6478         r->time                 = 0;
6479         r->pages_printed        = 0; /* ??? */
6480
6481         return WERR_OK;
6482 }
6483
6484 /****************************************************************************
6485  Enumjobs at level 1.
6486 ****************************************************************************/
6487
6488 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6489                               const print_queue_struct *queue,
6490                               uint32_t num_queues, int snum,
6491                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6492                               union spoolss_JobInfo **info_p,
6493                               uint32_t *count)
6494 {
6495         union spoolss_JobInfo *info;
6496         int i;
6497         WERROR result = WERR_OK;
6498
6499         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6500         W_ERROR_HAVE_NO_MEMORY(info);
6501
6502         *count = num_queues;
6503
6504         for (i=0; i<*count; i++) {
6505                 result = fill_job_info1(info,
6506                                         &info[i].info1,
6507                                         &queue[i],
6508                                         i,
6509                                         snum,
6510                                         ntprinter);
6511                 if (!W_ERROR_IS_OK(result)) {
6512                         goto out;
6513                 }
6514         }
6515
6516  out:
6517         if (!W_ERROR_IS_OK(result)) {
6518                 TALLOC_FREE(info);
6519                 *count = 0;
6520                 return result;
6521         }
6522
6523         *info_p = info;
6524
6525         return WERR_OK;
6526 }
6527
6528 /****************************************************************************
6529  Enumjobs at level 2.
6530 ****************************************************************************/
6531
6532 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6533                               const print_queue_struct *queue,
6534                               uint32_t num_queues, int snum,
6535                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6536                               union spoolss_JobInfo **info_p,
6537                               uint32_t *count)
6538 {
6539         union spoolss_JobInfo *info;
6540         int i;
6541         WERROR result = WERR_OK;
6542
6543         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6544         W_ERROR_HAVE_NO_MEMORY(info);
6545
6546         *count = num_queues;
6547
6548         for (i=0; i<*count; i++) {
6549
6550                 struct spoolss_DeviceMode *devmode;
6551
6552                 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6553                 if (!devmode) {
6554                         result = WERR_NOMEM;
6555                         goto out;
6556                 }
6557
6558                 result = fill_job_info2(info,
6559                                         &info[i].info2,
6560                                         &queue[i],
6561                                         i,
6562                                         snum,
6563                                         ntprinter,
6564                                         devmode);
6565                 if (!W_ERROR_IS_OK(result)) {
6566                         goto out;
6567                 }
6568         }
6569
6570  out:
6571         if (!W_ERROR_IS_OK(result)) {
6572                 TALLOC_FREE(info);
6573                 *count = 0;
6574                 return result;
6575         }
6576
6577         *info_p = info;
6578
6579         return WERR_OK;
6580 }
6581
6582 /****************************************************************
6583  _spoolss_EnumJobs
6584 ****************************************************************/
6585
6586 WERROR _spoolss_EnumJobs(pipes_struct *p,
6587                          struct spoolss_EnumJobs *r)
6588 {
6589         WERROR result;
6590         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6591         int snum;
6592         print_status_struct prt_status;
6593         print_queue_struct *queue = NULL;
6594         uint32_t count;
6595
6596         /* that's an [in out] buffer */
6597
6598         if (!r->in.buffer && (r->in.offered != 0)) {
6599                 return WERR_INVALID_PARAM;
6600         }
6601
6602         DEBUG(4,("_spoolss_EnumJobs\n"));
6603
6604         *r->out.needed = 0;
6605         *r->out.count = 0;
6606         *r->out.info = NULL;
6607
6608         /* lookup the printer snum and tdb entry */
6609
6610         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6611                 return WERR_BADFID;
6612         }
6613
6614         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6615         if (!W_ERROR_IS_OK(result)) {
6616                 return result;
6617         }
6618
6619         count = print_queue_status(snum, &queue, &prt_status);
6620         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6621                 count, prt_status.status, prt_status.message));
6622
6623         if (count == 0) {
6624                 SAFE_FREE(queue);
6625                 free_a_printer(&ntprinter, 2);
6626                 return WERR_OK;
6627         }
6628
6629         switch (r->in.level) {
6630         case 1:
6631                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6632                                          ntprinter, r->out.info, r->out.count);
6633                 break;
6634         case 2:
6635                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6636                                          ntprinter, r->out.info, r->out.count);
6637                 break;
6638         default:
6639                 result = WERR_UNKNOWN_LEVEL;
6640                 break;
6641         }
6642
6643         SAFE_FREE(queue);
6644         free_a_printer(&ntprinter, 2);
6645
6646         if (!W_ERROR_IS_OK(result)) {
6647                 return result;
6648         }
6649
6650         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6651                                                      spoolss_EnumJobs, NULL,
6652                                                      *r->out.info, r->in.level,
6653                                                      *r->out.count);
6654         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6655         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6656
6657         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6658 }
6659
6660 /****************************************************************
6661  _spoolss_ScheduleJob
6662 ****************************************************************/
6663
6664 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6665                             struct spoolss_ScheduleJob *r)
6666 {
6667         return WERR_OK;
6668 }
6669
6670 /****************************************************************
6671  _spoolss_SetJob
6672 ****************************************************************/
6673
6674 WERROR _spoolss_SetJob(pipes_struct *p,
6675                        struct spoolss_SetJob *r)
6676 {
6677         int snum;
6678         WERROR errcode = WERR_BADFUNC;
6679
6680         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6681                 return WERR_BADFID;
6682         }
6683
6684         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6685                 return WERR_INVALID_PRINTER_NAME;
6686         }
6687
6688         switch (r->in.command) {
6689         case SPOOLSS_JOB_CONTROL_CANCEL:
6690         case SPOOLSS_JOB_CONTROL_DELETE:
6691                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6692                         errcode = WERR_OK;
6693                 }
6694                 break;
6695         case SPOOLSS_JOB_CONTROL_PAUSE:
6696                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6697                         errcode = WERR_OK;
6698                 }
6699                 break;
6700         case SPOOLSS_JOB_CONTROL_RESTART:
6701         case SPOOLSS_JOB_CONTROL_RESUME:
6702                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6703                         errcode = WERR_OK;
6704                 }
6705                 break;
6706         default:
6707                 return WERR_UNKNOWN_LEVEL;
6708         }
6709
6710         return errcode;
6711 }
6712
6713 static const struct print_architecture_table_node archi_table[]= {
6714
6715         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
6716         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
6717         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
6718         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
6719         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
6720         {"Windows IA64",         SPL_ARCH_IA64,         3 },
6721         {"Windows x64",          SPL_ARCH_X64,          3 },
6722         {NULL,                   "",            -1 }
6723 };
6724
6725 /****************************************************************************
6726  Enumerates all printer drivers by level and architecture.
6727 ****************************************************************************/
6728
6729 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6730                                                        const char *servername,
6731                                                        const char *architecture,
6732                                                        uint32_t level,
6733                                                        union spoolss_DriverInfo **info_p,
6734                                                        uint32_t *count_p)
6735 {
6736         int i;
6737         int ndrivers;
6738         uint32_t version;
6739         fstring *list = NULL;
6740         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6741         union spoolss_DriverInfo *info = NULL;
6742         uint32_t count = 0;
6743         WERROR result = WERR_OK;
6744
6745         *count_p = 0;
6746         *info_p = NULL;
6747
6748         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6749                 list = NULL;
6750                 ndrivers = get_ntdrivers(&list, architecture, version);
6751                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6752                         ndrivers, architecture, version));
6753
6754                 if (ndrivers == -1) {
6755                         result = WERR_NOMEM;
6756                         goto out;
6757                 }
6758
6759                 if (ndrivers != 0) {
6760                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6761                                                     union spoolss_DriverInfo,
6762                                                     count + ndrivers);
6763                         if (!info) {
6764                                 DEBUG(0,("enumprinterdrivers_level1: "
6765                                         "failed to enlarge driver info buffer!\n"));
6766                                 result = WERR_NOMEM;
6767                                 goto out;
6768                         }
6769                 }
6770
6771                 for (i=0; i<ndrivers; i++) {
6772                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6773                         ZERO_STRUCT(driver);
6774                         result = get_a_printer_driver(&driver, 3, list[i],
6775                                                       architecture, version);
6776                         if (!W_ERROR_IS_OK(result)) {
6777                                 goto out;
6778                         }
6779
6780                         switch (level) {
6781                         case 1:
6782                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6783                                                                    &driver, servername,
6784                                                                    architecture);
6785                                 break;
6786                         case 2:
6787                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6788                                                                    &driver, servername);
6789                                 break;
6790                         case 3:
6791                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6792                                                                    &driver, servername);
6793                                 break;
6794                         case 4:
6795                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6796                                                                    &driver, servername);
6797                                 break;
6798                         case 5:
6799                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6800                                                                    &driver, servername);
6801                                 break;
6802                         case 6:
6803                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6804                                                                    &driver, servername);
6805                                 break;
6806                         default:
6807                                 result = WERR_UNKNOWN_LEVEL;
6808                                 break;
6809                         }
6810
6811                         if (!W_ERROR_IS_OK(result)) {
6812                                 free_a_printer_driver(driver, 3);
6813                                 goto out;
6814                         }
6815                         free_a_printer_driver(driver, 3);
6816                 }
6817
6818                 count += ndrivers;
6819                 SAFE_FREE(list);
6820         }
6821
6822  out:
6823         SAFE_FREE(list);
6824
6825         if (!W_ERROR_IS_OK(result)) {
6826                 TALLOC_FREE(info);
6827                 return result;
6828         }
6829
6830         *info_p = info;
6831         *count_p = count;
6832
6833         return WERR_OK;
6834 }
6835
6836 /****************************************************************************
6837  Enumerates all printer drivers by level.
6838 ****************************************************************************/
6839
6840 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6841                                        const char *servername,
6842                                        const char *architecture,
6843                                        uint32_t level,
6844                                        union spoolss_DriverInfo **info_p,
6845                                        uint32_t *count_p)
6846 {
6847         uint32_t a,i;
6848         WERROR result = WERR_OK;
6849
6850         if (strequal(architecture, "all")) {
6851
6852                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6853
6854                         union spoolss_DriverInfo *info = NULL;
6855                         uint32_t count = 0;
6856
6857                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6858                                                                           servername,
6859                                                                           archi_table[a].long_archi,
6860                                                                           level,
6861                                                                           &info,
6862                                                                           &count);
6863                         if (!W_ERROR_IS_OK(result)) {
6864                                 continue;
6865                         }
6866
6867                         for (i=0; i < count; i++) {
6868                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6869                                              info[i], info_p, count_p);
6870                         }
6871                 }
6872
6873                 return result;
6874         }
6875
6876         return enumprinterdrivers_level_by_architecture(mem_ctx,
6877                                                         servername,
6878                                                         architecture,
6879                                                         level,
6880                                                         info_p,
6881                                                         count_p);
6882 }
6883
6884 /****************************************************************************
6885  Enumerates all printer drivers at level 1.
6886 ****************************************************************************/
6887
6888 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6889                                         const char *servername,
6890                                         const char *architecture,
6891                                         union spoolss_DriverInfo **info_p,
6892                                         uint32_t *count)
6893 {
6894         return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6895                                         info_p, count);
6896 }
6897
6898 /****************************************************************************
6899  Enumerates all printer drivers at level 2.
6900 ****************************************************************************/
6901
6902 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6903                                         const char *servername,
6904                                         const char *architecture,
6905                                         union spoolss_DriverInfo **info_p,
6906                                         uint32_t *count)
6907 {
6908         return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6909                                         info_p, count);
6910 }
6911
6912 /****************************************************************************
6913  Enumerates all printer drivers at level 3.
6914 ****************************************************************************/
6915
6916 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6917                                         const char *servername,
6918                                         const char *architecture,
6919                                         union spoolss_DriverInfo **info_p,
6920                                         uint32_t *count)
6921 {
6922         return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6923                                         info_p, count);
6924 }
6925
6926 /****************************************************************************
6927  Enumerates all printer drivers at level 4.
6928 ****************************************************************************/
6929
6930 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6931                                         const char *servername,
6932                                         const char *architecture,
6933                                         union spoolss_DriverInfo **info_p,
6934                                         uint32_t *count)
6935 {
6936         return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6937                                         info_p, count);
6938 }
6939
6940 /****************************************************************************
6941  Enumerates all printer drivers at level 5.
6942 ****************************************************************************/
6943
6944 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6945                                         const char *servername,
6946                                         const char *architecture,
6947                                         union spoolss_DriverInfo **info_p,
6948                                         uint32_t *count)
6949 {
6950         return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6951                                         info_p, count);
6952 }
6953
6954 /****************************************************************************
6955  Enumerates all printer drivers at level 6.
6956 ****************************************************************************/
6957
6958 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6959                                         const char *servername,
6960                                         const char *architecture,
6961                                         union spoolss_DriverInfo **info_p,
6962                                         uint32_t *count)
6963 {
6964         return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6965                                         info_p, count);
6966 }
6967
6968
6969 /****************************************************************
6970  _spoolss_EnumPrinterDrivers
6971 ****************************************************************/
6972
6973 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6974                                    struct spoolss_EnumPrinterDrivers *r)
6975 {
6976         const char *cservername;
6977         WERROR result;
6978
6979         /* that's an [in out] buffer */
6980
6981         if (!r->in.buffer && (r->in.offered != 0)) {
6982                 return WERR_INVALID_PARAM;
6983         }
6984
6985         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6986
6987         *r->out.needed = 0;
6988         *r->out.count = 0;
6989         *r->out.info = NULL;
6990
6991         cservername = canon_servername(r->in.server);
6992
6993         if (!is_myname_or_ipaddr(cservername)) {
6994                 return WERR_UNKNOWN_PRINTER_DRIVER;
6995         }
6996
6997         switch (r->in.level) {
6998         case 1:
6999                 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
7000                                                    r->in.environment,
7001                                                    r->out.info, r->out.count);
7002                 break;
7003         case 2:
7004                 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
7005                                                    r->in.environment,
7006                                                    r->out.info, r->out.count);
7007                 break;
7008         case 3:
7009                 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
7010                                                    r->in.environment,
7011                                                    r->out.info, r->out.count);
7012                 break;
7013         case 4:
7014                 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
7015                                                    r->in.environment,
7016                                                    r->out.info, r->out.count);
7017                 break;
7018         case 5:
7019                 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
7020                                                    r->in.environment,
7021                                                    r->out.info, r->out.count);
7022                 break;
7023         case 6:
7024                 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
7025                                                    r->in.environment,
7026                                                    r->out.info, r->out.count);
7027                 break;
7028         default:
7029                 return WERR_UNKNOWN_LEVEL;
7030         }
7031
7032         if (!W_ERROR_IS_OK(result)) {
7033                 return result;
7034         }
7035
7036         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7037                                                      spoolss_EnumPrinterDrivers, NULL,
7038                                                      *r->out.info, r->in.level,
7039                                                      *r->out.count);
7040         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7041         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7042
7043         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7044 }
7045
7046 /****************************************************************************
7047 ****************************************************************************/
7048
7049 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7050                                struct spoolss_FormInfo1 *r,
7051                                const nt_forms_struct *form)
7052 {
7053         r->form_name    = talloc_strdup(mem_ctx, form->name);
7054         W_ERROR_HAVE_NO_MEMORY(r->form_name);
7055
7056         r->flags        = form->flag;
7057         r->size.width   = form->width;
7058         r->size.height  = form->length;
7059         r->area.left    = form->left;
7060         r->area.top     = form->top;
7061         r->area.right   = form->right;
7062         r->area.bottom  = form->bottom;
7063
7064         return WERR_OK;
7065 }
7066
7067 /****************************************************************
7068  spoolss_enumforms_level1
7069 ****************************************************************/
7070
7071 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7072                                        const nt_forms_struct *builtin_forms,
7073                                        uint32_t num_builtin_forms,
7074                                        const nt_forms_struct *user_forms,
7075                                        uint32_t num_user_forms,
7076                                        union spoolss_FormInfo **info_p,
7077                                        uint32_t *count)
7078 {
7079         union spoolss_FormInfo *info;
7080         WERROR result = WERR_OK;
7081         int i;
7082
7083         *count = num_builtin_forms + num_user_forms;
7084
7085         info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7086         W_ERROR_HAVE_NO_MEMORY(info);
7087
7088         /* construct the list of form structures */
7089         for (i=0; i<num_builtin_forms; i++) {
7090                 DEBUGADD(6,("Filling form number [%d]\n",i));
7091                 result = fill_form_info_1(info, &info[i].info1,
7092                                           &builtin_forms[i]);
7093                 if (!W_ERROR_IS_OK(result)) {
7094                         goto out;
7095                 }
7096         }
7097
7098         for (; i<num_user_forms; i++) {
7099                 DEBUGADD(6,("Filling form number [%d]\n",i));
7100                 result = fill_form_info_1(info, &info[i].info1,
7101                                           &user_forms[i-num_builtin_forms]);
7102                 if (!W_ERROR_IS_OK(result)) {
7103                         goto out;
7104                 }
7105         }
7106
7107  out:
7108         if (!W_ERROR_IS_OK(result)) {
7109                 TALLOC_FREE(info);
7110                 *count = 0;
7111                 return result;
7112         }
7113
7114         *info_p = info;
7115
7116         return WERR_OK;
7117 }
7118
7119 /****************************************************************
7120  _spoolss_EnumForms
7121 ****************************************************************/
7122
7123 WERROR _spoolss_EnumForms(pipes_struct *p,
7124                           struct spoolss_EnumForms *r)
7125 {
7126         WERROR result;
7127         nt_forms_struct *user_forms = NULL;
7128         nt_forms_struct *builtin_forms = NULL;
7129         uint32_t num_user_forms;
7130         uint32_t num_builtin_forms;
7131
7132         *r->out.count = 0;
7133         *r->out.needed = 0;
7134         *r->out.info = NULL;
7135
7136         /* that's an [in out] buffer */
7137
7138         if (!r->in.buffer && (r->in.offered != 0) ) {
7139                 return WERR_INVALID_PARAM;
7140         }
7141
7142         DEBUG(4,("_spoolss_EnumForms\n"));
7143         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7144         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7145
7146         num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7147         DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7148         num_user_forms = get_ntforms(&user_forms);
7149         DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7150
7151         if (num_user_forms + num_builtin_forms == 0) {
7152                 SAFE_FREE(builtin_forms);
7153                 SAFE_FREE(user_forms);
7154                 return WERR_NO_MORE_ITEMS;
7155         }
7156
7157         switch (r->in.level) {
7158         case 1:
7159                 result = spoolss_enumforms_level1(p->mem_ctx,
7160                                                   builtin_forms,
7161                                                   num_builtin_forms,
7162                                                   user_forms,
7163                                                   num_user_forms,
7164                                                   r->out.info,
7165                                                   r->out.count);
7166                 break;
7167         default:
7168                 result = WERR_UNKNOWN_LEVEL;
7169                 break;
7170         }
7171
7172         SAFE_FREE(user_forms);
7173         SAFE_FREE(builtin_forms);
7174
7175         if (!W_ERROR_IS_OK(result)) {
7176                 return result;
7177         }
7178
7179         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7180                                                      spoolss_EnumForms, NULL,
7181                                                      *r->out.info, r->in.level,
7182                                                      *r->out.count);
7183         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7184         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7185
7186         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7187 }
7188
7189 /****************************************************************
7190 ****************************************************************/
7191
7192 static WERROR find_form_byname(const char *name,
7193                                nt_forms_struct *form)
7194 {
7195         nt_forms_struct *list = NULL;
7196         int num_forms = 0, i = 0;
7197
7198         if (get_a_builtin_ntform_by_string(name, form)) {
7199                 return WERR_OK;
7200         }
7201
7202         num_forms = get_ntforms(&list);
7203         DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7204
7205         if (num_forms == 0) {
7206                 return WERR_BADFID;
7207         }
7208
7209         /* Check if the requested name is in the list of form structures */
7210         for (i = 0; i < num_forms; i++) {
7211
7212                 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7213
7214                 if (strequal(name, list[i].name)) {
7215                         DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7216                         *form = list[i];
7217                         SAFE_FREE(list);
7218                         return WERR_OK;
7219                 }
7220         }
7221
7222         SAFE_FREE(list);
7223
7224         return WERR_BADFID;
7225 }
7226
7227 /****************************************************************
7228  _spoolss_GetForm
7229 ****************************************************************/
7230
7231 WERROR _spoolss_GetForm(pipes_struct *p,
7232                         struct spoolss_GetForm *r)
7233 {
7234         WERROR result;
7235         nt_forms_struct form;
7236
7237         /* that's an [in out] buffer */
7238
7239         if (!r->in.buffer && (r->in.offered != 0)) {
7240                 return WERR_INVALID_PARAM;
7241         }
7242
7243         DEBUG(4,("_spoolss_GetForm\n"));
7244         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7245         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7246
7247         result = find_form_byname(r->in.form_name, &form);
7248         if (!W_ERROR_IS_OK(result)) {
7249                 TALLOC_FREE(r->out.info);
7250                 return result;
7251         }
7252
7253         switch (r->in.level) {
7254         case 1:
7255                 result = fill_form_info_1(p->mem_ctx,
7256                                           &r->out.info->info1,
7257                                           &form);
7258                 break;
7259
7260         default:
7261                 result = WERR_UNKNOWN_LEVEL;
7262                 break;
7263         }
7264
7265         if (!W_ERROR_IS_OK(result)) {
7266                 TALLOC_FREE(r->out.info);
7267                 return result;
7268         }
7269
7270         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7271                                                r->out.info, r->in.level);
7272         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7273
7274         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7275 }
7276
7277 /****************************************************************************
7278 ****************************************************************************/
7279
7280 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7281                           struct spoolss_PortInfo1 *r,
7282                           const char *name)
7283 {
7284         r->port_name = talloc_strdup(mem_ctx, name);
7285         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7286
7287         return WERR_OK;
7288 }
7289
7290 /****************************************************************************
7291  TODO: This probably needs distinguish between TCP/IP and Local ports
7292  somehow.
7293 ****************************************************************************/
7294
7295 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7296                           struct spoolss_PortInfo2 *r,
7297                           const char *name)
7298 {
7299         r->port_name = talloc_strdup(mem_ctx, name);
7300         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7301
7302         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7303         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7304
7305         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7306         W_ERROR_HAVE_NO_MEMORY(r->description);
7307
7308         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7309         r->reserved = 0;
7310
7311         return WERR_OK;
7312 }
7313
7314
7315 /****************************************************************************
7316  wrapper around the enumer ports command
7317 ****************************************************************************/
7318
7319 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7320 {
7321         char *cmd = lp_enumports_cmd();
7322         char **qlines = NULL;
7323         char *command = NULL;
7324         int numlines;
7325         int ret;
7326         int fd;
7327
7328         *count = 0;
7329         *lines = NULL;
7330
7331         /* if no hook then just fill in the default port */
7332
7333         if ( !*cmd ) {
7334                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7335                         return WERR_NOMEM;
7336                 }
7337                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7338                         TALLOC_FREE(qlines);
7339                         return WERR_NOMEM;
7340                 }
7341                 qlines[1] = NULL;
7342                 numlines = 1;
7343         }
7344         else {
7345                 /* we have a valid enumport command */
7346
7347                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7348                 if (!command) {
7349                         return WERR_NOMEM;
7350                 }
7351
7352                 DEBUG(10,("Running [%s]\n", command));
7353                 ret = smbrun(command, &fd);
7354                 DEBUG(10,("Returned [%d]\n", ret));
7355                 TALLOC_FREE(command);
7356                 if (ret != 0) {
7357                         if (fd != -1) {
7358                                 close(fd);
7359                         }
7360                         return WERR_ACCESS_DENIED;
7361                 }
7362
7363                 numlines = 0;
7364                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7365                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7366                 close(fd);
7367         }
7368
7369         *count = numlines;
7370         *lines = qlines;
7371
7372         return WERR_OK;
7373 }
7374
7375 /****************************************************************************
7376  enumports level 1.
7377 ****************************************************************************/
7378
7379 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7380                                 union spoolss_PortInfo **info_p,
7381                                 uint32_t *count)
7382 {
7383         union spoolss_PortInfo *info = NULL;
7384         int i=0;
7385         WERROR result = WERR_OK;
7386         char **qlines = NULL;
7387         int numlines = 0;
7388
7389         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7390         if (!W_ERROR_IS_OK(result)) {
7391                 goto out;
7392         }
7393
7394         if (numlines) {
7395                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7396                 if (!info) {
7397                         DEBUG(10,("Returning WERR_NOMEM\n"));
7398                         result = WERR_NOMEM;
7399                         goto out;
7400                 }
7401
7402                 for (i=0; i<numlines; i++) {
7403                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7404                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7405                         if (!W_ERROR_IS_OK(result)) {
7406                                 goto out;
7407                         }
7408                 }
7409         }
7410         TALLOC_FREE(qlines);
7411
7412 out:
7413         if (!W_ERROR_IS_OK(result)) {
7414                 TALLOC_FREE(info);
7415                 TALLOC_FREE(qlines);
7416                 *count = 0;
7417                 *info_p = NULL;
7418                 return result;
7419         }
7420
7421         *info_p = info;
7422         *count = numlines;
7423
7424         return WERR_OK;
7425 }
7426
7427 /****************************************************************************
7428  enumports level 2.
7429 ****************************************************************************/
7430
7431 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7432                                 union spoolss_PortInfo **info_p,
7433                                 uint32_t *count)
7434 {
7435         union spoolss_PortInfo *info = NULL;
7436         int i=0;
7437         WERROR result = WERR_OK;
7438         char **qlines = NULL;
7439         int numlines = 0;
7440
7441         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7442         if (!W_ERROR_IS_OK(result)) {
7443                 goto out;
7444         }
7445
7446         if (numlines) {
7447                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7448                 if (!info) {
7449                         DEBUG(10,("Returning WERR_NOMEM\n"));
7450                         result = WERR_NOMEM;
7451                         goto out;
7452                 }
7453
7454                 for (i=0; i<numlines; i++) {
7455                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7456                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7457                         if (!W_ERROR_IS_OK(result)) {
7458                                 goto out;
7459                         }
7460                 }
7461         }
7462         TALLOC_FREE(qlines);
7463
7464 out:
7465         if (!W_ERROR_IS_OK(result)) {
7466                 TALLOC_FREE(info);
7467                 TALLOC_FREE(qlines);
7468                 *count = 0;
7469                 *info_p = NULL;
7470                 return result;
7471         }
7472
7473         *info_p = info;
7474         *count = numlines;
7475
7476         return WERR_OK;
7477 }
7478
7479 /****************************************************************
7480  _spoolss_EnumPorts
7481 ****************************************************************/
7482
7483 WERROR _spoolss_EnumPorts(pipes_struct *p,
7484                           struct spoolss_EnumPorts *r)
7485 {
7486         WERROR result;
7487
7488         /* that's an [in out] buffer */
7489
7490         if (!r->in.buffer && (r->in.offered != 0)) {
7491                 return WERR_INVALID_PARAM;
7492         }
7493
7494         DEBUG(4,("_spoolss_EnumPorts\n"));
7495
7496         *r->out.count = 0;
7497         *r->out.needed = 0;
7498         *r->out.info = NULL;
7499
7500         switch (r->in.level) {
7501         case 1:
7502                 result = enumports_level_1(p->mem_ctx, r->out.info,
7503                                            r->out.count);
7504                 break;
7505         case 2:
7506                 result = enumports_level_2(p->mem_ctx, r->out.info,
7507                                            r->out.count);
7508                 break;
7509         default:
7510                 return WERR_UNKNOWN_LEVEL;
7511         }
7512
7513         if (!W_ERROR_IS_OK(result)) {
7514                 return result;
7515         }
7516
7517         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7518                                                      spoolss_EnumPorts, NULL,
7519                                                      *r->out.info, r->in.level,
7520                                                      *r->out.count);
7521         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7522         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7523
7524         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7525 }
7526
7527 /****************************************************************************
7528 ****************************************************************************/
7529
7530 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7531                                            const char *server,
7532                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7533                                            struct spoolss_DeviceMode *devmode,
7534                                            struct security_descriptor *sec_desc,
7535                                            struct spoolss_UserLevelCtr *user_ctr,
7536                                            struct policy_handle *handle)
7537 {
7538         NT_PRINTER_INFO_LEVEL *printer = NULL;
7539         fstring name;
7540         int     snum;
7541         WERROR err = WERR_OK;
7542
7543         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7544                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7545                 return WERR_NOMEM;
7546         }
7547
7548         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7549         if (!convert_printer_info(info_ctr, printer)) {
7550                 free_a_printer(&printer, 2);
7551                 return WERR_NOMEM;
7552         }
7553
7554         /* check to see if the printer already exists */
7555
7556         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7557                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7558                         printer->info_2->sharename));
7559                 free_a_printer(&printer, 2);
7560                 return WERR_PRINTER_ALREADY_EXISTS;
7561         }
7562
7563         /* FIXME!!!  smbd should check to see if the driver is installed before
7564            trying to add a printer like this  --jerry */
7565
7566         if (*lp_addprinter_cmd() ) {
7567                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7568                                        printer) ) {
7569                         free_a_printer(&printer,2);
7570                         return WERR_ACCESS_DENIED;
7571                 }
7572         } else {
7573                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7574                         "smb.conf parameter \"addprinter command\" is defined. This"
7575                         "parameter must exist for this call to succeed\n",
7576                         printer->info_2->sharename ));
7577         }
7578
7579         /* use our primary netbios name since get_a_printer() will convert
7580            it to what the client expects on a case by case basis */
7581
7582         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7583              printer->info_2->sharename);
7584
7585
7586         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7587                 free_a_printer(&printer,2);
7588                 return WERR_ACCESS_DENIED;
7589         }
7590
7591         /* you must be a printer admin to add a new printer */
7592         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7593                 free_a_printer(&printer,2);
7594                 return WERR_ACCESS_DENIED;
7595         }
7596
7597         /*
7598          * Do sanity check on the requested changes for Samba.
7599          */
7600
7601         if (!check_printer_ok(printer->info_2, snum)) {
7602                 free_a_printer(&printer,2);
7603                 return WERR_INVALID_PARAM;
7604         }
7605
7606         /*
7607          * When a printer is created, the drivername bound to the printer is used
7608          * to lookup previously saved driver initialization info, which is then
7609          * bound to the new printer, simulating what happens in the Windows arch.
7610          */
7611
7612         if (!devmode)
7613         {
7614                 set_driver_init(printer, 2);
7615         }
7616         else
7617         {
7618                 /* A valid devmode was included, convert and link it
7619                 */
7620                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7621
7622                 if (!convert_devicemode(printer->info_2->printername, devmode,
7623                                         &printer->info_2->devmode)) {
7624                         return  WERR_NOMEM;
7625                 }
7626         }
7627
7628         /* write the ASCII on disk */
7629         err = mod_a_printer(printer, 2);
7630         if (!W_ERROR_IS_OK(err)) {
7631                 free_a_printer(&printer,2);
7632                 return err;
7633         }
7634
7635         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7636                 /* Handle open failed - remove addition. */
7637                 del_a_printer(printer->info_2->sharename);
7638                 free_a_printer(&printer,2);
7639                 ZERO_STRUCTP(handle);
7640                 return WERR_ACCESS_DENIED;
7641         }
7642
7643         update_c_setprinter(false);
7644         free_a_printer(&printer,2);
7645
7646         return WERR_OK;
7647 }
7648
7649 /****************************************************************
7650  _spoolss_AddPrinterEx
7651 ****************************************************************/
7652
7653 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7654                              struct spoolss_AddPrinterEx *r)
7655 {
7656         switch (r->in.info_ctr->level) {
7657         case 1:
7658                 /* we don't handle yet */
7659                 /* but I know what to do ... */
7660                 return WERR_UNKNOWN_LEVEL;
7661         case 2:
7662                 return spoolss_addprinterex_level_2(p, r->in.server,
7663                                                     r->in.info_ctr,
7664                                                     r->in.devmode_ctr->devmode,
7665                                                     r->in.secdesc_ctr->sd,
7666                                                     r->in.userlevel_ctr,
7667                                                     r->out.handle);
7668         default:
7669                 return WERR_UNKNOWN_LEVEL;
7670         }
7671 }
7672
7673 /****************************************************************
7674  _spoolss_AddPrinterDriver
7675 ****************************************************************/
7676
7677 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7678                                  struct spoolss_AddPrinterDriver *r)
7679 {
7680         uint32_t level = r->in.info_ctr->level;
7681         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7682         WERROR err = WERR_OK;
7683         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7684         const char *driver_name = NULL;
7685         uint32_t version;
7686         const char *fn;
7687
7688         switch (p->hdr_req.opnum) {
7689                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7690                         fn = "_spoolss_AddPrinterDriver";
7691                         break;
7692                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7693                         fn = "_spoolss_AddPrinterDriverEx";
7694                         break;
7695                 default:
7696                         return WERR_INVALID_PARAM;
7697         }
7698
7699
7700         /* FIXME */
7701         if (level != 3 && level != 6) {
7702                 /* Clever hack from Martin Zielinski <mz@seh.de>
7703                  * to allow downgrade from level 8 (Vista).
7704                  */
7705                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7706                 return WERR_UNKNOWN_LEVEL;
7707         }
7708
7709         ZERO_STRUCT(driver);
7710
7711         if (!convert_printer_driver_info(info, &driver, level)) {
7712                 err = WERR_NOMEM;
7713                 goto done;
7714         }
7715
7716         DEBUG(5,("Cleaning driver's information\n"));
7717         err = clean_up_driver_struct(p, driver, level);
7718         if (!W_ERROR_IS_OK(err))
7719                 goto done;
7720
7721         DEBUG(5,("Moving driver to final destination\n"));
7722         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7723                                                               &err)) ) {
7724                 goto done;
7725         }
7726
7727         if (add_a_printer_driver(driver, level)!=0) {
7728                 err = WERR_ACCESS_DENIED;
7729                 goto done;
7730         }
7731
7732         switch(level) {
7733         case 3:
7734                 driver_name = driver.info_3->name ? driver.info_3->name : "";
7735                 break;
7736         case 6:
7737                 driver_name = driver.info_6->name ? driver.info_6->name : "";
7738                 break;
7739         }
7740
7741         /*
7742          * I think this is where he DrvUpgradePrinter() hook would be
7743          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7744          * server.  Right now, we just need to send ourselves a message
7745          * to update each printer bound to this driver.   --jerry
7746          */
7747
7748         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7749                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7750                         fn, driver_name));
7751         }
7752
7753         /*
7754          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7755          * decide if the driver init data should be deleted. The rules are:
7756          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7757          *  2) delete init data only if there is no 2k/Xp driver
7758          *  3) always delete init data
7759          * The generalized rule is always use init data from the highest order driver.
7760          * It is necessary to follow the driver install by an initialization step to
7761          * finish off this process.
7762         */
7763         if (level == 3)
7764                 version = driver.info_3->cversion;
7765         else if (level == 6)
7766                 version = driver.info_6->version;
7767         else
7768                 version = -1;
7769         switch (version) {
7770                 /*
7771                  * 9x printer driver - never delete init data
7772                 */
7773                 case 0:
7774                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7775                                 fn, driver_name));
7776                         break;
7777
7778                 /*
7779                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7780                  * there is no 2k/Xp driver init data for this driver name.
7781                 */
7782                 case 2:
7783                 {
7784                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7785
7786                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7787                                 /*
7788                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7789                                 */
7790                                 if (!del_driver_init(driver_name))
7791                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7792                                                 fn, driver_name));
7793                         } else {
7794                                 /*
7795                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7796                                 */
7797                                 free_a_printer_driver(driver1,3);
7798                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7799                                         fn, driver_name));
7800                         }
7801                 }
7802                 break;
7803
7804                 /*
7805                  * 2k or Xp printer driver - always delete init data
7806                 */
7807                 case 3:
7808                         if (!del_driver_init(driver_name))
7809                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7810                                         fn, driver_name));
7811                         break;
7812
7813                 default:
7814                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7815                         break;
7816         }
7817
7818
7819 done:
7820         free_a_printer_driver(driver, level);
7821         return err;
7822 }
7823
7824 /****************************************************************
7825  _spoolss_AddPrinterDriverEx
7826 ****************************************************************/
7827
7828 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7829                                    struct spoolss_AddPrinterDriverEx *r)
7830 {
7831         struct spoolss_AddPrinterDriver a;
7832
7833         /*
7834          * we only support the semantics of AddPrinterDriver()
7835          * i.e. only copy files that are newer than existing ones
7836          */
7837
7838         if (r->in.flags != APD_COPY_NEW_FILES) {
7839                 return WERR_ACCESS_DENIED;
7840         }
7841
7842         a.in.servername         = r->in.servername;
7843         a.in.info_ctr           = r->in.info_ctr;
7844
7845         return _spoolss_AddPrinterDriver(p, &a);
7846 }
7847
7848 /****************************************************************************
7849 ****************************************************************************/
7850
7851 struct _spoolss_paths {
7852         int type;
7853         const char *share;
7854         const char *dir;
7855 };
7856
7857 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7858
7859 static const struct _spoolss_paths spoolss_paths[]= {
7860         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7861         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7862 };
7863
7864 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7865                                           const char *servername,
7866                                           const char *environment,
7867                                           int component,
7868                                           char **path)
7869 {
7870         const char *pservername = NULL;
7871         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7872         const char *short_archi;
7873
7874         *path = NULL;
7875
7876         /* environment may be empty */
7877         if (environment && strlen(environment)) {
7878                 long_archi = environment;
7879         }
7880
7881         /* servername may be empty */
7882         if (servername && strlen(servername)) {
7883                 pservername = canon_servername(servername);
7884
7885                 if (!is_myname_or_ipaddr(pservername)) {
7886                         return WERR_INVALID_PARAM;
7887                 }
7888         }
7889
7890         if (!(short_archi = get_short_archi(long_archi))) {
7891                 return WERR_INVALID_ENVIRONMENT;
7892         }
7893
7894         switch (component) {
7895         case SPOOLSS_PRTPROCS_PATH:
7896         case SPOOLSS_DRIVER_PATH:
7897                 if (pservername) {
7898                         *path = talloc_asprintf(mem_ctx,
7899                                         "\\\\%s\\%s\\%s",
7900                                         pservername,
7901                                         spoolss_paths[component].share,
7902                                         short_archi);
7903                 } else {
7904                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7905                                         SPOOLSS_DEFAULT_SERVER_PATH,
7906                                         spoolss_paths[component].dir,
7907                                         short_archi);
7908                 }
7909                 break;
7910         default:
7911                 return WERR_INVALID_PARAM;
7912         }
7913
7914         if (!*path) {
7915                 return WERR_NOMEM;
7916         }
7917
7918         return WERR_OK;
7919 }
7920
7921 /****************************************************************************
7922 ****************************************************************************/
7923
7924 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7925                                           const char *servername,
7926                                           const char *environment,
7927                                           struct spoolss_DriverDirectoryInfo1 *r)
7928 {
7929         WERROR werr;
7930         char *path = NULL;
7931
7932         werr = compose_spoolss_server_path(mem_ctx,
7933                                            servername,
7934                                            environment,
7935                                            SPOOLSS_DRIVER_PATH,
7936                                            &path);
7937         if (!W_ERROR_IS_OK(werr)) {
7938                 return werr;
7939         }
7940
7941         DEBUG(4,("printer driver directory: [%s]\n", path));
7942
7943         r->directory_name = path;
7944
7945         return WERR_OK;
7946 }
7947
7948 /****************************************************************
7949  _spoolss_GetPrinterDriverDirectory
7950 ****************************************************************/
7951
7952 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7953                                           struct spoolss_GetPrinterDriverDirectory *r)
7954 {
7955         WERROR werror;
7956
7957         /* that's an [in out] buffer */
7958
7959         if (!r->in.buffer && (r->in.offered != 0)) {
7960                 return WERR_INVALID_PARAM;
7961         }
7962
7963         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7964                 r->in.level));
7965
7966         *r->out.needed = 0;
7967
7968         /* r->in.level is ignored */
7969
7970         werror = getprinterdriverdir_level_1(p->mem_ctx,
7971                                              r->in.server,
7972                                              r->in.environment,
7973                                              &r->out.info->info1);
7974         if (!W_ERROR_IS_OK(werror)) {
7975                 TALLOC_FREE(r->out.info);
7976                 return werror;
7977         }
7978
7979         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
7980                                                r->out.info, r->in.level);
7981         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7982
7983         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7984 }
7985
7986 /****************************************************************
7987  _spoolss_EnumPrinterData
7988 ****************************************************************/
7989
7990 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7991                                 struct spoolss_EnumPrinterData *r)
7992 {
7993         NT_PRINTER_INFO_LEVEL *printer = NULL;
7994         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7995         int             snum;
7996         WERROR          result;
7997         struct regval_blob      *val = NULL;
7998         NT_PRINTER_DATA *p_data;
7999         int             i, key_index, num_values;
8000         int             name_length;
8001
8002         *r->out.value_needed    = 0;
8003         *r->out.type            = REG_NONE;
8004         *r->out.data_needed     = 0;
8005
8006         DEBUG(5,("_spoolss_EnumPrinterData\n"));
8007
8008         if (!Printer) {
8009                 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
8010                         OUR_HANDLE(r->in.handle)));
8011                 return WERR_BADFID;
8012         }
8013
8014         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8015                 return WERR_BADFID;
8016         }
8017
8018         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8019         if (!W_ERROR_IS_OK(result)) {
8020                 return result;
8021         }
8022
8023         p_data = printer->info_2->data;
8024         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8025
8026         result = WERR_OK;
8027
8028         /*
8029          * The NT machine wants to know the biggest size of value and data
8030          *
8031          * cf: MSDN EnumPrinterData remark section
8032          */
8033
8034         if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
8035
8036                 uint32_t biggest_valuesize = 0;
8037                 uint32_t biggest_datasize = 0;
8038
8039                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8040
8041                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8042
8043                 for ( i=0; i<num_values; i++ )
8044                 {
8045                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8046
8047                         name_length = strlen(val->valuename);
8048                         if ( strlen(val->valuename) > biggest_valuesize )
8049                                 biggest_valuesize = name_length;
8050
8051                         if ( val->size > biggest_datasize )
8052                                 biggest_datasize = val->size;
8053
8054                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8055                                 biggest_datasize));
8056                 }
8057
8058                 /* the value is an UNICODE string but real_value_size is the length
8059                    in bytes including the trailing 0 */
8060
8061                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8062                 *r->out.data_needed  = biggest_datasize;
8063
8064                 DEBUG(6,("final values: [%d], [%d]\n",
8065                         *r->out.value_needed, *r->out.data_needed));
8066
8067                 goto done;
8068         }
8069
8070         /*
8071          * the value len is wrong in NT sp3
8072          * that's the number of bytes not the number of unicode chars
8073          */
8074
8075         if (key_index != -1) {
8076                 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8077                                                 r->in.enum_index);
8078         }
8079
8080         if (!val) {
8081
8082                 /* out_value should default to "" or else NT4 has
8083                    problems unmarshalling the response */
8084
8085                 if (r->in.value_offered) {
8086                         *r->out.value_needed = 1;
8087                         r->out.value_name = talloc_strdup(r, "");
8088                         if (!r->out.value_name) {
8089                                 result = WERR_NOMEM;
8090                                 goto done;
8091                         }
8092                 } else {
8093                         r->out.value_name = NULL;
8094                         *r->out.value_needed = 0;
8095                 }
8096
8097                 /* the data is counted in bytes */
8098
8099                 *r->out.data_needed = r->in.data_offered;
8100
8101                 result = WERR_NO_MORE_ITEMS;
8102         } else {
8103                 /*
8104                  * the value is:
8105                  * - counted in bytes in the request
8106                  * - counted in UNICODE chars in the max reply
8107                  * - counted in bytes in the real size
8108                  *
8109                  * take a pause *before* coding not *during* coding
8110                  */
8111
8112                 /* name */
8113                 if (r->in.value_offered) {
8114                         r->out.value_name = talloc_strdup(r, regval_name(val));
8115                         if (!r->out.value_name) {
8116                                 result = WERR_NOMEM;
8117                                 goto done;
8118                         }
8119                         *r->out.value_needed = strlen_m(regval_name(val));
8120                 } else {
8121                         r->out.value_name = NULL;
8122                         *r->out.value_needed = 0;
8123                 }
8124
8125                 /* type */
8126
8127                 *r->out.type = regval_type(val);
8128
8129                 /* data - counted in bytes */
8130
8131                 if (r->out.data && regval_size(val)) {
8132                         memcpy(r->out.data, regval_data_p(val), regval_size(val));
8133                 }
8134
8135                 *r->out.data_needed = regval_size(val);
8136         }
8137
8138 done:
8139         free_a_printer(&printer, 2);
8140         return result;
8141 }
8142
8143 /****************************************************************
8144  _spoolss_SetPrinterData
8145 ****************************************************************/
8146
8147 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8148                                struct spoolss_SetPrinterData *r)
8149 {
8150         NT_PRINTER_INFO_LEVEL *printer = NULL;
8151         int snum=0;
8152         WERROR result = WERR_OK;
8153         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8154         DATA_BLOB blob;
8155
8156         DEBUG(5,("_spoolss_SetPrinterData\n"));
8157
8158         if (!Printer) {
8159                 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8160                         OUR_HANDLE(r->in.handle)));
8161                 return WERR_BADFID;
8162         }
8163
8164         if (Printer->printer_type == SPLHND_SERVER) {
8165                 DEBUG(10,("_spoolss_SetPrinterData: "
8166                         "Not implemented for server handles yet\n"));
8167                 return WERR_INVALID_PARAM;
8168         }
8169
8170         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8171                 return WERR_BADFID;
8172         }
8173
8174         /*
8175          * Access check : NT returns "access denied" if you make a
8176          * SetPrinterData call without the necessary privildge.
8177          * we were originally returning OK if nothing changed
8178          * which made Win2k issue **a lot** of SetPrinterData
8179          * when connecting to a printer  --jerry
8180          */
8181
8182         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8183                 DEBUG(3,("_spoolss_SetPrinterData: "
8184                         "change denied by handle access permissions\n"));
8185                 result = WERR_ACCESS_DENIED;
8186                 goto done;
8187         }
8188
8189         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8190         if (!W_ERROR_IS_OK(result)) {
8191                 return result;
8192         }
8193
8194         result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8195                                           r->in.type, &r->in.data);
8196         if (!W_ERROR_IS_OK(result)) {
8197                 goto done;
8198         }
8199
8200         /*
8201          * When client side code sets a magic printer data key, detect it and save
8202          * the current printer data and the magic key's data (its the DEVMODE) for
8203          * future printer/driver initializations.
8204          */
8205         if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8206                 /* Set devmode and printer initialization info */
8207                 result = save_driver_init(printer, 2, blob.data, blob.length);
8208
8209                 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8210
8211                 goto done;
8212         }
8213
8214         result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8215                                     r->in.value_name, r->in.type,
8216                                     blob.data, blob.length);
8217         if (W_ERROR_IS_OK(result)) {
8218                 result = mod_a_printer(printer, 2);
8219         }
8220
8221 done:
8222         free_a_printer(&printer, 2);
8223
8224         return result;
8225 }
8226
8227 /****************************************************************
8228  _spoolss_ResetPrinter
8229 ****************************************************************/
8230
8231 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8232                              struct spoolss_ResetPrinter *r)
8233 {
8234         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8235         int             snum;
8236
8237         DEBUG(5,("_spoolss_ResetPrinter\n"));
8238
8239         /*
8240          * All we do is to check to see if the handle and queue is valid.
8241          * This call really doesn't mean anything to us because we only
8242          * support RAW printing.   --jerry
8243          */
8244
8245         if (!Printer) {
8246                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8247                         OUR_HANDLE(r->in.handle)));
8248                 return WERR_BADFID;
8249         }
8250
8251         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8252                 return WERR_BADFID;
8253
8254
8255         /* blindly return success */
8256         return WERR_OK;
8257 }
8258
8259 /****************************************************************
8260  _spoolss_DeletePrinterData
8261 ****************************************************************/
8262
8263 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8264                                   struct spoolss_DeletePrinterData *r)
8265 {
8266         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8267         int             snum=0;
8268         WERROR          status = WERR_OK;
8269         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8270
8271         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8272
8273         if (!Printer) {
8274                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8275                         OUR_HANDLE(r->in.handle)));
8276                 return WERR_BADFID;
8277         }
8278
8279         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8280                 return WERR_BADFID;
8281
8282         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8283                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8284                         "printer properties change denied by handle\n"));
8285                 return WERR_ACCESS_DENIED;
8286         }
8287
8288         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8289         if (!W_ERROR_IS_OK(status))
8290                 return status;
8291
8292         if (!r->in.value_name) {
8293                 free_a_printer(&printer, 2);
8294                 return WERR_NOMEM;
8295         }
8296
8297         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8298                                         r->in.value_name );
8299
8300         if ( W_ERROR_IS_OK(status) )
8301                 mod_a_printer( printer, 2 );
8302
8303         free_a_printer(&printer, 2);
8304
8305         return status;
8306 }
8307
8308 /****************************************************************
8309  _spoolss_AddForm
8310 ****************************************************************/
8311
8312 WERROR _spoolss_AddForm(pipes_struct *p,
8313                         struct spoolss_AddForm *r)
8314 {
8315         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8316         nt_forms_struct tmpForm;
8317         int snum = -1;
8318         WERROR status = WERR_OK;
8319         NT_PRINTER_INFO_LEVEL *printer = NULL;
8320         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8321
8322         int count=0;
8323         nt_forms_struct *list=NULL;
8324         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8325
8326         DEBUG(5,("_spoolss_AddForm\n"));
8327
8328         if (!Printer) {
8329                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8330                         OUR_HANDLE(r->in.handle)));
8331                 return WERR_BADFID;
8332         }
8333
8334
8335         /* forms can be added on printer of on the print server handle */
8336
8337         if ( Printer->printer_type == SPLHND_PRINTER )
8338         {
8339                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8340                         return WERR_BADFID;
8341
8342                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8343                 if (!W_ERROR_IS_OK(status))
8344                         goto done;
8345         }
8346
8347         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8348            and not a printer admin, then fail */
8349
8350         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8351              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8352              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8353                                           NULL, NULL,
8354                                           p->server_info->ptok,
8355                                           lp_printer_admin(snum))) {
8356                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8357                 return WERR_ACCESS_DENIED;
8358         }
8359
8360         /* can't add if builtin */
8361
8362         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8363                 status = WERR_FILE_EXISTS;
8364                 goto done;
8365         }
8366
8367         count = get_ntforms(&list);
8368
8369         if(!add_a_form(&list, form, &count)) {
8370                 status =  WERR_NOMEM;
8371                 goto done;
8372         }
8373
8374         become_root();
8375         write_ntforms(&list, count);
8376         unbecome_root();
8377
8378         /*
8379          * ChangeID must always be set if this is a printer
8380          */
8381
8382         if ( Printer->printer_type == SPLHND_PRINTER )
8383                 status = mod_a_printer(printer, 2);
8384
8385 done:
8386         if ( printer )
8387                 free_a_printer(&printer, 2);
8388         SAFE_FREE(list);
8389
8390         return status;
8391 }
8392
8393 /****************************************************************
8394  _spoolss_DeleteForm
8395 ****************************************************************/
8396
8397 WERROR _spoolss_DeleteForm(pipes_struct *p,
8398                            struct spoolss_DeleteForm *r)
8399 {
8400         const char *form_name = r->in.form_name;
8401         nt_forms_struct tmpForm;
8402         int count=0;
8403         nt_forms_struct *list=NULL;
8404         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8405         int snum = -1;
8406         WERROR status = WERR_OK;
8407         NT_PRINTER_INFO_LEVEL *printer = NULL;
8408         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8409         bool ret = false;
8410
8411         DEBUG(5,("_spoolss_DeleteForm\n"));
8412
8413         if (!Printer) {
8414                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8415                         OUR_HANDLE(r->in.handle)));
8416                 return WERR_BADFID;
8417         }
8418
8419         /* forms can be deleted on printer of on the print server handle */
8420
8421         if ( Printer->printer_type == SPLHND_PRINTER )
8422         {
8423                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8424                         return WERR_BADFID;
8425
8426                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8427                 if (!W_ERROR_IS_OK(status))
8428                         goto done;
8429         }
8430
8431         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8432              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8433              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8434                                           NULL, NULL,
8435                                           p->server_info->ptok,
8436                                           lp_printer_admin(snum))) {
8437                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8438                 return WERR_ACCESS_DENIED;
8439         }
8440
8441
8442         /* can't delete if builtin */
8443
8444         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8445                 status = WERR_INVALID_PARAM;
8446                 goto done;
8447         }
8448
8449         count = get_ntforms(&list);
8450
8451         become_root();
8452         ret = delete_a_form(&list, form_name, &count, &status);
8453         unbecome_root();
8454         if (ret == false) {
8455                 goto done;
8456         }
8457
8458         /*
8459          * ChangeID must always be set if this is a printer
8460          */
8461
8462         if ( Printer->printer_type == SPLHND_PRINTER )
8463                 status = mod_a_printer(printer, 2);
8464
8465 done:
8466         if ( printer )
8467                 free_a_printer(&printer, 2);
8468         SAFE_FREE(list);
8469
8470         return status;
8471 }
8472
8473 /****************************************************************
8474  _spoolss_SetForm
8475 ****************************************************************/
8476
8477 WERROR _spoolss_SetForm(pipes_struct *p,
8478                         struct spoolss_SetForm *r)
8479 {
8480         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8481         nt_forms_struct tmpForm;
8482         int snum = -1;
8483         WERROR status = WERR_OK;
8484         NT_PRINTER_INFO_LEVEL *printer = NULL;
8485         SE_PRIV se_printop = SE_PRINT_OPERATOR;
8486
8487         int count=0;
8488         nt_forms_struct *list=NULL;
8489         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8490
8491         DEBUG(5,("_spoolss_SetForm\n"));
8492
8493         if (!Printer) {
8494                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8495                         OUR_HANDLE(r->in.handle)));
8496                 return WERR_BADFID;
8497         }
8498
8499         /* forms can be modified on printer of on the print server handle */
8500
8501         if ( Printer->printer_type == SPLHND_PRINTER )
8502         {
8503                 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8504                         return WERR_BADFID;
8505
8506                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8507                 if (!W_ERROR_IS_OK(status))
8508                         goto done;
8509         }
8510
8511         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8512            and not a printer admin, then fail */
8513
8514         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8515              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8516              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8517                                           NULL, NULL,
8518                                           p->server_info->ptok,
8519                                           lp_printer_admin(snum))) {
8520                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8521                 return WERR_ACCESS_DENIED;
8522         }
8523
8524         /* can't set if builtin */
8525         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8526                 status = WERR_INVALID_PARAM;
8527                 goto done;
8528         }
8529
8530         count = get_ntforms(&list);
8531         update_a_form(&list, form, count);
8532         become_root();
8533         write_ntforms(&list, count);
8534         unbecome_root();
8535
8536         /*
8537          * ChangeID must always be set if this is a printer
8538          */
8539
8540         if ( Printer->printer_type == SPLHND_PRINTER )
8541                 status = mod_a_printer(printer, 2);
8542
8543
8544 done:
8545         if ( printer )
8546                 free_a_printer(&printer, 2);
8547         SAFE_FREE(list);
8548
8549         return status;
8550 }
8551
8552 /****************************************************************************
8553  fill_print_processor1
8554 ****************************************************************************/
8555
8556 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8557                                     struct spoolss_PrintProcessorInfo1 *r,
8558                                     const char *print_processor_name)
8559 {
8560         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8561         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8562
8563         return WERR_OK;
8564 }
8565
8566 /****************************************************************************
8567  enumprintprocessors level 1.
8568 ****************************************************************************/
8569
8570 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8571                                           union spoolss_PrintProcessorInfo **info_p,
8572                                           uint32_t *count)
8573 {
8574         union spoolss_PrintProcessorInfo *info;
8575         WERROR result;
8576
8577         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8578         W_ERROR_HAVE_NO_MEMORY(info);
8579
8580         *count = 1;
8581
8582         result = fill_print_processor1(info, &info[0].info1, "winprint");
8583         if (!W_ERROR_IS_OK(result)) {
8584                 goto out;
8585         }
8586
8587  out:
8588         if (!W_ERROR_IS_OK(result)) {
8589                 TALLOC_FREE(info);
8590                 *count = 0;
8591                 return result;
8592         }
8593
8594         *info_p = info;
8595
8596         return WERR_OK;
8597 }
8598
8599 /****************************************************************
8600  _spoolss_EnumPrintProcessors
8601 ****************************************************************/
8602
8603 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8604                                     struct spoolss_EnumPrintProcessors *r)
8605 {
8606         WERROR result;
8607
8608         /* that's an [in out] buffer */
8609
8610         if (!r->in.buffer && (r->in.offered != 0)) {
8611                 return WERR_INVALID_PARAM;
8612         }
8613
8614         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8615
8616         /*
8617          * Enumerate the print processors ...
8618          *
8619          * Just reply with "winprint", to keep NT happy
8620          * and I can use my nice printer checker.
8621          */
8622
8623         *r->out.count = 0;
8624         *r->out.needed = 0;
8625         *r->out.info = NULL;
8626
8627         switch (r->in.level) {
8628         case 1:
8629                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8630                                                      r->out.count);
8631                 break;
8632         default:
8633                 return WERR_UNKNOWN_LEVEL;
8634         }
8635
8636         if (!W_ERROR_IS_OK(result)) {
8637                 return result;
8638         }
8639
8640         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8641                                                      spoolss_EnumPrintProcessors, NULL,
8642                                                      *r->out.info, r->in.level,
8643                                                      *r->out.count);
8644         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8645         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8646
8647         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8648 }
8649
8650 /****************************************************************************
8651  fill_printprocdatatype1
8652 ****************************************************************************/
8653
8654 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8655                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8656                                       const char *name_array)
8657 {
8658         r->name_array = talloc_strdup(mem_ctx, name_array);
8659         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8660
8661         return WERR_OK;
8662 }
8663
8664 /****************************************************************************
8665  enumprintprocdatatypes level 1.
8666 ****************************************************************************/
8667
8668 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8669                                              union spoolss_PrintProcDataTypesInfo **info_p,
8670                                              uint32_t *count)
8671 {
8672         WERROR result;
8673         union spoolss_PrintProcDataTypesInfo *info;
8674
8675         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8676         W_ERROR_HAVE_NO_MEMORY(info);
8677
8678         *count = 1;
8679
8680         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8681         if (!W_ERROR_IS_OK(result)) {
8682                 goto out;
8683         }
8684
8685  out:
8686         if (!W_ERROR_IS_OK(result)) {
8687                 TALLOC_FREE(info);
8688                 *count = 0;
8689                 return result;
8690         }
8691
8692         *info_p = info;
8693
8694         return WERR_OK;
8695 }
8696
8697 /****************************************************************
8698  _spoolss_EnumPrintProcDataTypes
8699 ****************************************************************/
8700
8701 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8702                                        struct spoolss_EnumPrintProcDataTypes *r)
8703 {
8704         WERROR result;
8705
8706         /* that's an [in out] buffer */
8707
8708         if (!r->in.buffer && (r->in.offered != 0)) {
8709                 return WERR_INVALID_PARAM;
8710         }
8711
8712         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8713
8714         *r->out.count = 0;
8715         *r->out.needed = 0;
8716         *r->out.info = NULL;
8717
8718         switch (r->in.level) {
8719         case 1:
8720                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8721                                                         r->out.count);
8722                 break;
8723         default:
8724                 return WERR_UNKNOWN_LEVEL;
8725         }
8726
8727         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8728                                                      spoolss_EnumPrintProcDataTypes, NULL,
8729                                                      *r->out.info, r->in.level,
8730                                                      *r->out.count);
8731         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8732         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8733
8734         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8735 }
8736
8737 /****************************************************************************
8738  fill_monitor_1
8739 ****************************************************************************/
8740
8741 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8742                              struct spoolss_MonitorInfo1 *r,
8743                              const char *monitor_name)
8744 {
8745         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8746         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8747
8748         return WERR_OK;
8749 }
8750
8751 /****************************************************************************
8752  fill_monitor_2
8753 ****************************************************************************/
8754
8755 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8756                              struct spoolss_MonitorInfo2 *r,
8757                              const char *monitor_name,
8758                              const char *environment,
8759                              const char *dll_name)
8760 {
8761         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8762         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8763         r->environment                  = talloc_strdup(mem_ctx, environment);
8764         W_ERROR_HAVE_NO_MEMORY(r->environment);
8765         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8766         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8767
8768         return WERR_OK;
8769 }
8770
8771 /****************************************************************************
8772  enumprintmonitors level 1.
8773 ****************************************************************************/
8774
8775 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8776                                         union spoolss_MonitorInfo **info_p,
8777                                         uint32_t *count)
8778 {
8779         union spoolss_MonitorInfo *info;
8780         WERROR result = WERR_OK;
8781
8782         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8783         W_ERROR_HAVE_NO_MEMORY(info);
8784
8785         *count = 2;
8786
8787         result = fill_monitor_1(info, &info[0].info1,
8788                                 SPL_LOCAL_PORT);
8789         if (!W_ERROR_IS_OK(result)) {
8790                 goto out;
8791         }
8792
8793         result = fill_monitor_1(info, &info[1].info1,
8794                                 SPL_TCPIP_PORT);
8795         if (!W_ERROR_IS_OK(result)) {
8796                 goto out;
8797         }
8798
8799 out:
8800         if (!W_ERROR_IS_OK(result)) {
8801                 TALLOC_FREE(info);
8802                 *count = 0;
8803                 return result;
8804         }
8805
8806         *info_p = info;
8807
8808         return WERR_OK;
8809 }
8810
8811 /****************************************************************************
8812  enumprintmonitors level 2.
8813 ****************************************************************************/
8814
8815 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8816                                         union spoolss_MonitorInfo **info_p,
8817                                         uint32_t *count)
8818 {
8819         union spoolss_MonitorInfo *info;
8820         WERROR result = WERR_OK;
8821
8822         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8823         W_ERROR_HAVE_NO_MEMORY(info);
8824
8825         *count = 2;
8826
8827         result = fill_monitor_2(info, &info[0].info2,
8828                                 SPL_LOCAL_PORT,
8829                                 "Windows NT X86", /* FIXME */
8830                                 "localmon.dll");
8831         if (!W_ERROR_IS_OK(result)) {
8832                 goto out;
8833         }
8834
8835         result = fill_monitor_2(info, &info[1].info2,
8836                                 SPL_TCPIP_PORT,
8837                                 "Windows NT X86", /* FIXME */
8838                                 "tcpmon.dll");
8839         if (!W_ERROR_IS_OK(result)) {
8840                 goto out;
8841         }
8842
8843 out:
8844         if (!W_ERROR_IS_OK(result)) {
8845                 TALLOC_FREE(info);
8846                 *count = 0;
8847                 return result;
8848         }
8849
8850         *info_p = info;
8851
8852         return WERR_OK;
8853 }
8854
8855 /****************************************************************
8856  _spoolss_EnumMonitors
8857 ****************************************************************/
8858
8859 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8860                              struct spoolss_EnumMonitors *r)
8861 {
8862         WERROR result;
8863
8864         /* that's an [in out] buffer */
8865
8866         if (!r->in.buffer && (r->in.offered != 0)) {
8867                 return WERR_INVALID_PARAM;
8868         }
8869
8870         DEBUG(5,("_spoolss_EnumMonitors\n"));
8871
8872         /*
8873          * Enumerate the print monitors ...
8874          *
8875          * Just reply with "Local Port", to keep NT happy
8876          * and I can use my nice printer checker.
8877          */
8878
8879         *r->out.count = 0;
8880         *r->out.needed = 0;
8881         *r->out.info = NULL;
8882
8883         switch (r->in.level) {
8884         case 1:
8885                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8886                                                    r->out.count);
8887                 break;
8888         case 2:
8889                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8890                                                    r->out.count);
8891                 break;
8892         default:
8893                 return WERR_UNKNOWN_LEVEL;
8894         }
8895
8896         if (!W_ERROR_IS_OK(result)) {
8897                 return result;
8898         }
8899
8900         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8901                                                      spoolss_EnumMonitors, NULL,
8902                                                      *r->out.info, r->in.level,
8903                                                      *r->out.count);
8904         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8905         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8906
8907         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8908 }
8909
8910 /****************************************************************************
8911 ****************************************************************************/
8912
8913 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8914                              const print_queue_struct *queue,
8915                              int count, int snum,
8916                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8917                              uint32_t jobid,
8918                              struct spoolss_JobInfo1 *r)
8919 {
8920         int i = 0;
8921         bool found = false;
8922
8923         for (i=0; i<count && found == false; i++) {
8924                 if (queue[i].job == (int)jobid) {
8925                         found = true;
8926                 }
8927         }
8928
8929         if (found == false) {
8930                 /* NT treats not found as bad param... yet another bad choice */
8931                 return WERR_INVALID_PARAM;
8932         }
8933
8934         return fill_job_info1(mem_ctx,
8935                               r,
8936                               &queue[i-1],
8937                               i,
8938                               snum,
8939                               ntprinter);
8940 }
8941
8942 /****************************************************************************
8943 ****************************************************************************/
8944
8945 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8946                              const print_queue_struct *queue,
8947                              int count, int snum,
8948                              const NT_PRINTER_INFO_LEVEL *ntprinter,
8949                              uint32_t jobid,
8950                              struct spoolss_JobInfo2 *r)
8951 {
8952         int i = 0;
8953         bool found = false;
8954         struct spoolss_DeviceMode *devmode;
8955         NT_DEVICEMODE *nt_devmode;
8956         WERROR result;
8957
8958         for (i=0; i<count && found == false; i++) {
8959                 if (queue[i].job == (int)jobid) {
8960                         found = true;
8961                 }
8962         }
8963
8964         if (found == false) {
8965                 /* NT treats not found as bad param... yet another bad
8966                    choice */
8967                 return WERR_INVALID_PARAM;
8968         }
8969
8970         /*
8971          * if the print job does not have a DEVMODE associated with it,
8972          * just use the one for the printer. A NULL devicemode is not
8973          *  a failure condition
8974          */
8975
8976         nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8977         if (nt_devmode) {
8978                 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
8979                 W_ERROR_HAVE_NO_MEMORY(devmode);
8980                 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
8981                 if (!W_ERROR_IS_OK(result)) {
8982                         return result;
8983                 }
8984         } else {
8985                 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8986                 W_ERROR_HAVE_NO_MEMORY(devmode);
8987         }
8988
8989         return fill_job_info2(mem_ctx,
8990                               r,
8991                               &queue[i-1],
8992                               i,
8993                               snum,
8994                               ntprinter,
8995                               devmode);
8996 }
8997
8998 /****************************************************************
8999  _spoolss_GetJob
9000 ****************************************************************/
9001
9002 WERROR _spoolss_GetJob(pipes_struct *p,
9003                        struct spoolss_GetJob *r)
9004 {
9005         WERROR result = WERR_OK;
9006         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9007         int snum;
9008         int count;
9009         print_queue_struct      *queue = NULL;
9010         print_status_struct prt_status;
9011
9012         /* that's an [in out] buffer */
9013
9014         if (!r->in.buffer && (r->in.offered != 0)) {
9015                 return WERR_INVALID_PARAM;
9016         }
9017
9018         DEBUG(5,("_spoolss_GetJob\n"));
9019
9020         *r->out.needed = 0;
9021
9022         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9023                 return WERR_BADFID;
9024         }
9025
9026         result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9027         if (!W_ERROR_IS_OK(result)) {
9028                 return result;
9029         }
9030
9031         count = print_queue_status(snum, &queue, &prt_status);
9032
9033         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9034                      count, prt_status.status, prt_status.message));
9035
9036         switch (r->in.level) {
9037         case 1:
9038                 result = getjob_level_1(p->mem_ctx,
9039                                         queue, count, snum, ntprinter,
9040                                         r->in.job_id, &r->out.info->info1);
9041                 break;
9042         case 2:
9043                 result = getjob_level_2(p->mem_ctx,
9044                                         queue, count, snum, ntprinter,
9045                                         r->in.job_id, &r->out.info->info2);
9046                 break;
9047         default:
9048                 result = WERR_UNKNOWN_LEVEL;
9049                 break;
9050         }
9051
9052         SAFE_FREE(queue);
9053         free_a_printer(&ntprinter, 2);
9054
9055         if (!W_ERROR_IS_OK(result)) {
9056                 TALLOC_FREE(r->out.info);
9057                 return result;
9058         }
9059
9060         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9061                                                r->out.info, r->in.level);
9062         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9063
9064         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9065 }
9066
9067 /****************************************************************
9068  _spoolss_GetPrinterDataEx
9069
9070  From MSDN documentation of GetPrinterDataEx: pass request
9071  to GetPrinterData if key is "PrinterDriverData".
9072 ****************************************************************/
9073
9074 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9075                                  struct spoolss_GetPrinterDataEx *r)
9076 {
9077
9078         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9079         struct regval_blob              *val = NULL;
9080         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9081         int                     snum = 0;
9082         WERROR result = WERR_OK;
9083
9084         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9085
9086         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9087                 r->in.key_name, r->in.value_name));
9088
9089         /* in case of problem, return some default values */
9090
9091         *r->out.needed  = 0;
9092         *r->out.type    = REG_NONE;
9093
9094         if (!Printer) {
9095                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9096                         OUR_HANDLE(r->in.handle)));
9097                 result = WERR_BADFID;
9098                 goto done;
9099         }
9100
9101         /* Is the handle to a printer or to the server? */
9102
9103         if (Printer->printer_type == SPLHND_SERVER) {
9104                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9105                         "Not implemented for server handles yet\n"));
9106                 result = WERR_INVALID_PARAM;
9107                 goto done;
9108         }
9109
9110         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9111                 return WERR_BADFID;
9112         }
9113
9114         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9115         if (!W_ERROR_IS_OK(result)) {
9116                 goto done;
9117         }
9118
9119         /* check to see if the keyname is valid */
9120         if (!strlen(r->in.key_name)) {
9121                 result = WERR_INVALID_PARAM;
9122                 goto done;
9123         }
9124
9125         if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9126                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9127                         "Invalid keyname [%s]\n", r->in.key_name ));
9128                 result = WERR_BADFILE;
9129                 goto done;
9130         }
9131
9132         /* When given a new keyname, we should just create it */
9133
9134         val = get_printer_data(printer->info_2,
9135                                r->in.key_name, r->in.value_name);
9136         if (!val) {
9137                 result = WERR_BADFILE;
9138                 goto done;
9139         }
9140
9141         *r->out.needed = regval_size(val);
9142
9143         if (*r->out.needed > r->in.offered) {
9144                 result = WERR_MORE_DATA;
9145                 goto done;
9146         }
9147
9148         *r->out.type = regval_type(val);
9149
9150         memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9151
9152  done:
9153         if (printer) {
9154                 free_a_printer(&printer, 2);
9155         }
9156
9157         return result;
9158 }
9159
9160 /****************************************************************
9161  _spoolss_SetPrinterDataEx
9162 ****************************************************************/
9163
9164 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9165                                  struct spoolss_SetPrinterDataEx *r)
9166 {
9167         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9168         int                     snum = 0;
9169         WERROR                  result = WERR_OK;
9170         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9171         char                    *oid_string;
9172
9173         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9174
9175         /* From MSDN documentation of SetPrinterDataEx: pass request to
9176            SetPrinterData if key is "PrinterDriverData" */
9177
9178         if (!Printer) {
9179                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9180                         OUR_HANDLE(r->in.handle)));
9181                 return WERR_BADFID;
9182         }
9183
9184         if (Printer->printer_type == SPLHND_SERVER) {
9185                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9186                         "Not implemented for server handles yet\n"));
9187                 return WERR_INVALID_PARAM;
9188         }
9189
9190         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9191                 return WERR_BADFID;
9192         }
9193
9194         /*
9195          * Access check : NT returns "access denied" if you make a
9196          * SetPrinterData call without the necessary privildge.
9197          * we were originally returning OK if nothing changed
9198          * which made Win2k issue **a lot** of SetPrinterData
9199          * when connecting to a printer  --jerry
9200          */
9201
9202         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9203                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9204                         "change denied by handle access permissions\n"));
9205                 return WERR_ACCESS_DENIED;
9206         }
9207
9208         result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9209         if (!W_ERROR_IS_OK(result)) {
9210                 return result;
9211         }
9212
9213         /* check for OID in valuename */
9214
9215         oid_string = strchr(r->in.value_name, ',');
9216         if (oid_string) {
9217                 *oid_string = '\0';
9218                 oid_string++;
9219         }
9220
9221         /* save the registry data */
9222
9223         result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9224                                     r->in.type, r->in.buffer, r->in.offered);
9225
9226         if (W_ERROR_IS_OK(result)) {
9227                 /* save the OID if one was specified */
9228                 if (oid_string) {
9229                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9230                                 r->in.key_name, SPOOL_OID_KEY);
9231                         if (!str) {
9232                                 result = WERR_NOMEM;
9233                                 goto done;
9234                         }
9235
9236                         /*
9237                          * I'm not checking the status here on purpose.  Don't know
9238                          * if this is right, but I'm returning the status from the
9239                          * previous set_printer_dataex() call.  I have no idea if
9240                          * this is right.    --jerry
9241                          */
9242
9243                         set_printer_dataex(printer, str, r->in.value_name,
9244                                            REG_SZ, (uint8_t *)oid_string,
9245                                            strlen(oid_string)+1);
9246                 }
9247
9248                 result = mod_a_printer(printer, 2);
9249         }
9250
9251  done:
9252         free_a_printer(&printer, 2);
9253
9254         return result;
9255 }
9256
9257 /****************************************************************
9258  _spoolss_DeletePrinterDataEx
9259 ****************************************************************/
9260
9261 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9262                                     struct spoolss_DeletePrinterDataEx *r)
9263 {
9264         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9265         int             snum=0;
9266         WERROR          status = WERR_OK;
9267         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9268
9269         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9270
9271         if (!Printer) {
9272                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9273                         "Invalid handle (%s:%u:%u).\n",
9274                         OUR_HANDLE(r->in.handle)));
9275                 return WERR_BADFID;
9276         }
9277
9278         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9279                 return WERR_BADFID;
9280
9281         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9282                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9283                         "printer properties change denied by handle\n"));
9284                 return WERR_ACCESS_DENIED;
9285         }
9286
9287         if (!r->in.value_name || !r->in.key_name) {
9288                 return WERR_NOMEM;
9289         }
9290
9291         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9292         if (!W_ERROR_IS_OK(status))
9293                 return status;
9294
9295         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9296
9297         if ( W_ERROR_IS_OK(status) )
9298                 mod_a_printer( printer, 2 );
9299
9300         free_a_printer(&printer, 2);
9301
9302         return status;
9303 }
9304
9305 /****************************************************************
9306  _spoolss_EnumPrinterKey
9307 ****************************************************************/
9308
9309 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9310                                struct spoolss_EnumPrinterKey *r)
9311 {
9312         fstring         *keynames = NULL;
9313         int             num_keys;
9314         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9315         NT_PRINTER_DATA *data;
9316         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9317         int             snum = 0;
9318         WERROR          result = WERR_BADFILE;
9319         int i;
9320         const char **array = NULL;
9321
9322
9323         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9324
9325         if (!Printer) {
9326                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9327                         OUR_HANDLE(r->in.handle)));
9328                 return WERR_BADFID;
9329         }
9330
9331         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9332                 return WERR_BADFID;
9333         }
9334
9335         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9336         if (!W_ERROR_IS_OK(result)) {
9337                 return result;
9338         }
9339
9340         /* get the list of subkey names */
9341
9342         data = printer->info_2->data;
9343
9344         num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9345         if (num_keys == -1) {
9346                 result = WERR_BADFILE;
9347                 goto done;
9348         }
9349
9350         *r->out.needed = 4;
9351
9352         array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9353         if (!array) {
9354                 result = WERR_NOMEM;
9355                 goto done;
9356         }
9357
9358         for (i=0; i < num_keys; i++) {
9359                 array[i] = talloc_strdup(array, keynames[i]);
9360                 if (!array[i]) {
9361                         result = WERR_NOMEM;
9362                         goto done;
9363                 }
9364
9365                 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9366         }
9367
9368         if (r->in.offered < *r->out.needed) {
9369                 result = WERR_MORE_DATA;
9370                 goto done;
9371         }
9372
9373         result = WERR_OK;
9374
9375         *r->out.key_buffer = array;
9376
9377  done:
9378         if (!W_ERROR_IS_OK(result)) {
9379                 TALLOC_FREE(array);
9380                 ZERO_STRUCTP(r->out.key_buffer);
9381         }
9382
9383         free_a_printer(&printer, 2);
9384         SAFE_FREE(keynames);
9385
9386         return result;
9387 }
9388
9389 /****************************************************************
9390  _spoolss_DeletePrinterKey
9391 ****************************************************************/
9392
9393 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9394                                  struct spoolss_DeletePrinterKey *r)
9395 {
9396         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
9397         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9398         int                     snum=0;
9399         WERROR                  status;
9400
9401         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9402
9403         if (!Printer) {
9404                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9405                         OUR_HANDLE(r->in.handle)));
9406                 return WERR_BADFID;
9407         }
9408
9409         /* if keyname == NULL, return error */
9410
9411         if ( !r->in.key_name )
9412                 return WERR_INVALID_PARAM;
9413
9414         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9415                 return WERR_BADFID;
9416
9417         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9418                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9419                         "printer properties change denied by handle\n"));
9420                 return WERR_ACCESS_DENIED;
9421         }
9422
9423         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9424         if (!W_ERROR_IS_OK(status))
9425                 return status;
9426
9427         /* delete the key and all subneys */
9428
9429         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9430
9431         if ( W_ERROR_IS_OK(status) )
9432                 status = mod_a_printer(printer, 2);
9433
9434         free_a_printer( &printer, 2 );
9435
9436         return status;
9437 }
9438
9439 /****************************************************************
9440 ****************************************************************/
9441
9442 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9443                                                    struct regval_blob *v,
9444                                                    struct spoolss_PrinterEnumValues *r)
9445 {
9446         WERROR result;
9447
9448         r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9449         W_ERROR_HAVE_NO_MEMORY(r->data);
9450
9451         r->value_name   = talloc_strdup(mem_ctx, regval_name(v));
9452         W_ERROR_HAVE_NO_MEMORY(r->value_name);
9453
9454         r->type         = regval_type(v);
9455         r->data_length  = regval_size(v);
9456
9457         if (r->data_length) {
9458                 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9459                                                  regval_size(v));
9460                 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9461                                                   r->data,
9462                                                   r->type);
9463                 if (!W_ERROR_IS_OK(result)) {
9464                         return result;
9465                 }
9466         }
9467
9468         return WERR_OK;
9469 }
9470
9471 /****************************************************************
9472  _spoolss_EnumPrinterDataEx
9473 ****************************************************************/
9474
9475 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9476                                   struct spoolss_EnumPrinterDataEx *r)
9477 {
9478         uint32_t        count = 0;
9479         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9480         struct spoolss_PrinterEnumValues *info = NULL;
9481         NT_PRINTER_DATA         *p_data;
9482         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
9483         int             snum;
9484         WERROR          result;
9485         int             key_index;
9486         int             i;
9487
9488         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9489
9490         *r->out.count = 0;
9491         *r->out.needed = 0;
9492         *r->out.info = NULL;
9493
9494         if (!Printer) {
9495                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9496                         OUR_HANDLE(r->in.handle)));
9497                 return WERR_BADFID;
9498         }
9499
9500         /*
9501          * first check for a keyname of NULL or "".  Win2k seems to send
9502          * this a lot and we should send back WERR_INVALID_PARAM
9503          * no need to spend time looking up the printer in this case.
9504          * --jerry
9505          */
9506
9507         if (!strlen(r->in.key_name)) {
9508                 result = WERR_INVALID_PARAM;
9509                 goto done;
9510         }
9511
9512         /* get the printer off of disk */
9513
9514         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9515                 return WERR_BADFID;
9516         }
9517
9518         ZERO_STRUCT(printer);
9519         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9520         if (!W_ERROR_IS_OK(result)) {
9521                 return result;
9522         }
9523
9524         /* now look for a match on the key name */
9525
9526         p_data = printer->info_2->data;
9527
9528         key_index = lookup_printerkey(p_data, r->in.key_name);
9529         if (key_index == -1) {
9530                 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9531                         r->in.key_name));
9532                 result = WERR_INVALID_PARAM;
9533                 goto done;
9534         }
9535
9536         /* allocate the memory for the array of pointers -- if necessary */
9537
9538         count = regval_ctr_numvals(p_data->keys[key_index].values);
9539         if (!count) {
9540                 result = WERR_OK; /* ??? */
9541                 goto done;
9542         }
9543
9544         info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9545                                  struct spoolss_PrinterEnumValues,
9546                                  count);
9547         if (!info) {
9548                 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9549                 result = WERR_NOMEM;
9550                 goto done;
9551         }
9552
9553         /*
9554          * loop through all params and build the array to pass
9555          * back to the  client
9556          */
9557
9558         for (i=0; i < count; i++) {
9559
9560                 struct regval_blob      *val;
9561
9562                 /* lookup the registry value */
9563
9564                 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9565
9566                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9567
9568                 /* copy the data */
9569
9570                 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9571                 if (!W_ERROR_IS_OK(result)) {
9572                         goto done;
9573                 }
9574         }
9575
9576 #if 0 /* FIXME - gd */
9577         /* housekeeping information in the reply */
9578
9579         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9580          * the hand marshalled container size is a multiple
9581          * of 4 bytes for RPC alignment.
9582          */
9583
9584         if (needed % 4) {
9585                 needed += 4-(needed % 4);
9586         }
9587 #endif
9588         *r->out.count   = count;
9589         *r->out.info    = info;
9590
9591  done:
9592
9593         if (printer) {
9594                 free_a_printer(&printer, 2);
9595         }
9596
9597         if (!W_ERROR_IS_OK(result)) {
9598                 return result;
9599         }
9600
9601         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9602                                                spoolss_EnumPrinterDataEx, NULL,
9603                                                *r->out.info,
9604                                                *r->out.count);
9605         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9606         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9607
9608         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9609 }
9610
9611 /****************************************************************************
9612 ****************************************************************************/
9613
9614 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9615                                                  const char *servername,
9616                                                  const char *environment,
9617                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9618 {
9619         WERROR werr;
9620         char *path = NULL;
9621
9622         werr = compose_spoolss_server_path(mem_ctx,
9623                                            servername,
9624                                            environment,
9625                                            SPOOLSS_PRTPROCS_PATH,
9626                                            &path);
9627         if (!W_ERROR_IS_OK(werr)) {
9628                 return werr;
9629         }
9630
9631         DEBUG(4,("print processor directory: [%s]\n", path));
9632
9633         r->directory_name = path;
9634
9635         return WERR_OK;
9636 }
9637
9638 /****************************************************************
9639  _spoolss_GetPrintProcessorDirectory
9640 ****************************************************************/
9641
9642 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9643                                            struct spoolss_GetPrintProcessorDirectory *r)
9644 {
9645         WERROR result;
9646
9647         /* that's an [in out] buffer */
9648
9649         if (!r->in.buffer && (r->in.offered != 0)) {
9650                 return WERR_INVALID_PARAM;
9651         }
9652
9653         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9654                 r->in.level));
9655
9656         *r->out.needed = 0;
9657
9658         /* r->in.level is ignored */
9659
9660         result = getprintprocessordirectory_level_1(p->mem_ctx,
9661                                                     r->in.server,
9662                                                     r->in.environment,
9663                                                     &r->out.info->info1);
9664         if (!W_ERROR_IS_OK(result)) {
9665                 TALLOC_FREE(r->out.info);
9666                 return result;
9667         }
9668
9669         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9670                                                r->out.info, r->in.level);
9671         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9672
9673         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9674 }
9675
9676 /*******************************************************************
9677  ********************************************************************/
9678
9679 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9680                                const char *dllname)
9681 {
9682         enum ndr_err_code ndr_err;
9683         struct spoolss_MonitorUi ui;
9684
9685         ui.dll_name = dllname;
9686
9687         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9688                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9689         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9690                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9691         }
9692         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9693 }
9694
9695 /*******************************************************************
9696  Streams the monitor UI DLL name in UNICODE
9697 *******************************************************************/
9698
9699 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9700                                NT_USER_TOKEN *token, DATA_BLOB *in,
9701                                DATA_BLOB *out, uint32_t *needed)
9702 {
9703         const char *dllname = "tcpmonui.dll";
9704
9705         *needed = (strlen(dllname)+1) * 2;
9706
9707         if (out->length < *needed) {
9708                 return WERR_INSUFFICIENT_BUFFER;
9709         }
9710
9711         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9712                 return WERR_NOMEM;
9713         }
9714
9715         return WERR_OK;
9716 }
9717
9718 /*******************************************************************
9719  ********************************************************************/
9720
9721 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9722                              struct spoolss_PortData1 *port1,
9723                              const DATA_BLOB *buf)
9724 {
9725         enum ndr_err_code ndr_err;
9726         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9727                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9728         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9729                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9730         }
9731         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9732 }
9733
9734 /*******************************************************************
9735  ********************************************************************/
9736
9737 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9738                              struct spoolss_PortData2 *port2,
9739                              const DATA_BLOB *buf)
9740 {
9741         enum ndr_err_code ndr_err;
9742         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9743                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9744         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9745                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9746         }
9747         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9748 }
9749
9750 /*******************************************************************
9751  Create a new TCP/IP port
9752 *******************************************************************/
9753
9754 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9755                              NT_USER_TOKEN *token, DATA_BLOB *in,
9756                              DATA_BLOB *out, uint32_t *needed)
9757 {
9758         struct spoolss_PortData1 port1;
9759         struct spoolss_PortData2 port2;
9760         char *device_uri = NULL;
9761         uint32_t version;
9762
9763         const char *portname;
9764         const char *hostaddress;
9765         const char *queue;
9766         uint32_t port_number;
9767         uint32_t protocol;
9768
9769         /* peek for spoolss_PortData version */
9770
9771         if (!in || (in->length < (128 + 4))) {
9772                 return WERR_GENERAL_FAILURE;
9773         }
9774
9775         version = IVAL(in->data, 128);
9776
9777         switch (version) {
9778                 case 1:
9779                         ZERO_STRUCT(port1);
9780
9781                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9782                                 return WERR_NOMEM;
9783                         }
9784
9785                         portname        = port1.portname;
9786                         hostaddress     = port1.hostaddress;
9787                         queue           = port1.queue;
9788                         protocol        = port1.protocol;
9789                         port_number     = port1.port_number;
9790
9791                         break;
9792                 case 2:
9793                         ZERO_STRUCT(port2);
9794
9795                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9796                                 return WERR_NOMEM;
9797                         }
9798
9799                         portname        = port2.portname;
9800                         hostaddress     = port2.hostaddress;
9801                         queue           = port2.queue;
9802                         protocol        = port2.protocol;
9803                         port_number     = port2.port_number;
9804
9805                         break;
9806                 default:
9807                         DEBUG(1,("xcvtcp_addport: "
9808                                 "unknown version of port_data: %d\n", version));
9809                         return WERR_UNKNOWN_PORT;
9810         }
9811
9812         /* create the device URI and call the add_port_hook() */
9813
9814         switch (protocol) {
9815         case PROTOCOL_RAWTCP_TYPE:
9816                 device_uri = talloc_asprintf(mem_ctx,
9817                                 "socket://%s:%d/", hostaddress,
9818                                 port_number);
9819                 break;
9820
9821         case PROTOCOL_LPR_TYPE:
9822                 device_uri = talloc_asprintf(mem_ctx,
9823                         "lpr://%s/%s", hostaddress, queue );
9824                 break;
9825
9826         default:
9827                 return WERR_UNKNOWN_PORT;
9828         }
9829
9830         if (!device_uri) {
9831                 return WERR_NOMEM;
9832         }
9833
9834         return add_port_hook(mem_ctx, token, portname, device_uri);
9835 }
9836
9837 /*******************************************************************
9838 *******************************************************************/
9839
9840 struct xcv_api_table xcvtcp_cmds[] = {
9841         { "MonitorUI",  xcvtcp_monitorui },
9842         { "AddPort",    xcvtcp_addport},
9843         { NULL,         NULL }
9844 };
9845
9846 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9847                                      NT_USER_TOKEN *token, const char *command,
9848                                      DATA_BLOB *inbuf,
9849                                      DATA_BLOB *outbuf,
9850                                      uint32_t *needed )
9851 {
9852         int i;
9853
9854         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9855
9856         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9857                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9858                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9859         }
9860
9861         return WERR_BADFUNC;
9862 }
9863
9864 /*******************************************************************
9865 *******************************************************************/
9866 #if 0   /* don't support management using the "Local Port" monitor */
9867
9868 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9869                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9870                                  DATA_BLOB *out, uint32_t *needed)
9871 {
9872         const char *dllname = "localui.dll";
9873
9874         *needed = (strlen(dllname)+1) * 2;
9875
9876         if (out->length < *needed) {
9877                 return WERR_INSUFFICIENT_BUFFER;
9878         }
9879
9880         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9881                 return WERR_NOMEM;
9882         }
9883
9884         return WERR_OK;
9885 }
9886
9887 /*******************************************************************
9888 *******************************************************************/
9889
9890 struct xcv_api_table xcvlocal_cmds[] = {
9891         { "MonitorUI",  xcvlocal_monitorui },
9892         { NULL,         NULL }
9893 };
9894 #else
9895 struct xcv_api_table xcvlocal_cmds[] = {
9896         { NULL,         NULL }
9897 };
9898 #endif
9899
9900
9901
9902 /*******************************************************************
9903 *******************************************************************/
9904
9905 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9906                                        NT_USER_TOKEN *token, const char *command,
9907                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9908                                        uint32_t *needed)
9909 {
9910         int i;
9911
9912         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9913
9914         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9915                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9916                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9917         }
9918         return WERR_BADFUNC;
9919 }
9920
9921 /****************************************************************
9922  _spoolss_XcvData
9923 ****************************************************************/
9924
9925 WERROR _spoolss_XcvData(pipes_struct *p,
9926                         struct spoolss_XcvData *r)
9927 {
9928         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9929         DATA_BLOB out_data = data_blob_null;
9930         WERROR werror;
9931
9932         if (!Printer) {
9933                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9934                         OUR_HANDLE(r->in.handle)));
9935                 return WERR_BADFID;
9936         }
9937
9938         /* Has to be a handle to the TCP/IP port monitor */
9939
9940         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9941                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9942                 return WERR_BADFID;
9943         }
9944
9945         /* requires administrative access to the server */
9946
9947         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9948                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9949                 return WERR_ACCESS_DENIED;
9950         }
9951
9952         /* Allocate the outgoing buffer */
9953
9954         if (r->in.out_data_size) {
9955                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9956                 if (out_data.data == NULL) {
9957                         return WERR_NOMEM;
9958                 }
9959         }
9960
9961         switch ( Printer->printer_type ) {
9962         case SPLHND_PORTMON_TCP:
9963                 werror = process_xcvtcp_command(p->mem_ctx,
9964                                                 p->server_info->ptok,
9965                                                 r->in.function_name,
9966                                                 &r->in.in_data, &out_data,
9967                                                 r->out.needed);
9968                 break;
9969         case SPLHND_PORTMON_LOCAL:
9970                 werror = process_xcvlocal_command(p->mem_ctx,
9971                                                   p->server_info->ptok,
9972                                                   r->in.function_name,
9973                                                   &r->in.in_data, &out_data,
9974                                                   r->out.needed);
9975                 break;
9976         default:
9977                 werror = WERR_INVALID_PRINT_MONITOR;
9978         }
9979
9980         if (!W_ERROR_IS_OK(werror)) {
9981                 return werror;
9982         }
9983
9984         *r->out.status_code = 0;
9985
9986         memcpy(r->out.out_data, out_data.data, out_data.length);
9987
9988         return WERR_OK;
9989 }
9990
9991 /****************************************************************
9992  _spoolss_AddPrintProcessor
9993 ****************************************************************/
9994
9995 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9996                                   struct spoolss_AddPrintProcessor *r)
9997 {
9998         /* for now, just indicate success and ignore the add.  We'll
9999            automatically set the winprint processor for printer
10000            entries later.  Used to debug the LexMark Optra S 1855 PCL
10001            driver --jerry */
10002
10003         return WERR_OK;
10004 }
10005
10006 /****************************************************************
10007  _spoolss_AddPort
10008 ****************************************************************/
10009
10010 WERROR _spoolss_AddPort(pipes_struct *p,
10011                         struct spoolss_AddPort *r)
10012 {
10013         /* do what w2k3 does */
10014
10015         return WERR_NOT_SUPPORTED;
10016 }
10017
10018 /****************************************************************
10019  _spoolss_AddPrinter
10020 ****************************************************************/
10021
10022 WERROR _spoolss_AddPrinter(pipes_struct *p,
10023                            struct spoolss_AddPrinter *r)
10024 {
10025         p->rng_fault_state = true;
10026         return WERR_NOT_SUPPORTED;
10027 }
10028
10029 /****************************************************************
10030  _spoolss_GetPrinterDriver
10031 ****************************************************************/
10032
10033 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10034                                  struct spoolss_GetPrinterDriver *r)
10035 {
10036         p->rng_fault_state = true;
10037         return WERR_NOT_SUPPORTED;
10038 }
10039
10040 /****************************************************************
10041  _spoolss_ReadPrinter
10042 ****************************************************************/
10043
10044 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10045                             struct spoolss_ReadPrinter *r)
10046 {
10047         p->rng_fault_state = true;
10048         return WERR_NOT_SUPPORTED;
10049 }
10050
10051 /****************************************************************
10052  _spoolss_WaitForPrinterChange
10053 ****************************************************************/
10054
10055 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10056                                      struct spoolss_WaitForPrinterChange *r)
10057 {
10058         p->rng_fault_state = true;
10059         return WERR_NOT_SUPPORTED;
10060 }
10061
10062 /****************************************************************
10063  _spoolss_ConfigurePort
10064 ****************************************************************/
10065
10066 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10067                               struct spoolss_ConfigurePort *r)
10068 {
10069         p->rng_fault_state = true;
10070         return WERR_NOT_SUPPORTED;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_DeletePort
10075 ****************************************************************/
10076
10077 WERROR _spoolss_DeletePort(pipes_struct *p,
10078                            struct spoolss_DeletePort *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085  _spoolss_CreatePrinterIC
10086 ****************************************************************/
10087
10088 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10089                                 struct spoolss_CreatePrinterIC *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_PlayGDIScriptOnPrinterIC
10097 ****************************************************************/
10098
10099 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10100                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107  _spoolss_DeletePrinterIC
10108 ****************************************************************/
10109
10110 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10111                                 struct spoolss_DeletePrinterIC *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118  _spoolss_AddPrinterConnection
10119 ****************************************************************/
10120
10121 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10122                                      struct spoolss_AddPrinterConnection *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_DeletePrinterConnection
10130 ****************************************************************/
10131
10132 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10133                                         struct spoolss_DeletePrinterConnection *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140  _spoolss_PrinterMessageBox
10141 ****************************************************************/
10142
10143 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10144                                   struct spoolss_PrinterMessageBox *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151  _spoolss_AddMonitor
10152 ****************************************************************/
10153
10154 WERROR _spoolss_AddMonitor(pipes_struct *p,
10155                            struct spoolss_AddMonitor *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162  _spoolss_DeleteMonitor
10163 ****************************************************************/
10164
10165 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10166                               struct spoolss_DeleteMonitor *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173  _spoolss_DeletePrintProcessor
10174 ****************************************************************/
10175
10176 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10177                                      struct spoolss_DeletePrintProcessor *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_AddPrintProvidor
10185 ****************************************************************/
10186
10187 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10188                                  struct spoolss_AddPrintProvidor *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195  _spoolss_DeletePrintProvidor
10196 ****************************************************************/
10197
10198 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10199                                     struct spoolss_DeletePrintProvidor *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206  _spoolss_FindFirstPrinterChangeNotification
10207 ****************************************************************/
10208
10209 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10210                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217  _spoolss_FindNextPrinterChangeNotification
10218 ****************************************************************/
10219
10220 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10221                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10229 ****************************************************************/
10230
10231 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10232                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239  _spoolss_ReplyOpenPrinter
10240 ****************************************************************/
10241
10242 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10243                                  struct spoolss_ReplyOpenPrinter *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250  _spoolss_RouterReplyPrinter
10251 ****************************************************************/
10252
10253 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10254                                    struct spoolss_RouterReplyPrinter *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_ReplyClosePrinter
10262 ****************************************************************/
10263
10264 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10265                                   struct spoolss_ReplyClosePrinter *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272  _spoolss_AddPortEx
10273 ****************************************************************/
10274
10275 WERROR _spoolss_AddPortEx(pipes_struct *p,
10276                           struct spoolss_AddPortEx *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283  _spoolss_RouterFindFirstPrinterChangeNotification
10284 ****************************************************************/
10285
10286 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10287                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294  _spoolss_SpoolerInit
10295 ****************************************************************/
10296
10297 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10298                             struct spoolss_SpoolerInit *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305  _spoolss_ResetPrinterEx
10306 ****************************************************************/
10307
10308 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10309                                struct spoolss_ResetPrinterEx *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316  _spoolss_RouterReplyPrinterEx
10317 ****************************************************************/
10318
10319 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10320                                      struct spoolss_RouterReplyPrinterEx *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_44
10328 ****************************************************************/
10329
10330 WERROR _spoolss_44(pipes_struct *p,
10331                    struct spoolss_44 *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_47
10339 ****************************************************************/
10340
10341 WERROR _spoolss_47(pipes_struct *p,
10342                    struct spoolss_47 *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }
10347
10348 /****************************************************************
10349  _spoolss_4a
10350 ****************************************************************/
10351
10352 WERROR _spoolss_4a(pipes_struct *p,
10353                    struct spoolss_4a *r)
10354 {
10355         p->rng_fault_state = true;
10356         return WERR_NOT_SUPPORTED;
10357 }
10358
10359 /****************************************************************
10360  _spoolss_4b
10361 ****************************************************************/
10362
10363 WERROR _spoolss_4b(pipes_struct *p,
10364                    struct spoolss_4b *r)
10365 {
10366         p->rng_fault_state = true;
10367         return WERR_NOT_SUPPORTED;
10368 }
10369
10370 /****************************************************************
10371  _spoolss_4c
10372 ****************************************************************/
10373
10374 WERROR _spoolss_4c(pipes_struct *p,
10375                    struct spoolss_4c *r)
10376 {
10377         p->rng_fault_state = true;
10378         return WERR_NOT_SUPPORTED;
10379 }
10380
10381 /****************************************************************
10382  _spoolss_53
10383 ****************************************************************/
10384
10385 WERROR _spoolss_53(pipes_struct *p,
10386                    struct spoolss_53 *r)
10387 {
10388         p->rng_fault_state = true;
10389         return WERR_NOT_SUPPORTED;
10390 }
10391
10392 /****************************************************************
10393  _spoolss_55
10394 ****************************************************************/
10395
10396 WERROR _spoolss_55(pipes_struct *p,
10397                    struct spoolss_55 *r)
10398 {
10399         p->rng_fault_state = true;
10400         return WERR_NOT_SUPPORTED;
10401 }
10402
10403 /****************************************************************
10404  _spoolss_56
10405 ****************************************************************/
10406
10407 WERROR _spoolss_56(pipes_struct *p,
10408                    struct spoolss_56 *r)
10409 {
10410         p->rng_fault_state = true;
10411         return WERR_NOT_SUPPORTED;
10412 }
10413
10414 /****************************************************************
10415  _spoolss_57
10416 ****************************************************************/
10417
10418 WERROR _spoolss_57(pipes_struct *p,
10419                    struct spoolss_57 *r)
10420 {
10421         p->rng_fault_state = true;
10422         return WERR_NOT_SUPPORTED;
10423 }
10424
10425 /****************************************************************
10426  _spoolss_5a
10427 ****************************************************************/
10428
10429 WERROR _spoolss_5a(pipes_struct *p,
10430                    struct spoolss_5a *r)
10431 {
10432         p->rng_fault_state = true;
10433         return WERR_NOT_SUPPORTED;
10434 }
10435
10436 /****************************************************************
10437  _spoolss_5b
10438 ****************************************************************/
10439
10440 WERROR _spoolss_5b(pipes_struct *p,
10441                    struct spoolss_5b *r)
10442 {
10443         p->rng_fault_state = true;
10444         return WERR_NOT_SUPPORTED;
10445 }
10446
10447 /****************************************************************
10448  _spoolss_5c
10449 ****************************************************************/
10450
10451 WERROR _spoolss_5c(pipes_struct *p,
10452                    struct spoolss_5c *r)
10453 {
10454         p->rng_fault_state = true;
10455         return WERR_NOT_SUPPORTED;
10456 }
10457
10458 /****************************************************************
10459  _spoolss_5d
10460 ****************************************************************/
10461
10462 WERROR _spoolss_5d(pipes_struct *p,
10463                    struct spoolss_5d *r)
10464 {
10465         p->rng_fault_state = true;
10466         return WERR_NOT_SUPPORTED;
10467 }
10468
10469 /****************************************************************
10470  _spoolss_5e
10471 ****************************************************************/
10472
10473 WERROR _spoolss_5e(pipes_struct *p,
10474                    struct spoolss_5e *r)
10475 {
10476         p->rng_fault_state = true;
10477         return WERR_NOT_SUPPORTED;
10478 }
10479
10480 /****************************************************************
10481  _spoolss_5f
10482 ****************************************************************/
10483
10484 WERROR _spoolss_5f(pipes_struct *p,
10485                    struct spoolss_5f *r)
10486 {
10487         p->rng_fault_state = true;
10488         return WERR_NOT_SUPPORTED;
10489 }
10490