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