s3-spoolss: Convert do_drv_upgrade_printer() to winreg functions.
[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-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "srv_spoolss_util.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "librpc/gen_ndr/messaging.h"
36 #include "registry.h"
37 #include "registry/reg_objects.h"
38
39 /* macros stolen from s4 spoolss server */
40 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
41         ((info)?ndr_size_##fn(info, level, 0):0)
42
43 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
44         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
45
46 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
47         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
48
49 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
50
51
52 extern userdom_struct current_user_info;
53
54 #undef DBGC_CLASS
55 #define DBGC_CLASS DBGC_RPC_SRV
56
57 #ifndef MAX_OPEN_PRINTER_EXS
58 #define MAX_OPEN_PRINTER_EXS 50
59 #endif
60
61 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
62
63 static Printer_entry *printers_list;
64
65 typedef struct _counter_printer_0 {
66         struct _counter_printer_0 *next;
67         struct _counter_printer_0 *prev;
68
69         int snum;
70         uint32_t counter;
71 } counter_printer_0;
72
73 static counter_printer_0 *counter_list;
74
75 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
76 static uint32_t smb_connections = 0;
77
78
79 /* in printing/nt_printing.c */
80
81 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
82
83 /* API table for Xcv Monitor functions */
84
85 struct xcv_api_table {
86         const char *name;
87         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
88 };
89
90 /********************************************************************
91  * Canonicalize servername.
92  ********************************************************************/
93
94 static const char *canon_servername(const char *servername)
95 {
96         const char *pservername = servername;
97         while (*pservername == '\\') {
98                 pservername++;
99         }
100         return pservername;
101 }
102
103 /* translate between internal status numbers and NT status numbers */
104 static int nt_printj_status(int v)
105 {
106         switch (v) {
107         case LPQ_QUEUED:
108                 return 0;
109         case LPQ_PAUSED:
110                 return JOB_STATUS_PAUSED;
111         case LPQ_SPOOLING:
112                 return JOB_STATUS_SPOOLING;
113         case LPQ_PRINTING:
114                 return JOB_STATUS_PRINTING;
115         case LPQ_ERROR:
116                 return JOB_STATUS_ERROR;
117         case LPQ_DELETING:
118                 return JOB_STATUS_DELETING;
119         case LPQ_OFFLINE:
120                 return JOB_STATUS_OFFLINE;
121         case LPQ_PAPEROUT:
122                 return JOB_STATUS_PAPEROUT;
123         case LPQ_PRINTED:
124                 return JOB_STATUS_PRINTED;
125         case LPQ_DELETED:
126                 return JOB_STATUS_DELETED;
127         case LPQ_BLOCKED:
128                 return JOB_STATUS_BLOCKED_DEVQ;
129         case LPQ_USER_INTERVENTION:
130                 return JOB_STATUS_USER_INTERVENTION;
131         }
132         return 0;
133 }
134
135 static int nt_printq_status(int v)
136 {
137         switch (v) {
138         case LPQ_PAUSED:
139                 return PRINTER_STATUS_PAUSED;
140         case LPQ_QUEUED:
141         case LPQ_SPOOLING:
142         case LPQ_PRINTING:
143                 return 0;
144         }
145         return 0;
146 }
147
148 /***************************************************************************
149  Disconnect from the client
150 ****************************************************************************/
151
152 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
153 {
154         WERROR result;
155         NTSTATUS status;
156
157         /*
158          * Tell the specific printing tdb we no longer want messages for this printer
159          * by deregistering our PID.
160          */
161
162         if (!print_notify_deregister_pid(snum))
163                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
164
165         /* weird if the test succeds !!! */
166         if (smb_connections==0) {
167                 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
168                 return;
169         }
170
171         status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
172                                                   handle,
173                                                   &result);
174         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
175                 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
176                         win_errstr(result)));
177
178         /* if it's the last connection, deconnect the IPC$ share */
179         if (smb_connections==1) {
180
181                 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
182                 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
183
184                 messaging_deregister(smbd_messaging_context(),
185                                      MSG_PRINTER_NOTIFY2, NULL);
186
187                 /* Tell the connections db we're no longer interested in
188                  * printer notify messages. */
189
190                 serverid_register_msg_flags(
191                         messaging_server_id(smbd_messaging_context()),
192                         false, FLAG_MSG_PRINT_NOTIFY);
193         }
194
195         smb_connections--;
196 }
197
198 /****************************************************************************
199  Functions to free a printer entry datastruct.
200 ****************************************************************************/
201
202 static int printer_entry_destructor(Printer_entry *Printer)
203 {
204         if (Printer->notify.client_connected == true) {
205                 int snum = -1;
206
207                 if ( Printer->printer_type == SPLHND_SERVER) {
208                         snum = -1;
209                         srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
210                 } else if (Printer->printer_type == SPLHND_PRINTER) {
211                         snum = print_queue_snum(Printer->sharename);
212                         if (snum != -1)
213                                 srv_spoolss_replycloseprinter(snum,
214                                                 &Printer->notify.client_hnd);
215                 }
216         }
217
218         Printer->notify.flags=0;
219         Printer->notify.options=0;
220         Printer->notify.localmachine[0]='\0';
221         Printer->notify.printerlocal=0;
222         TALLOC_FREE(Printer->notify.option);
223         Printer->notify.client_connected = false;
224
225         TALLOC_FREE(Printer->devmode);
226         free_a_printer( &Printer->printer_info, 2 );
227
228         /* Remove from the internal list. */
229         DLIST_REMOVE(printers_list, Printer);
230         return 0;
231 }
232
233 /****************************************************************************
234   find printer index by handle
235 ****************************************************************************/
236
237 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
238                                                 struct policy_handle *hnd)
239 {
240         Printer_entry *find_printer = NULL;
241
242         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
243                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
244                 return NULL;
245         }
246
247         return find_printer;
248 }
249
250 /****************************************************************************
251  Close printer index by handle.
252 ****************************************************************************/
253
254 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
255 {
256         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
257
258         if (!Printer) {
259                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
260                         OUR_HANDLE(hnd)));
261                 return false;
262         }
263
264         close_policy_hnd(p, hnd);
265
266         return true;
267 }
268
269 /****************************************************************************
270  Delete a printer given a handle.
271 ****************************************************************************/
272
273 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
274 {
275         char *cmd = lp_deleteprinter_cmd();
276         char *command = NULL;
277         int ret;
278         SE_PRIV se_printop = SE_PRINT_OPERATOR;
279         bool is_print_op = false;
280
281         /* can't fail if we don't try */
282
283         if ( !*cmd )
284                 return WERR_OK;
285
286         command = talloc_asprintf(ctx,
287                         "%s \"%s\"",
288                         cmd, sharename);
289         if (!command) {
290                 return WERR_NOMEM;
291         }
292         if ( token )
293                 is_print_op = user_has_privileges( token, &se_printop );
294
295         DEBUG(10,("Running [%s]\n", command));
296
297         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
298
299         if ( is_print_op )
300                 become_root();
301
302         if ( (ret = smbrun(command, NULL)) == 0 ) {
303                 /* Tell everyone we updated smb.conf. */
304                 message_send_all(smbd_messaging_context(),
305                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
306         }
307
308         if ( is_print_op )
309                 unbecome_root();
310
311         /********** END SePrintOperatorPrivlege BLOCK **********/
312
313         DEBUGADD(10,("returned [%d]\n", ret));
314
315         TALLOC_FREE(command);
316
317         if (ret != 0)
318                 return WERR_BADFID; /* What to return here? */
319
320         /* go ahead and re-read the services immediately */
321         become_root();
322         reload_services(false);
323         unbecome_root();
324
325         if ( lp_servicenumber( sharename )  > 0 )
326                 return WERR_ACCESS_DENIED;
327
328         return WERR_OK;
329 }
330
331 /****************************************************************************
332  Delete a printer given a handle.
333 ****************************************************************************/
334
335 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
336 {
337         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
338
339         if (!Printer) {
340                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
341                         OUR_HANDLE(hnd)));
342                 return WERR_BADFID;
343         }
344
345         /*
346          * It turns out that Windows allows delete printer on a handle
347          * opened by an admin user, then used on a pipe handle created
348          * by an anonymous user..... but they're working on security.... riiight !
349          * JRA.
350          */
351
352         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
353                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
354                 return WERR_ACCESS_DENIED;
355         }
356
357         /* this does not need a become root since the access check has been
358            done on the handle already */
359
360         if (del_a_printer( Printer->sharename ) != 0) {
361                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
362                 return WERR_BADFID;
363         }
364
365         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
366                                    Printer->sharename );
367 }
368
369 /****************************************************************************
370  Return the snum of a printer corresponding to an handle.
371 ****************************************************************************/
372
373 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
374                              int *number, struct share_params **params)
375 {
376         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
377
378         if (!Printer) {
379                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
380                         OUR_HANDLE(hnd)));
381                 return false;
382         }
383
384         switch (Printer->printer_type) {
385                 case SPLHND_PRINTER:
386                         DEBUG(4,("short name:%s\n", Printer->sharename));
387                         *number = print_queue_snum(Printer->sharename);
388                         return (*number != -1);
389                 case SPLHND_SERVER:
390                         return false;
391                 default:
392                         return false;
393         }
394 }
395
396 /****************************************************************************
397  Set printer handle type.
398  Check if it's \\server or \\server\printer
399 ****************************************************************************/
400
401 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
402 {
403         DEBUG(3,("Setting printer type=%s\n", handlename));
404
405         if ( strlen(handlename) < 3 ) {
406                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
407                 return false;
408         }
409
410         /* it's a print server */
411         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
412                 DEBUGADD(4,("Printer is a print server\n"));
413                 Printer->printer_type = SPLHND_SERVER;
414         }
415         /* it's a printer (set_printer_hnd_name() will handle port monitors */
416         else {
417                 DEBUGADD(4,("Printer is a printer\n"));
418                 Printer->printer_type = SPLHND_PRINTER;
419         }
420
421         return true;
422 }
423
424 /****************************************************************************
425  Set printer handle name..  Accept names like \\server, \\server\printer,
426  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
427  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
428  XcvDataPort() interface.
429 ****************************************************************************/
430
431 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
432                                  struct auth_serversupplied_info *server_info,
433                                  Printer_entry *Printer,
434                                  const char *handlename)
435 {
436         int snum;
437         int n_services=lp_numservices();
438         char *aprinter;
439         const char *printername;
440         const char *servername;
441         fstring sname;
442         bool found = false;
443         struct spoolss_PrinterInfo2 *info2 = NULL;
444         WERROR result;
445
446         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
447                 (unsigned long)strlen(handlename)));
448
449         aprinter = CONST_DISCARD(char *, handlename);
450         if ( *handlename == '\\' ) {
451                 servername = canon_servername(handlename);
452                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
453                         *aprinter = '\0';
454                         aprinter++;
455                 }
456                 if (!is_myname_or_ipaddr(servername)) {
457                         return false;
458                 }
459
460                 fstrcpy(Printer->servername, servername);
461         }
462
463         if (Printer->printer_type == SPLHND_SERVER) {
464                 return true;
465         }
466
467         if (Printer->printer_type != SPLHND_PRINTER) {
468                 return false;
469         }
470
471         DEBUGADD(5, ("searching for [%s]\n", aprinter));
472
473         /* check for the Port Monitor Interface */
474         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
475                 Printer->printer_type = SPLHND_PORTMON_TCP;
476                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
477                 found = true;
478         }
479         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
480                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
481                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
482                 found = true;
483         }
484
485         /* Search all sharenames first as this is easier than pulling
486            the printer_info_2 off of disk. Don't use find_service() since
487            that calls out to map_username() */
488
489         /* do another loop to look for printernames */
490         for (snum = 0; !found && snum < n_services; snum++) {
491                 const char *printer = lp_const_servicename(snum);
492
493                 /* no point going on if this is not a printer */
494                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
495                         continue;
496                 }
497
498                 /* ignore [printers] share */
499                 if (strequal(printer, "printers")) {
500                         continue;
501                 }
502
503                 fstrcpy(sname, printer);
504                 if (strequal(aprinter, printer)) {
505                         found = true;
506                         break;
507                 }
508
509                 /* no point looking up the printer object if
510                    we aren't allowing printername != sharename */
511                 if (lp_force_printername(snum)) {
512                         continue;
513                 }
514
515                 result = winreg_get_printer(mem_ctx,
516                                             server_info,
517                                             servername,
518                                             sname,
519                                             &info2);
520                 if ( !W_ERROR_IS_OK(result) ) {
521                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
522                                  sname, win_errstr(result)));
523                         continue;
524                 }
525
526                 printername = strrchr(info2->printername, '\\');
527                 if (printername == NULL) {
528                         printername = info2->printername;
529                 } else {
530                         printername++;
531                 }
532
533                 if (strequal(printername, aprinter)) {
534                         found = true;
535                         break;
536                 }
537
538                 DEBUGADD(10, ("printername: %s\n", printername));
539
540                 TALLOC_FREE(info2);
541         }
542
543         if ( !found ) {
544                 DEBUGADD(4,("Printer not found\n"));
545                 return false;
546         }
547
548         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
549
550         fstrcpy(Printer->sharename, sname);
551
552         return true;
553 }
554
555 /****************************************************************************
556  Find first available printer slot. creates a printer handle for you.
557  ****************************************************************************/
558
559 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
560                              const char *name, uint32_t access_granted)
561 {
562         Printer_entry *new_printer;
563
564         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
565
566         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
567         if (new_printer == NULL) {
568                 return false;
569         }
570         talloc_set_destructor(new_printer, printer_entry_destructor);
571
572         if (!create_policy_hnd(p, hnd, new_printer)) {
573                 TALLOC_FREE(new_printer);
574                 return false;
575         }
576
577         /* Add to the internal list. */
578         DLIST_ADD(printers_list, new_printer);
579
580         new_printer->notify.option=NULL;
581
582         if (!set_printer_hnd_printertype(new_printer, name)) {
583                 close_printer_handle(p, hnd);
584                 return false;
585         }
586
587         if (!set_printer_hnd_name(p->mem_ctx, p->server_info, new_printer, name)) {
588                 close_printer_handle(p, hnd);
589                 return false;
590         }
591
592         new_printer->access_granted = access_granted;
593
594         DEBUG(5, ("%d printer handles active\n",
595                   (int)num_pipe_handles(p)));
596
597         return true;
598 }
599
600 /***************************************************************************
601  check to see if the client motify handle is monitoring the notification
602  given by (notify_type, notify_field).
603  **************************************************************************/
604
605 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
606                                       uint16_t notify_field)
607 {
608         return true;
609 }
610
611 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
612                                 uint16_t notify_field)
613 {
614         struct spoolss_NotifyOption *option = p->notify.option;
615         uint32_t i, j;
616
617         /*
618          * Flags should always be zero when the change notify
619          * is registered by the client's spooler.  A user Win32 app
620          * might use the flags though instead of the NOTIFY_OPTION_INFO
621          * --jerry
622          */
623
624         if (!option) {
625                 return false;
626         }
627
628         if (p->notify.flags)
629                 return is_monitoring_event_flags(
630                         p->notify.flags, notify_type, notify_field);
631
632         for (i = 0; i < option->count; i++) {
633
634                 /* Check match for notify_type */
635
636                 if (option->types[i].type != notify_type)
637                         continue;
638
639                 /* Check match for field */
640
641                 for (j = 0; j < option->types[i].count; j++) {
642                         if (option->types[i].fields[j].field == notify_field) {
643                                 return true;
644                         }
645                 }
646         }
647
648         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
649                    p->servername, p->sharename, notify_type, notify_field));
650
651         return false;
652 }
653
654 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
655         _data->data.integer[0] = _integer; \
656         _data->data.integer[1] = 0;
657
658
659 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
660         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
661         if (!_data->data.string.string) {\
662                 _data->data.string.size = 0; \
663         } \
664         _data->data.string.size = strlen_m_term(_p) * 2;
665
666 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
667         _data->data.devmode.devmode = _devmode;
668
669 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
670         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
671         if (!_data->data.sd.sd) { \
672                 _data->data.sd.sd_size = 0; \
673         } \
674         _data->data.sd.sd_size = _size;
675
676 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
677                                    struct tm *t,
678                                    const char **pp,
679                                    uint32_t *plen)
680 {
681         struct spoolss_Time st;
682         uint32_t len = 16;
683         char *p;
684
685         if (!init_systemtime(&st, t)) {
686                 return;
687         }
688
689         p = talloc_array(mem_ctx, char, len);
690         if (!p) {
691                 return;
692         }
693
694         /*
695          * Systemtime must be linearized as a set of UINT16's.
696          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
697          */
698
699         SSVAL(p, 0, st.year);
700         SSVAL(p, 2, st.month);
701         SSVAL(p, 4, st.day_of_week);
702         SSVAL(p, 6, st.day);
703         SSVAL(p, 8, st.hour);
704         SSVAL(p, 10, st.minute);
705         SSVAL(p, 12, st.second);
706         SSVAL(p, 14, st.millisecond);
707
708         *pp = p;
709         *plen = len;
710 }
711
712 /* Convert a notification message to a struct spoolss_Notify */
713
714 static void notify_one_value(struct spoolss_notify_msg *msg,
715                              struct spoolss_Notify *data,
716                              TALLOC_CTX *mem_ctx)
717 {
718         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
719 }
720
721 static void notify_string(struct spoolss_notify_msg *msg,
722                           struct spoolss_Notify *data,
723                           TALLOC_CTX *mem_ctx)
724 {
725         /* The length of the message includes the trailing \0 */
726
727         data->data.string.size = msg->len * 2;
728         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
729         if (!data->data.string.string) {
730                 data->data.string.size = 0;
731                 return;
732         }
733 }
734
735 static void notify_system_time(struct spoolss_notify_msg *msg,
736                                struct spoolss_Notify *data,
737                                TALLOC_CTX *mem_ctx)
738 {
739         data->data.string.string = NULL;
740         data->data.string.size = 0;
741
742         if (msg->len != sizeof(time_t)) {
743                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
744                           msg->len));
745                 return;
746         }
747
748         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
749                                &data->data.string.string,
750                                &data->data.string.size);
751 }
752
753 struct notify2_message_table {
754         const char *name;
755         void (*fn)(struct spoolss_notify_msg *msg,
756                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
757 };
758
759 static struct notify2_message_table printer_notify_table[] = {
760         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
761         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
762         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
763         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
764         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
765         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
766         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
767         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
768         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
769         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
770         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
771         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
772         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
773         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
774         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
775         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
776         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
777         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
778         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
779 };
780
781 static struct notify2_message_table job_notify_table[] = {
782         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
783         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
784         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
785         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
786         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
787         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
788         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
789         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
790         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
791         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
792         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
793         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
794         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
795         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
796         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
797         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
798         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
799         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
800         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
801         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
802         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
803         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
804         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
805         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
806 };
807
808
809 /***********************************************************************
810  Allocate talloc context for container object
811  **********************************************************************/
812
813 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 {
815         if ( !ctr )
816                 return;
817
818         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
819
820         return;
821 }
822
823 /***********************************************************************
824  release all allocated memory and zero out structure
825  **********************************************************************/
826
827 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
828 {
829         if ( !ctr )
830                 return;
831
832         if ( ctr->ctx )
833                 talloc_destroy(ctr->ctx);
834
835         ZERO_STRUCTP(ctr);
836
837         return;
838 }
839
840 /***********************************************************************
841  **********************************************************************/
842
843 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
844 {
845         if ( !ctr )
846                 return NULL;
847
848         return ctr->ctx;
849 }
850
851 /***********************************************************************
852  **********************************************************************/
853
854 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
855 {
856         if ( !ctr || !ctr->msg_groups )
857                 return NULL;
858
859         if ( idx >= ctr->num_groups )
860                 return NULL;
861
862         return &ctr->msg_groups[idx];
863
864 }
865
866 /***********************************************************************
867  How many groups of change messages do we have ?
868  **********************************************************************/
869
870 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
871 {
872         if ( !ctr )
873                 return 0;
874
875         return ctr->num_groups;
876 }
877
878 /***********************************************************************
879  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
880  **********************************************************************/
881
882 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
883 {
884         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
885         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
886         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
887         int                             i, new_slot;
888
889         if ( !ctr || !msg )
890                 return 0;
891
892         /* loop over all groups looking for a matching printer name */
893
894         for ( i=0; i<ctr->num_groups; i++ ) {
895                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
896                         break;
897         }
898
899         /* add a new group? */
900
901         if ( i == ctr->num_groups ) {
902                 ctr->num_groups++;
903
904                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
905                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
906                         return 0;
907                 }
908                 ctr->msg_groups = groups;
909
910                 /* clear the new entry and set the printer name */
911
912                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
913                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
914         }
915
916         /* add the change messages; 'i' is the correct index now regardless */
917
918         msg_grp = &ctr->msg_groups[i];
919
920         msg_grp->num_msgs++;
921
922         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
923                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
924                 return 0;
925         }
926         msg_grp->msgs = msg_list;
927
928         new_slot = msg_grp->num_msgs-1;
929         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
930
931         /* need to allocate own copy of data */
932
933         if ( msg->len != 0 )
934                 msg_grp->msgs[new_slot].notify.data = (char *)
935                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
936
937         return ctr->num_groups;
938 }
939
940 void construct_info_data(struct spoolss_Notify *info_data,
941                          enum spoolss_NotifyType type,
942                          uint16_t field,
943                          int id);
944
945 /***********************************************************************
946  Send a change notication message on all handles which have a call
947  back registered
948  **********************************************************************/
949
950 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
951 {
952         Printer_entry            *p;
953         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
954         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
955         SPOOLSS_NOTIFY_MSG       *messages;
956         int                      sending_msg_count;
957
958         if ( !msg_group ) {
959                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
960                 return;
961         }
962
963         messages = msg_group->msgs;
964
965         if ( !messages ) {
966                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
967                 return;
968         }
969
970         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
971
972         /* loop over all printers */
973
974         for (p = printers_list; p; p = p->next) {
975                 struct spoolss_Notify *notifies;
976                 uint32_t count = 0;
977                 uint32_t id;
978                 int     i;
979
980                 /* Is there notification on this handle? */
981
982                 if ( !p->notify.client_connected )
983                         continue;
984
985                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
986
987                 /* For this printer?  Print servers always receive
988                    notifications. */
989
990                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
991                     ( !strequal(msg_group->printername, p->sharename) ) )
992                         continue;
993
994                 DEBUG(10,("Our printer\n"));
995
996                 /* allocate the max entries possible */
997
998                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
999                 if (!notifies) {
1000                         return;
1001                 }
1002
1003                 /* build the array of change notifications */
1004
1005                 sending_msg_count = 0;
1006
1007                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1008                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1009
1010                         /* Are we monitoring this event? */
1011
1012                         if (!is_monitoring_event(p, msg->type, msg->field))
1013                                 continue;
1014
1015                         sending_msg_count++;
1016
1017
1018                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1019                                 msg->type, msg->field, p->sharename));
1020
1021                         /*
1022                          * if the is a printer notification handle and not a job notification
1023                          * type, then set the id to 0.  Other wise just use what was specified
1024                          * in the message.
1025                          *
1026                          * When registering change notification on a print server handle
1027                          * we always need to send back the id (snum) matching the printer
1028                          * for which the change took place.  For change notify registered
1029                          * on a printer handle, this does not matter and the id should be 0.
1030                          *
1031                          * --jerry
1032                          */
1033
1034                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1035                                 id = 0;
1036                         else
1037                                 id = msg->id;
1038
1039
1040                         /* Convert unix jobid to smb jobid */
1041
1042                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1043                                 id = sysjob_to_jobid(msg->id);
1044
1045                                 if (id == -1) {
1046                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1047                                         goto done;
1048                                 }
1049                         }
1050
1051                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1052
1053                         switch(msg->type) {
1054                         case PRINTER_NOTIFY_TYPE:
1055                                 if ( printer_notify_table[msg->field].fn )
1056                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1057                                 break;
1058
1059                         case JOB_NOTIFY_TYPE:
1060                                 if ( job_notify_table[msg->field].fn )
1061                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1062                                 break;
1063
1064                         default:
1065                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1066                                 goto done;
1067                         }
1068
1069                         count++;
1070                 }
1071
1072                 if ( sending_msg_count ) {
1073                         NTSTATUS status;
1074                         WERROR werr;
1075                         union spoolss_ReplyPrinterInfo info;
1076                         struct spoolss_NotifyInfo info0;
1077                         uint32_t reply_result;
1078
1079                         info0.version   = 0x2;
1080                         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1081                         info0.count     = count;
1082                         info0.notifies  = notifies;
1083
1084                         info.info0 = &info0;
1085
1086                         status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1087                                                                      &p->notify.client_hnd,
1088                                                                      p->notify.change, /* color */
1089                                                                      p->notify.flags,
1090                                                                      &reply_result,
1091                                                                      0, /* reply_type, must be 0 */
1092                                                                      info,
1093                                                                      &werr);
1094                         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1095                                 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1096                                         notify_cli_pipe->srv_name_slash,
1097                                         win_errstr(werr)));
1098                         }
1099                         switch (reply_result) {
1100                                 case 0:
1101                                         break;
1102                                 case PRINTER_NOTIFY_INFO_DISCARDED:
1103                                 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1104                                 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1105                                         break;
1106                                 default:
1107                                         break;
1108                         }
1109                 }
1110         }
1111
1112 done:
1113         DEBUG(8,("send_notify2_changes: Exit...\n"));
1114         return;
1115 }
1116
1117 /***********************************************************************
1118  **********************************************************************/
1119
1120 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1121 {
1122
1123         uint32_t tv_sec, tv_usec;
1124         size_t offset = 0;
1125
1126         /* Unpack message */
1127
1128         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1129                              msg->printer);
1130
1131         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1132                                 &tv_sec, &tv_usec,
1133                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1134
1135         if (msg->len == 0)
1136                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1137                            &msg->notify.value[0], &msg->notify.value[1]);
1138         else
1139                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1140                            &msg->len, &msg->notify.data);
1141
1142         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1143                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1144
1145         tv->tv_sec = tv_sec;
1146         tv->tv_usec = tv_usec;
1147
1148         if (msg->len == 0)
1149                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1150                           msg->notify.value[1]));
1151         else
1152                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1153
1154         return true;
1155 }
1156
1157 /********************************************************************
1158  Receive a notify2 message list
1159  ********************************************************************/
1160
1161 static void receive_notify2_message_list(struct messaging_context *msg,
1162                                          void *private_data,
1163                                          uint32_t msg_type,
1164                                          struct server_id server_id,
1165                                          DATA_BLOB *data)
1166 {
1167         size_t                  msg_count, i;
1168         char                    *buf = (char *)data->data;
1169         char                    *msg_ptr;
1170         size_t                  msg_len;
1171         SPOOLSS_NOTIFY_MSG      notify;
1172         SPOOLSS_NOTIFY_MSG_CTR  messages;
1173         int                     num_groups;
1174
1175         if (data->length < 4) {
1176                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1177                 return;
1178         }
1179
1180         msg_count = IVAL(buf, 0);
1181         msg_ptr = buf + 4;
1182
1183         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1184
1185         if (msg_count == 0) {
1186                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1187                 return;
1188         }
1189
1190         /* initialize the container */
1191
1192         ZERO_STRUCT( messages );
1193         notify_msg_ctr_init( &messages );
1194
1195         /*
1196          * build message groups for each printer identified
1197          * in a change_notify msg.  Remember that a PCN message
1198          * includes the handle returned for the srv_spoolss_replyopenprinter()
1199          * call.  Therefore messages are grouped according to printer handle.
1200          */
1201
1202         for ( i=0; i<msg_count; i++ ) {
1203                 struct timeval msg_tv;
1204
1205                 if (msg_ptr + 4 - buf > data->length) {
1206                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1207                         return;
1208                 }
1209
1210                 msg_len = IVAL(msg_ptr,0);
1211                 msg_ptr += 4;
1212
1213                 if (msg_ptr + msg_len - buf > data->length) {
1214                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1215                         return;
1216                 }
1217
1218                 /* unpack messages */
1219
1220                 ZERO_STRUCT( notify );
1221                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1222                 msg_ptr += msg_len;
1223
1224                 /* add to correct list in container */
1225
1226                 notify_msg_ctr_addmsg( &messages, &notify );
1227
1228                 /* free memory that might have been allocated by notify2_unpack_msg() */
1229
1230                 if ( notify.len != 0 )
1231                         SAFE_FREE( notify.notify.data );
1232         }
1233
1234         /* process each group of messages */
1235
1236         num_groups = notify_msg_ctr_numgroups( &messages );
1237         for ( i=0; i<num_groups; i++ )
1238                 send_notify2_changes( &messages, i );
1239
1240
1241         /* cleanup */
1242
1243         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1244                 (uint32_t)msg_count ));
1245
1246         notify_msg_ctr_destroy( &messages );
1247
1248         return;
1249 }
1250
1251 /********************************************************************
1252  Send a message to ourself about new driver being installed
1253  so we can upgrade the information for each printer bound to this
1254  driver
1255  ********************************************************************/
1256
1257 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1258 {
1259         int len = strlen(drivername);
1260
1261         if (!len)
1262                 return false;
1263
1264         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1265                 drivername));
1266
1267         messaging_send_buf(smbd_messaging_context(),
1268                            messaging_server_id(smbd_messaging_context()),
1269                            MSG_PRINTER_DRVUPGRADE,
1270                            (uint8_t *)drivername, len+1);
1271
1272         return true;
1273 }
1274
1275 /**********************************************************************
1276  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1277  over all printers, upgrading ones as necessary
1278  **********************************************************************/
1279
1280 void do_drv_upgrade_printer(struct messaging_context *msg,
1281                             void *private_data,
1282                             uint32_t msg_type,
1283                             struct server_id server_id,
1284                             DATA_BLOB *data)
1285 {
1286         TALLOC_CTX *tmp_ctx;
1287         struct auth_serversupplied_info *server_info = NULL;
1288         struct spoolss_PrinterInfo2 *pinfo2;
1289         NTSTATUS status;
1290         WERROR result;
1291         const char *drivername;
1292         int snum;
1293         int n_services = lp_numservices();
1294         size_t len;
1295
1296         tmp_ctx = talloc_new(NULL);
1297         if (!tmp_ctx) return;
1298
1299         status = make_server_info_system(tmp_ctx, &server_info);
1300         if (!NT_STATUS_IS_OK(status)) {
1301                 DEBUG(0, ("do_drv_upgrade_printer: "
1302                           "Could not create system server_info\n"));
1303                 goto done;
1304         }
1305
1306         len = MIN(data->length,sizeof(drivername)-1);
1307         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1308         if (!drivername) {
1309                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1310                 goto done;
1311         }
1312
1313         DEBUG(10, ("do_drv_upgrade_printer: "
1314                    "Got message for new driver [%s]\n", drivername));
1315
1316         /* Iterate the printer list */
1317
1318         for (snum = 0; snum < n_services; snum++) {
1319                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1320                         continue;
1321                 }
1322
1323                 result = winreg_get_printer(tmp_ctx, server_info, NULL,
1324                                             lp_const_servicename(snum),
1325                                             &pinfo2);
1326
1327                 if (!W_ERROR_IS_OK(result)) {
1328                         continue;
1329                 }
1330
1331                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1332                         continue;
1333                 }
1334
1335                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1336
1337                 /* all we care about currently is the change_id */
1338                 result = winreg_printer_update_changeid(tmp_ctx,
1339                                                         server_info,
1340                                                         pinfo2->printername);
1341
1342                 if (!W_ERROR_IS_OK(result)) {
1343                         DEBUG(3, ("do_drv_upgrade_printer: "
1344                                   "Failed to update changeid [%s]\n",
1345                                   win_errstr(result)));
1346                 }
1347         }
1348
1349         /* all done */
1350 done:
1351         talloc_free(tmp_ctx);
1352 }
1353
1354 /********************************************************************
1355  Update the cache for all printq's with a registered client
1356  connection
1357  ********************************************************************/
1358
1359 void update_monitored_printq_cache( void )
1360 {
1361         Printer_entry *printer = printers_list;
1362         int snum;
1363
1364         /* loop through all printers and update the cache where
1365            client_connected == true */
1366         while ( printer )
1367         {
1368                 if ( (printer->printer_type == SPLHND_PRINTER)
1369                         && printer->notify.client_connected )
1370                 {
1371                         snum = print_queue_snum(printer->sharename);
1372                         print_queue_status( snum, NULL, NULL );
1373                 }
1374
1375                 printer = printer->next;
1376         }
1377
1378         return;
1379 }
1380
1381 /****************************************************************
1382  _spoolss_OpenPrinter
1383 ****************************************************************/
1384
1385 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1386                             struct spoolss_OpenPrinter *r)
1387 {
1388         struct spoolss_OpenPrinterEx e;
1389         WERROR werr;
1390
1391         ZERO_STRUCT(e.in.userlevel);
1392
1393         e.in.printername        = r->in.printername;
1394         e.in.datatype           = r->in.datatype;
1395         e.in.devmode_ctr        = r->in.devmode_ctr;
1396         e.in.access_mask        = r->in.access_mask;
1397         e.in.level              = 0;
1398
1399         e.out.handle            = r->out.handle;
1400
1401         werr = _spoolss_OpenPrinterEx(p, &e);
1402
1403         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1404                 /* OpenPrinterEx returns this for a bad
1405                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1406                  * instead.
1407                  */
1408                 werr = WERR_INVALID_PRINTER_NAME;
1409         }
1410
1411         return werr;
1412 }
1413
1414 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1415                               struct spoolss_DeviceMode *orig,
1416                               struct spoolss_DeviceMode **dest)
1417 {
1418         struct spoolss_DeviceMode *dm;
1419
1420         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1421         if (!dm) {
1422                 return WERR_NOMEM;
1423         }
1424
1425         /* copy all values, then duplicate strings and structs */
1426         *dm = *orig;
1427
1428         dm->devicename = talloc_strdup(dm, orig->devicename);
1429         if (!dm->devicename) {
1430                 return WERR_NOMEM;
1431         }
1432         dm->formname = talloc_strdup(dm, orig->formname);
1433         if (!dm->formname) {
1434                 return WERR_NOMEM;
1435         }
1436         if (orig->driverextra_data.data) {
1437                 dm->driverextra_data.data =
1438                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1439                                         orig->driverextra_data.length);
1440                 if (!dm->driverextra_data.data) {
1441                         return WERR_NOMEM;
1442                 }
1443         }
1444
1445         *dest = dm;
1446         return WERR_OK;
1447 }
1448
1449 /****************************************************************
1450  _spoolss_OpenPrinterEx
1451 ****************************************************************/
1452
1453 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1454                               struct spoolss_OpenPrinterEx *r)
1455 {
1456         int snum;
1457         Printer_entry *Printer=NULL;
1458
1459         if (!r->in.printername) {
1460                 return WERR_INVALID_PARAM;
1461         }
1462
1463         /* some sanity check because you can open a printer or a print server */
1464         /* aka: \\server\printer or \\server */
1465
1466         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1467
1468         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1469                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1470                         " for printer %s\n", r->in.printername));
1471                 ZERO_STRUCTP(r->out.handle);
1472                 return WERR_INVALID_PARAM;
1473         }
1474
1475         Printer = find_printer_index_by_hnd(p, r->out.handle);
1476         if ( !Printer ) {
1477                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1478                         "handle we created for printer %s\n", r->in.printername));
1479                 close_printer_handle(p, r->out.handle);
1480                 ZERO_STRUCTP(r->out.handle);
1481                 return WERR_INVALID_PARAM;
1482         }
1483
1484         /*
1485          * First case: the user is opening the print server:
1486          *
1487          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1488          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1489          *
1490          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1491          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1492          * or if the user is listed in the smb.conf printer admin parameter.
1493          *
1494          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1495          * client view printer folder, but does not show the MSAPW.
1496          *
1497          * Note: this test needs code to check access rights here too. Jeremy
1498          * could you look at this?
1499          *
1500          * Second case: the user is opening a printer:
1501          * NT doesn't let us connect to a printer if the connecting user
1502          * doesn't have print permission.
1503          *
1504          * Third case: user is opening a Port Monitor
1505          * access checks same as opening a handle to the print server.
1506          */
1507
1508         switch (Printer->printer_type )
1509         {
1510         case SPLHND_SERVER:
1511         case SPLHND_PORTMON_TCP:
1512         case SPLHND_PORTMON_LOCAL:
1513                 /* Printserver handles use global struct... */
1514
1515                 snum = -1;
1516
1517                 /* Map standard access rights to object specific access rights */
1518
1519                 se_map_standard(&r->in.access_mask,
1520                                 &printserver_std_mapping);
1521
1522                 /* Deny any object specific bits that don't apply to print
1523                    servers (i.e printer and job specific bits) */
1524
1525                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1526
1527                 if (r->in.access_mask &
1528                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1529                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1530                         close_printer_handle(p, r->out.handle);
1531                         ZERO_STRUCTP(r->out.handle);
1532                         return WERR_ACCESS_DENIED;
1533                 }
1534
1535                 /* Allow admin access */
1536
1537                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1538                 {
1539                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1540
1541                         if (!lp_ms_add_printer_wizard()) {
1542                                 close_printer_handle(p, r->out.handle);
1543                                 ZERO_STRUCTP(r->out.handle);
1544                                 return WERR_ACCESS_DENIED;
1545                         }
1546
1547                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1548                            and not a printer admin, then fail */
1549
1550                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1551                             !user_has_privileges(p->server_info->ptok,
1552                                                  &se_printop ) &&
1553                             !token_contains_name_in_list(
1554                                     uidtoname(p->server_info->utok.uid),
1555                                     p->server_info->info3->base.domain.string,
1556                                     NULL,
1557                                     p->server_info->ptok,
1558                                     lp_printer_admin(snum))) {
1559                                 close_printer_handle(p, r->out.handle);
1560                                 ZERO_STRUCTP(r->out.handle);
1561                                 return WERR_ACCESS_DENIED;
1562                         }
1563
1564                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1565                 }
1566                 else
1567                 {
1568                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1569                 }
1570
1571                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1572                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1573
1574                 /* We fall through to return WERR_OK */
1575                 break;
1576
1577         case SPLHND_PRINTER:
1578                 /* NT doesn't let us connect to a printer if the connecting user
1579                    doesn't have print permission.  */
1580
1581                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1582                         close_printer_handle(p, r->out.handle);
1583                         ZERO_STRUCTP(r->out.handle);
1584                         return WERR_BADFID;
1585                 }
1586
1587                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1588                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1589                 }
1590
1591                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1592
1593                 /* map an empty access mask to the minimum access mask */
1594                 if (r->in.access_mask == 0x0)
1595                         r->in.access_mask = PRINTER_ACCESS_USE;
1596
1597                 /*
1598                  * If we are not serving the printer driver for this printer,
1599                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1600                  * will keep NT clients happy  --jerry
1601                  */
1602
1603                 if (lp_use_client_driver(snum)
1604                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1605                 {
1606                         r->in.access_mask = PRINTER_ACCESS_USE;
1607                 }
1608
1609                 /* check smb.conf parameters and the the sec_desc */
1610
1611                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1612                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1613                         ZERO_STRUCTP(r->out.handle);
1614                         return WERR_ACCESS_DENIED;
1615                 }
1616
1617                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1618                                    p->server_info->ptok, snum) ||
1619                     !print_access_check(p->server_info, snum,
1620                                         r->in.access_mask)) {
1621                         DEBUG(3, ("access DENIED for printer open\n"));
1622                         close_printer_handle(p, r->out.handle);
1623                         ZERO_STRUCTP(r->out.handle);
1624                         return WERR_ACCESS_DENIED;
1625                 }
1626
1627                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1628                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1629                         close_printer_handle(p, r->out.handle);
1630                         ZERO_STRUCTP(r->out.handle);
1631                         return WERR_ACCESS_DENIED;
1632                 }
1633
1634                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1635                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1636                 else
1637                         r->in.access_mask = PRINTER_ACCESS_USE;
1638
1639                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1640                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1641
1642                 winreg_create_printer(p->mem_ctx,
1643                                       p->server_info,
1644                                       Printer->servername,
1645                                       lp_const_servicename(snum));
1646
1647                 break;
1648
1649         default:
1650                 /* sanity check to prevent programmer error */
1651                 ZERO_STRUCTP(r->out.handle);
1652                 return WERR_BADFID;
1653         }
1654
1655         Printer->access_granted = r->in.access_mask;
1656
1657         /*
1658          * If the client sent a devmode in the OpenPrinter() call, then
1659          * save it here in case we get a job submission on this handle
1660          */
1661
1662          if ((Printer->printer_type != SPLHND_SERVER) &&
1663              r->in.devmode_ctr.devmode) {
1664                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1665                                 &Printer->devmode);
1666          }
1667
1668 #if 0   /* JERRY -- I'm doubtful this is really effective */
1669         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1670            optimization in Windows 2000 clients  --jerry */
1671
1672         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1673                 && (RA_WIN2K == get_remote_arch()) )
1674         {
1675                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1676                 sys_usleep( 500000 );
1677         }
1678 #endif
1679
1680         return WERR_OK;
1681 }
1682
1683 /****************************************************************
1684  _spoolss_ClosePrinter
1685 ****************************************************************/
1686
1687 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1688                              struct spoolss_ClosePrinter *r)
1689 {
1690         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1691
1692         if (Printer && Printer->document_started) {
1693                 struct spoolss_EndDocPrinter e;
1694
1695                 e.in.handle = r->in.handle;
1696
1697                 _spoolss_EndDocPrinter(p, &e);
1698         }
1699
1700         if (!close_printer_handle(p, r->in.handle))
1701                 return WERR_BADFID;
1702
1703         /* clear the returned printer handle.  Observed behavior
1704            from Win2k server.  Don't think this really matters.
1705            Previous code just copied the value of the closed
1706            handle.    --jerry */
1707
1708         ZERO_STRUCTP(r->out.handle);
1709
1710         return WERR_OK;
1711 }
1712
1713 /****************************************************************
1714  _spoolss_DeletePrinter
1715 ****************************************************************/
1716
1717 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1718                               struct spoolss_DeletePrinter *r)
1719 {
1720         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1721         WERROR result;
1722         int snum;
1723
1724         if (Printer && Printer->document_started) {
1725                 struct spoolss_EndDocPrinter e;
1726
1727                 e.in.handle = r->in.handle;
1728
1729                 _spoolss_EndDocPrinter(p, &e);
1730         }
1731
1732         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1733                 winreg_delete_printer_key(p->mem_ctx,
1734                                           p->server_info,
1735                                           lp_const_servicename(snum),
1736                                           "");
1737         }
1738
1739         result = delete_printer_handle(p, r->in.handle);
1740
1741         return result;
1742 }
1743
1744 /*******************************************************************
1745  * static function to lookup the version id corresponding to an
1746  * long architecture string
1747  ******************************************************************/
1748
1749 static const struct print_architecture_table_node archi_table[]= {
1750
1751         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1752         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1753         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1754         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1755         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1756         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1757         {"Windows x64",          SPL_ARCH_X64,          3 },
1758         {NULL,                   "",            -1 }
1759 };
1760
1761 static int get_version_id(const char *arch)
1762 {
1763         int i;
1764
1765         for (i=0; archi_table[i].long_archi != NULL; i++)
1766         {
1767                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1768                         return (archi_table[i].version);
1769         }
1770
1771         return -1;
1772 }
1773
1774 /****************************************************************
1775  _spoolss_DeletePrinterDriver
1776 ****************************************************************/
1777
1778 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1779                                     struct spoolss_DeletePrinterDriver *r)
1780 {
1781
1782         struct spoolss_DriverInfo8 *info = NULL;
1783         struct spoolss_DriverInfo8 *info_win2k = NULL;
1784         int                             version;
1785         WERROR                          status;
1786         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1787
1788         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1789            and not a printer admin, then fail */
1790
1791         if ( (p->server_info->utok.uid != sec_initial_uid())
1792                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1793                 && !token_contains_name_in_list(
1794                         uidtoname(p->server_info->utok.uid),
1795                         p->server_info->info3->base.domain.string,
1796                         NULL,
1797                         p->server_info->ptok,
1798                         lp_printer_admin(-1)) )
1799         {
1800                 return WERR_ACCESS_DENIED;
1801         }
1802
1803         /* check that we have a valid driver name first */
1804
1805         if ((version = get_version_id(r->in.architecture)) == -1)
1806                 return WERR_INVALID_ENVIRONMENT;
1807
1808         status = winreg_get_driver(p->mem_ctx, p->server_info,
1809                                    r->in.architecture, r->in.driver,
1810                                    version, &info);
1811         if (!W_ERROR_IS_OK(status)) {
1812                 /* try for Win2k driver if "Windows NT x86" */
1813
1814                 if ( version == 2 ) {
1815                         version = 3;
1816
1817                         status = winreg_get_driver(p->mem_ctx, p->server_info,
1818                                                    r->in.architecture,
1819                                                    r->in.driver,
1820                                                    version, &info);
1821                         if (!W_ERROR_IS_OK(status)) {
1822                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1823                                 goto done;
1824                         }
1825                 }
1826                 /* otherwise it was a failure */
1827                 else {
1828                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1829                         goto done;
1830                 }
1831
1832         }
1833
1834         if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
1835                 status = WERR_PRINTER_DRIVER_IN_USE;
1836                 goto done;
1837         }
1838
1839         if (version == 2) {
1840                 status = winreg_get_driver(p->mem_ctx, p->server_info,
1841                                            r->in.architecture,
1842                                            r->in.driver, 3, &info_win2k);
1843                 if (W_ERROR_IS_OK(status)) {
1844                         /* if we get to here, we now have 2 driver info structures to remove */
1845                         /* remove the Win2k driver first*/
1846
1847                         status = winreg_del_driver(p->mem_ctx,
1848                                                    p->server_info,
1849                                                    info_win2k, 3);
1850                         talloc_free(info_win2k);
1851
1852                         /* this should not have failed---if it did, report to client */
1853                         if (!W_ERROR_IS_OK(status)) {
1854                                 goto done;
1855                         }
1856                 }
1857         }
1858
1859         status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
1860
1861 done:
1862         talloc_free(info);
1863
1864         return status;
1865 }
1866
1867 /****************************************************************
1868  _spoolss_DeletePrinterDriverEx
1869 ****************************************************************/
1870
1871 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1872                                       struct spoolss_DeletePrinterDriverEx *r)
1873 {
1874         struct spoolss_DriverInfo8      *info = NULL;
1875         struct spoolss_DriverInfo8      *info_win2k = NULL;
1876         int                             version;
1877         bool                            delete_files;
1878         WERROR                          status;
1879         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
1880
1881         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1882            and not a printer admin, then fail */
1883
1884         if ( (p->server_info->utok.uid != sec_initial_uid())
1885                 && !user_has_privileges(p->server_info->ptok, &se_printop )
1886                 && !token_contains_name_in_list(
1887                         uidtoname(p->server_info->utok.uid),
1888                         p->server_info->info3->base.domain.string,
1889                         NULL,
1890                         p->server_info->ptok, lp_printer_admin(-1)) )
1891         {
1892                 return WERR_ACCESS_DENIED;
1893         }
1894
1895         /* check that we have a valid driver name first */
1896         if ((version = get_version_id(r->in.architecture)) == -1) {
1897                 /* this is what NT returns */
1898                 return WERR_INVALID_ENVIRONMENT;
1899         }
1900
1901         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1902                 version = r->in.version;
1903
1904         status = winreg_get_driver(p->mem_ctx, p->server_info,
1905                                    r->in.architecture, r->in.driver,
1906                                    version, &info);
1907         if (!W_ERROR_IS_OK(status)) {
1908                 status = WERR_UNKNOWN_PRINTER_DRIVER;
1909
1910                 /*
1911                  * if the client asked for a specific version,
1912                  * or this is something other than Windows NT x86,
1913                  * then we've failed
1914                  */
1915
1916                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1917                         goto done;
1918
1919                 /* try for Win2k driver if "Windows NT x86" */
1920
1921                 version = 3;
1922                 status = winreg_get_driver(info, p->server_info,
1923                                            r->in.architecture,
1924                                            r->in.driver,
1925                                            version, &info);
1926                 if (!W_ERROR_IS_OK(status)) {
1927                         status = WERR_UNKNOWN_PRINTER_DRIVER;
1928                         goto done;
1929                 }
1930         }
1931
1932         if (printer_driver_in_use(info, p->server_info, info)) {
1933                 status = WERR_PRINTER_DRIVER_IN_USE;
1934                 goto done;
1935         }
1936
1937         /*
1938          * we have a couple of cases to consider.
1939          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
1940          *     then the delete should fail if **any** files overlap with
1941          *     other drivers
1942          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1943          *     non-overlapping files
1944          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1945          *     is set, the do not delete any files
1946          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1947          */
1948
1949         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1950
1951         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1952
1953         if (delete_files &&
1954             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1955             printer_driver_files_in_use(info, p->server_info, info)) {
1956                 /* no idea of the correct error here */
1957                 status = WERR_ACCESS_DENIED;
1958                 goto done;
1959         }
1960
1961
1962         /* also check for W32X86/3 if necessary; maybe we already have? */
1963
1964         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
1965                 status = winreg_get_driver(info, p->server_info,
1966                                            r->in.architecture,
1967                                            r->in.driver, 3, &info_win2k);
1968                 if (W_ERROR_IS_OK(status)) {
1969
1970                         if (delete_files &&
1971                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
1972                             printer_driver_files_in_use(info, p->server_info,
1973                                                         info_win2k)) {
1974                                 /* no idea of the correct error here */
1975                                 talloc_free(info_win2k);
1976                                 status = WERR_ACCESS_DENIED;
1977                                 goto done;
1978                         }
1979
1980                         /* if we get to here, we now have 2 driver info structures to remove */
1981                         /* remove the Win2k driver first*/
1982
1983                         status = winreg_del_driver(info, p->server_info,
1984                                                    info_win2k, 3);
1985
1986                         /* this should not have failed---if it did, report to client */
1987
1988                         if (!W_ERROR_IS_OK(status)) {
1989                                 goto done;
1990                         }
1991
1992                         /*
1993                          * now delete any associated files if delete_files is
1994                          * true. Even if this part failes, we return succes
1995                          * because the driver doesn not exist any more
1996                          */
1997                         if (delete_files) {
1998                                 delete_driver_files(p->server_info,
1999                                                     info_win2k);
2000                         }
2001                 }
2002         }
2003
2004         status = winreg_del_driver(info, p->server_info, info, version);
2005         if (!W_ERROR_IS_OK(status)) {
2006                 goto done;
2007         }
2008
2009         /*
2010          * now delete any associated files if delete_files is
2011          * true. Even if this part failes, we return succes
2012          * because the driver doesn not exist any more
2013          */
2014         if (delete_files) {
2015                 delete_driver_files(p->server_info, info);
2016         }
2017
2018 done:
2019         talloc_free(info);
2020         return status;
2021 }
2022
2023
2024 /****************************************************************************
2025  Internal routine for storing printerdata
2026  ***************************************************************************/
2027
2028 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2029                           const char *key, const char *value,
2030                           uint32_t type, uint8_t *data, int real_len)
2031 {
2032         /* the registry objects enforce uniqueness based on value name */
2033
2034         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2035 }
2036
2037 /********************************************************************
2038  GetPrinterData on a printer server Handle.
2039 ********************************************************************/
2040
2041 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2042                                             const char *value,
2043                                             enum winreg_Type *type,
2044                                             union spoolss_PrinterData *data)
2045 {
2046         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2047
2048         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2049                 *type = REG_DWORD;
2050                 data->value = 0x00;
2051                 return WERR_OK;
2052         }
2053
2054         if (!StrCaseCmp(value, "BeepEnabled")) {
2055                 *type = REG_DWORD;
2056                 data->value = 0x00;
2057                 return WERR_OK;
2058         }
2059
2060         if (!StrCaseCmp(value, "EventLog")) {
2061                 *type = REG_DWORD;
2062                 /* formally was 0x1b */
2063                 data->value = 0x00;
2064                 return WERR_OK;
2065         }
2066
2067         if (!StrCaseCmp(value, "NetPopup")) {
2068                 *type = REG_DWORD;
2069                 data->value = 0x00;
2070                 return WERR_OK;
2071         }
2072
2073         if (!StrCaseCmp(value, "MajorVersion")) {
2074                 *type = REG_DWORD;
2075
2076                 /* Windows NT 4.0 seems to not allow uploading of drivers
2077                    to a server that reports 0x3 as the MajorVersion.
2078                    need to investigate more how Win2k gets around this .
2079                    -- jerry */
2080
2081                 if (RA_WINNT == get_remote_arch()) {
2082                         data->value = 0x02;
2083                 } else {
2084                         data->value = 0x03;
2085                 }
2086
2087                 return WERR_OK;
2088         }
2089
2090         if (!StrCaseCmp(value, "MinorVersion")) {
2091                 *type = REG_DWORD;
2092                 data->value = 0x00;
2093                 return WERR_OK;
2094         }
2095
2096         /* REG_BINARY
2097          *  uint32_t size        = 0x114
2098          *  uint32_t major       = 5
2099          *  uint32_t minor       = [0|1]
2100          *  uint32_t build       = [2195|2600]
2101          *  extra unicode string = e.g. "Service Pack 3"
2102          */
2103         if (!StrCaseCmp(value, "OSVersion")) {
2104                 DATA_BLOB blob;
2105                 enum ndr_err_code ndr_err;
2106                 struct spoolss_OSVersion os;
2107
2108                 os.major                = 5;    /* Windows 2000 == 5.0 */
2109                 os.minor                = 0;
2110                 os.build                = 2195; /* build */
2111                 os.extra_string         = "";   /* leave extra string empty */
2112
2113                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2114                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2115                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2116                         return WERR_GENERAL_FAILURE;
2117                 }
2118
2119                 *type = REG_BINARY;
2120                 data->binary = blob;
2121
2122                 return WERR_OK;
2123         }
2124
2125
2126         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2127                 *type = REG_SZ;
2128
2129                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2130                 W_ERROR_HAVE_NO_MEMORY(data->string);
2131
2132                 return WERR_OK;
2133         }
2134
2135         if (!StrCaseCmp(value, "Architecture")) {
2136                 *type = REG_SZ;
2137                 data->string = talloc_strdup(mem_ctx,
2138                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2139                 W_ERROR_HAVE_NO_MEMORY(data->string);
2140
2141                 return WERR_OK;
2142         }
2143
2144         if (!StrCaseCmp(value, "DsPresent")) {
2145                 *type = REG_DWORD;
2146
2147                 /* only show the publish check box if we are a
2148                    member of a AD domain */
2149
2150                 if (lp_security() == SEC_ADS) {
2151                         data->value = 0x01;
2152                 } else {
2153                         data->value = 0x00;
2154                 }
2155                 return WERR_OK;
2156         }
2157
2158         if (!StrCaseCmp(value, "DNSMachineName")) {
2159                 const char *hostname = get_mydnsfullname();
2160
2161                 if (!hostname) {
2162                         return WERR_BADFILE;
2163                 }
2164
2165                 *type = REG_SZ;
2166                 data->string = talloc_strdup(mem_ctx, hostname);
2167                 W_ERROR_HAVE_NO_MEMORY(data->string);
2168
2169                 return WERR_OK;
2170         }
2171
2172         *type = REG_NONE;
2173
2174         return WERR_INVALID_PARAM;
2175 }
2176
2177 /****************************************************************
2178  _spoolss_GetPrinterData
2179 ****************************************************************/
2180
2181 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2182                                struct spoolss_GetPrinterData *r)
2183 {
2184         struct spoolss_GetPrinterDataEx r2;
2185
2186         r2.in.handle            = r->in.handle;
2187         r2.in.key_name          = "PrinterDriverData";
2188         r2.in.value_name        = r->in.value_name;
2189         r2.in.offered           = r->in.offered;
2190         r2.out.type             = r->out.type;
2191         r2.out.data             = r->out.data;
2192         r2.out.needed           = r->out.needed;
2193
2194         return _spoolss_GetPrinterDataEx(p, &r2);
2195 }
2196
2197 /*********************************************************
2198  Connect to the client machine.
2199 **********************************************************/
2200
2201 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2202                         struct sockaddr_storage *client_ss, const char *remote_machine)
2203 {
2204         NTSTATUS ret;
2205         struct cli_state *the_cli;
2206         struct sockaddr_storage rm_addr;
2207         char addr[INET6_ADDRSTRLEN];
2208
2209         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2210                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2211                         remote_machine));
2212                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2213                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2214                         return false;
2215                 }
2216                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2217         } else {
2218                 rm_addr = *client_ss;
2219                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2220                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2221                         addr));
2222         }
2223
2224         if (ismyaddr((struct sockaddr *)&rm_addr)) {
2225                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2226                         addr));
2227                 return false;
2228         }
2229
2230         /* setup the connection */
2231         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2232                 &rm_addr, 0, "IPC$", "IPC",
2233                 "", /* username */
2234                 "", /* domain */
2235                 "", /* password */
2236                 0, lp_client_signing(), NULL );
2237
2238         if ( !NT_STATUS_IS_OK( ret ) ) {
2239                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2240                         remote_machine ));
2241                 return false;
2242         }
2243
2244         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2245                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2246                 cli_shutdown(the_cli);
2247                 return false;
2248         }
2249
2250         /*
2251          * Ok - we have an anonymous connection to the IPC$ share.
2252          * Now start the NT Domain stuff :-).
2253          */
2254
2255         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2256         if (!NT_STATUS_IS_OK(ret)) {
2257                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2258                         remote_machine, nt_errstr(ret)));
2259                 cli_shutdown(the_cli);
2260                 return false;
2261         }
2262
2263         return true;
2264 }
2265
2266 /***************************************************************************
2267  Connect to the client.
2268 ****************************************************************************/
2269
2270 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2271                                         uint32_t localprinter, uint32_t type,
2272                                         struct policy_handle *handle,
2273                                         struct sockaddr_storage *client_ss)
2274 {
2275         WERROR result;
2276         NTSTATUS status;
2277
2278         /*
2279          * If it's the first connection, contact the client
2280          * and connect to the IPC$ share anonymously
2281          */
2282         if (smb_connections==0) {
2283                 fstring unix_printer;
2284
2285                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2286
2287                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2288                         return false;
2289
2290                 messaging_register(smbd_messaging_context(), NULL,
2291                                    MSG_PRINTER_NOTIFY2,
2292                                    receive_notify2_message_list);
2293                 /* Tell the connections db we're now interested in printer
2294                  * notify messages. */
2295                 serverid_register_msg_flags(
2296                         messaging_server_id(smbd_messaging_context()),
2297                         true, FLAG_MSG_PRINT_NOTIFY);
2298         }
2299
2300         /*
2301          * Tell the specific printing tdb we want messages for this printer
2302          * by registering our PID.
2303          */
2304
2305         if (!print_notify_register_pid(snum))
2306                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2307
2308         smb_connections++;
2309
2310         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2311                                                  printer,
2312                                                  localprinter,
2313                                                  type,
2314                                                  0,
2315                                                  NULL,
2316                                                  handle,
2317                                                  &result);
2318         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2319                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2320                         win_errstr(result)));
2321
2322         return (W_ERROR_IS_OK(result));
2323 }
2324
2325 /****************************************************************
2326  ****************************************************************/
2327
2328 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2329                                                              const struct spoolss_NotifyOption *r)
2330 {
2331         struct spoolss_NotifyOption *option;
2332         uint32_t i,k;
2333
2334         if (!r) {
2335                 return NULL;
2336         }
2337
2338         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2339         if (!option) {
2340                 return NULL;
2341         }
2342
2343         *option = *r;
2344
2345         if (!option->count) {
2346                 return option;
2347         }
2348
2349         option->types = talloc_zero_array(option,
2350                 struct spoolss_NotifyOptionType, option->count);
2351         if (!option->types) {
2352                 talloc_free(option);
2353                 return NULL;
2354         }
2355
2356         for (i=0; i < option->count; i++) {
2357                 option->types[i] = r->types[i];
2358
2359                 if (option->types[i].count) {
2360                         option->types[i].fields = talloc_zero_array(option,
2361                                 union spoolss_Field, option->types[i].count);
2362                         if (!option->types[i].fields) {
2363                                 talloc_free(option);
2364                                 return NULL;
2365                         }
2366                         for (k=0; k<option->types[i].count; k++) {
2367                                 option->types[i].fields[k] =
2368                                         r->types[i].fields[k];
2369                         }
2370                 }
2371         }
2372
2373         return option;
2374 }
2375
2376 /****************************************************************
2377  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2378  *
2379  * before replying OK: status=0 a rpc call is made to the workstation
2380  * asking ReplyOpenPrinter
2381  *
2382  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2383  * called from api_spoolss_rffpcnex
2384 ****************************************************************/
2385
2386 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2387                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2388 {
2389         int snum = -1;
2390         struct spoolss_NotifyOption *option = r->in.notify_options;
2391         struct sockaddr_storage client_ss;
2392
2393         /* store the notify value in the printer struct */
2394
2395         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2396
2397         if (!Printer) {
2398                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2399                         "Invalid handle (%s:%u:%u).\n",
2400                         OUR_HANDLE(r->in.handle)));
2401                 return WERR_BADFID;
2402         }
2403
2404         Printer->notify.flags           = r->in.flags;
2405         Printer->notify.options         = r->in.options;
2406         Printer->notify.printerlocal    = r->in.printer_local;
2407
2408         TALLOC_FREE(Printer->notify.option);
2409         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2410
2411         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2412
2413         /* Connect to the client machine and send a ReplyOpenPrinter */
2414
2415         if ( Printer->printer_type == SPLHND_SERVER)
2416                 snum = -1;
2417         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2418                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2419                 return WERR_BADFID;
2420
2421         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2422                 "client_address is %s\n", p->client_address));
2423
2424         if (!interpret_string_addr(&client_ss, p->client_address,
2425                                    AI_NUMERICHOST)) {
2426                 return WERR_SERVER_UNAVAILABLE;
2427         }
2428
2429         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2430                                         Printer->notify.printerlocal, 1,
2431                                         &Printer->notify.client_hnd, &client_ss))
2432                 return WERR_SERVER_UNAVAILABLE;
2433
2434         Printer->notify.client_connected = true;
2435
2436         return WERR_OK;
2437 }
2438
2439 /*******************************************************************
2440  * fill a notify_info_data with the servername
2441  ********************************************************************/
2442
2443 static void spoolss_notify_server_name(int snum,
2444                                        struct spoolss_Notify *data,
2445                                        print_queue_struct *queue,
2446                                        NT_PRINTER_INFO_LEVEL *printer,
2447                                        TALLOC_CTX *mem_ctx)
2448 {
2449         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2450 }
2451
2452 /*******************************************************************
2453  * fill a notify_info_data with the printername (not including the servername).
2454  ********************************************************************/
2455
2456 static void spoolss_notify_printer_name(int snum,
2457                                         struct spoolss_Notify *data,
2458                                         print_queue_struct *queue,
2459                                         NT_PRINTER_INFO_LEVEL *printer,
2460                                         TALLOC_CTX *mem_ctx)
2461 {
2462         /* the notify name should not contain the \\server\ part */
2463         char *p = strrchr(printer->info_2->printername, '\\');
2464
2465         if (!p) {
2466                 p = printer->info_2->printername;
2467         } else {
2468                 p++;
2469         }
2470
2471         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2472 }
2473
2474 /*******************************************************************
2475  * fill a notify_info_data with the servicename
2476  ********************************************************************/
2477
2478 static void spoolss_notify_share_name(int snum,
2479                                       struct spoolss_Notify *data,
2480                                       print_queue_struct *queue,
2481                                       NT_PRINTER_INFO_LEVEL *printer,
2482                                       TALLOC_CTX *mem_ctx)
2483 {
2484         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2485 }
2486
2487 /*******************************************************************
2488  * fill a notify_info_data with the port name
2489  ********************************************************************/
2490
2491 static void spoolss_notify_port_name(int snum,
2492                                      struct spoolss_Notify *data,
2493                                      print_queue_struct *queue,
2494                                      NT_PRINTER_INFO_LEVEL *printer,
2495                                      TALLOC_CTX *mem_ctx)
2496 {
2497         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2498 }
2499
2500 /*******************************************************************
2501  * fill a notify_info_data with the printername
2502  * but it doesn't exist, have to see what to do
2503  ********************************************************************/
2504
2505 static void spoolss_notify_driver_name(int snum,
2506                                        struct spoolss_Notify *data,
2507                                        print_queue_struct *queue,
2508                                        NT_PRINTER_INFO_LEVEL *printer,
2509                                        TALLOC_CTX *mem_ctx)
2510 {
2511         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2512 }
2513
2514 /*******************************************************************
2515  * fill a notify_info_data with the comment
2516  ********************************************************************/
2517
2518 static void spoolss_notify_comment(int snum,
2519                                    struct spoolss_Notify *data,
2520                                    print_queue_struct *queue,
2521                                    NT_PRINTER_INFO_LEVEL *printer,
2522                                    TALLOC_CTX *mem_ctx)
2523 {
2524         char *p;
2525
2526         if (*printer->info_2->comment == '\0') {
2527                 p = lp_comment(snum);
2528         } else {
2529                 p = printer->info_2->comment;
2530         }
2531
2532         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2533 }
2534
2535 /*******************************************************************
2536  * fill a notify_info_data with the comment
2537  * location = "Room 1, floor 2, building 3"
2538  ********************************************************************/
2539
2540 static void spoolss_notify_location(int snum,
2541                                     struct spoolss_Notify *data,
2542                                     print_queue_struct *queue,
2543                                     NT_PRINTER_INFO_LEVEL *printer,
2544                                     TALLOC_CTX *mem_ctx)
2545 {
2546         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2547 }
2548
2549 /*******************************************************************
2550  * fill a notify_info_data with the device mode
2551  * jfm:xxxx don't to it for know but that's a real problem !!!
2552  ********************************************************************/
2553
2554 static void spoolss_notify_devmode(int snum,
2555                                    struct spoolss_Notify *data,
2556                                    print_queue_struct *queue,
2557                                    NT_PRINTER_INFO_LEVEL *printer,
2558                                    TALLOC_CTX *mem_ctx)
2559 {
2560         /* for a dummy implementation we have to zero the fields */
2561         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2562 }
2563
2564 /*******************************************************************
2565  * fill a notify_info_data with the separator file name
2566  ********************************************************************/
2567
2568 static void spoolss_notify_sepfile(int snum,
2569                                    struct spoolss_Notify *data,
2570                                    print_queue_struct *queue,
2571                                    NT_PRINTER_INFO_LEVEL *printer,
2572                                    TALLOC_CTX *mem_ctx)
2573 {
2574         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2575 }
2576
2577 /*******************************************************************
2578  * fill a notify_info_data with the print processor
2579  * jfm:xxxx return always winprint to indicate we don't do anything to it
2580  ********************************************************************/
2581
2582 static void spoolss_notify_print_processor(int snum,
2583                                            struct spoolss_Notify *data,
2584                                            print_queue_struct *queue,
2585                                            NT_PRINTER_INFO_LEVEL *printer,
2586                                            TALLOC_CTX *mem_ctx)
2587 {
2588         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2589 }
2590
2591 /*******************************************************************
2592  * fill a notify_info_data with the print processor options
2593  * jfm:xxxx send an empty string
2594  ********************************************************************/
2595
2596 static void spoolss_notify_parameters(int snum,
2597                                       struct spoolss_Notify *data,
2598                                       print_queue_struct *queue,
2599                                       NT_PRINTER_INFO_LEVEL *printer,
2600                                       TALLOC_CTX *mem_ctx)
2601 {
2602         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2603 }
2604
2605 /*******************************************************************
2606  * fill a notify_info_data with the data type
2607  * jfm:xxxx always send RAW as data type
2608  ********************************************************************/
2609
2610 static void spoolss_notify_datatype(int snum,
2611                                     struct spoolss_Notify *data,
2612                                     print_queue_struct *queue,
2613                                     NT_PRINTER_INFO_LEVEL *printer,
2614                                     TALLOC_CTX *mem_ctx)
2615 {
2616         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2617 }
2618
2619 /*******************************************************************
2620  * fill a notify_info_data with the security descriptor
2621  * jfm:xxxx send an null pointer to say no security desc
2622  * have to implement security before !
2623  ********************************************************************/
2624
2625 static void spoolss_notify_security_desc(int snum,
2626                                          struct spoolss_Notify *data,
2627                                          print_queue_struct *queue,
2628                                          NT_PRINTER_INFO_LEVEL *printer,
2629                                          TALLOC_CTX *mem_ctx)
2630 {
2631         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2632                                           printer->info_2->secdesc_buf->sd_size,
2633                                           printer->info_2->secdesc_buf->sd);
2634 }
2635
2636 /*******************************************************************
2637  * fill a notify_info_data with the attributes
2638  * jfm:xxxx a samba printer is always shared
2639  ********************************************************************/
2640
2641 static void spoolss_notify_attributes(int snum,
2642                                       struct spoolss_Notify *data,
2643                                       print_queue_struct *queue,
2644                                       NT_PRINTER_INFO_LEVEL *printer,
2645                                       TALLOC_CTX *mem_ctx)
2646 {
2647         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2648 }
2649
2650 /*******************************************************************
2651  * fill a notify_info_data with the priority
2652  ********************************************************************/
2653
2654 static void spoolss_notify_priority(int snum,
2655                                     struct spoolss_Notify *data,
2656                                     print_queue_struct *queue,
2657                                     NT_PRINTER_INFO_LEVEL *printer,
2658                                     TALLOC_CTX *mem_ctx)
2659 {
2660         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2661 }
2662
2663 /*******************************************************************
2664  * fill a notify_info_data with the default priority
2665  ********************************************************************/
2666
2667 static void spoolss_notify_default_priority(int snum,
2668                                             struct spoolss_Notify *data,
2669                                             print_queue_struct *queue,
2670                                             NT_PRINTER_INFO_LEVEL *printer,
2671                                             TALLOC_CTX *mem_ctx)
2672 {
2673         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2674 }
2675
2676 /*******************************************************************
2677  * fill a notify_info_data with the start time
2678  ********************************************************************/
2679
2680 static void spoolss_notify_start_time(int snum,
2681                                       struct spoolss_Notify *data,
2682                                       print_queue_struct *queue,
2683                                       NT_PRINTER_INFO_LEVEL *printer,
2684                                       TALLOC_CTX *mem_ctx)
2685 {
2686         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2687 }
2688
2689 /*******************************************************************
2690  * fill a notify_info_data with the until time
2691  ********************************************************************/
2692
2693 static void spoolss_notify_until_time(int snum,
2694                                       struct spoolss_Notify *data,
2695                                       print_queue_struct *queue,
2696                                       NT_PRINTER_INFO_LEVEL *printer,
2697                                       TALLOC_CTX *mem_ctx)
2698 {
2699         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2700 }
2701
2702 /*******************************************************************
2703  * fill a notify_info_data with the status
2704  ********************************************************************/
2705
2706 static void spoolss_notify_status(int snum,
2707                                   struct spoolss_Notify *data,
2708                                   print_queue_struct *queue,
2709                                   NT_PRINTER_INFO_LEVEL *printer,
2710                                   TALLOC_CTX *mem_ctx)
2711 {
2712         print_status_struct status;
2713
2714         print_queue_length(snum, &status);
2715         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2716 }
2717
2718 /*******************************************************************
2719  * fill a notify_info_data with the number of jobs queued
2720  ********************************************************************/
2721
2722 static void spoolss_notify_cjobs(int snum,
2723                                  struct spoolss_Notify *data,
2724                                  print_queue_struct *queue,
2725                                  NT_PRINTER_INFO_LEVEL *printer,
2726                                  TALLOC_CTX *mem_ctx)
2727 {
2728         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2729 }
2730
2731 /*******************************************************************
2732  * fill a notify_info_data with the average ppm
2733  ********************************************************************/
2734
2735 static void spoolss_notify_average_ppm(int snum,
2736                                        struct spoolss_Notify *data,
2737                                        print_queue_struct *queue,
2738                                        NT_PRINTER_INFO_LEVEL *printer,
2739                                        TALLOC_CTX *mem_ctx)
2740 {
2741         /* always respond 8 pages per minutes */
2742         /* a little hard ! */
2743         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2744 }
2745
2746 /*******************************************************************
2747  * fill a notify_info_data with username
2748  ********************************************************************/
2749
2750 static void spoolss_notify_username(int snum,
2751                                     struct spoolss_Notify *data,
2752                                     print_queue_struct *queue,
2753                                     NT_PRINTER_INFO_LEVEL *printer,
2754                                     TALLOC_CTX *mem_ctx)
2755 {
2756         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2757 }
2758
2759 /*******************************************************************
2760  * fill a notify_info_data with job status
2761  ********************************************************************/
2762
2763 static void spoolss_notify_job_status(int snum,
2764                                       struct spoolss_Notify *data,
2765                                       print_queue_struct *queue,
2766                                       NT_PRINTER_INFO_LEVEL *printer,
2767                                       TALLOC_CTX *mem_ctx)
2768 {
2769         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2770 }
2771
2772 /*******************************************************************
2773  * fill a notify_info_data with job name
2774  ********************************************************************/
2775
2776 static void spoolss_notify_job_name(int snum,
2777                                     struct spoolss_Notify *data,
2778                                     print_queue_struct *queue,
2779                                     NT_PRINTER_INFO_LEVEL *printer,
2780                                     TALLOC_CTX *mem_ctx)
2781 {
2782         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2783 }
2784
2785 /*******************************************************************
2786  * fill a notify_info_data with job status
2787  ********************************************************************/
2788
2789 static void spoolss_notify_job_status_string(int snum,
2790                                              struct spoolss_Notify *data,
2791                                              print_queue_struct *queue,
2792                                              NT_PRINTER_INFO_LEVEL *printer,
2793                                              TALLOC_CTX *mem_ctx)
2794 {
2795         /*
2796          * Now we're returning job status codes we just return a "" here. JRA.
2797          */
2798
2799         const char *p = "";
2800
2801 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2802         p = "unknown";
2803
2804         switch (queue->status) {
2805         case LPQ_QUEUED:
2806                 p = "Queued";
2807                 break;
2808         case LPQ_PAUSED:
2809                 p = "";    /* NT provides the paused string */
2810                 break;
2811         case LPQ_SPOOLING:
2812                 p = "Spooling";
2813                 break;
2814         case LPQ_PRINTING:
2815                 p = "Printing";
2816                 break;
2817         }
2818 #endif /* NO LONGER NEEDED. */
2819
2820         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2821 }
2822
2823 /*******************************************************************
2824  * fill a notify_info_data with job time
2825  ********************************************************************/
2826
2827 static void spoolss_notify_job_time(int snum,
2828                                     struct spoolss_Notify *data,
2829                                     print_queue_struct *queue,
2830                                     NT_PRINTER_INFO_LEVEL *printer,
2831                                     TALLOC_CTX *mem_ctx)
2832 {
2833         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2834 }
2835
2836 /*******************************************************************
2837  * fill a notify_info_data with job size
2838  ********************************************************************/
2839
2840 static void spoolss_notify_job_size(int snum,
2841                                     struct spoolss_Notify *data,
2842                                     print_queue_struct *queue,
2843                                     NT_PRINTER_INFO_LEVEL *printer,
2844                                     TALLOC_CTX *mem_ctx)
2845 {
2846         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2847 }
2848
2849 /*******************************************************************
2850  * fill a notify_info_data with page info
2851  ********************************************************************/
2852 static void spoolss_notify_total_pages(int snum,
2853                                 struct spoolss_Notify *data,
2854                                 print_queue_struct *queue,
2855                                 NT_PRINTER_INFO_LEVEL *printer,
2856                                 TALLOC_CTX *mem_ctx)
2857 {
2858         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2859 }
2860
2861 /*******************************************************************
2862  * fill a notify_info_data with pages printed info.
2863  ********************************************************************/
2864 static void spoolss_notify_pages_printed(int snum,
2865                                 struct spoolss_Notify *data,
2866                                 print_queue_struct *queue,
2867                                 NT_PRINTER_INFO_LEVEL *printer,
2868                                 TALLOC_CTX *mem_ctx)
2869 {
2870         /* Add code when back-end tracks this */
2871         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2872 }
2873
2874 /*******************************************************************
2875  Fill a notify_info_data with job position.
2876  ********************************************************************/
2877
2878 static void spoolss_notify_job_position(int snum,
2879                                         struct spoolss_Notify *data,
2880                                         print_queue_struct *queue,
2881                                         NT_PRINTER_INFO_LEVEL *printer,
2882                                         TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2885 }
2886
2887 /*******************************************************************
2888  Fill a notify_info_data with submitted time.
2889  ********************************************************************/
2890
2891 static void spoolss_notify_submitted_time(int snum,
2892                                           struct spoolss_Notify *data,
2893                                           print_queue_struct *queue,
2894                                           NT_PRINTER_INFO_LEVEL *printer,
2895                                           TALLOC_CTX *mem_ctx)
2896 {
2897         data->data.string.string = NULL;
2898         data->data.string.size = 0;
2899
2900         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2901                                &data->data.string.string,
2902                                &data->data.string.size);
2903
2904 }
2905
2906 struct s_notify_info_data_table
2907 {
2908         enum spoolss_NotifyType type;
2909         uint16_t field;
2910         const char *name;
2911         enum spoolss_NotifyTable variable_type;
2912         void (*fn) (int snum, struct spoolss_Notify *data,
2913                     print_queue_struct *queue,
2914                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2915 };
2916
2917 /* A table describing the various print notification constants and
2918    whether the notification data is a pointer to a variable sized
2919    buffer, a one value uint32_t or a two value uint32_t. */
2920
2921 static const struct s_notify_info_data_table notify_info_data_table[] =
2922 {
2923 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2924 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2925 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
2926 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2927 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2928 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
2929 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
2930 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2931 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
2932 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2933 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2934 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2935 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
2936 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
2937 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2938 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
2939 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2940 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2941 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
2942 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
2943 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
2944 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
2945 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
2946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
2949 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
2950 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
2951 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
2952 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
2953 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
2954 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
2955 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
2956 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
2957 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
2958 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
2959 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
2960 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
2961 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
2962 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
2963 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
2964 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
2965 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
2966 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
2967 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
2968 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
2969 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
2970 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
2971 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
2972 };
2973
2974 /*******************************************************************
2975  Return the variable_type of info_data structure.
2976 ********************************************************************/
2977
2978 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2979                                                   uint16_t field)
2980 {
2981         int i=0;
2982
2983         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
2984                 if ( (notify_info_data_table[i].type == type) &&
2985                      (notify_info_data_table[i].field == field) ) {
2986                         return notify_info_data_table[i].variable_type;
2987                 }
2988         }
2989
2990         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
2991
2992         return 0;
2993 }
2994
2995 /****************************************************************************
2996 ****************************************************************************/
2997
2998 static bool search_notify(enum spoolss_NotifyType type,
2999                           uint16_t field,
3000                           int *value)
3001 {
3002         int i;
3003
3004         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3005                 if (notify_info_data_table[i].type == type &&
3006                     notify_info_data_table[i].field == field &&
3007                     notify_info_data_table[i].fn != NULL) {
3008                         *value = i;
3009                         return true;
3010                 }
3011         }
3012
3013         return false;
3014 }
3015
3016 /****************************************************************************
3017 ****************************************************************************/
3018
3019 void construct_info_data(struct spoolss_Notify *info_data,
3020                          enum spoolss_NotifyType type,
3021                          uint16_t field,
3022                          int id)
3023 {
3024         info_data->type                 = type;
3025         info_data->field.field          = field;
3026         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3027         info_data->job_id               = id;
3028 }
3029
3030 /*******************************************************************
3031  *
3032  * fill a notify_info struct with info asked
3033  *
3034  ********************************************************************/
3035
3036 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3037                                           struct spoolss_NotifyInfo *info,
3038                                           int snum,
3039                                           const struct spoolss_NotifyOptionType *option_type,
3040                                           uint32_t id,
3041                                           TALLOC_CTX *mem_ctx)
3042 {
3043         int field_num,j;
3044         enum spoolss_NotifyType type;
3045         uint16_t field;
3046
3047         struct spoolss_Notify *current_data;
3048         NT_PRINTER_INFO_LEVEL *printer = NULL;
3049         print_queue_struct *queue=NULL;
3050
3051         type = option_type->type;
3052
3053         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3054                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3055                 option_type->count, lp_servicename(snum)));
3056
3057         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3058                 return false;
3059
3060         for(field_num=0; field_num < option_type->count; field_num++) {
3061                 field = option_type->fields[field_num].field;
3062
3063                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3064
3065                 if (!search_notify(type, field, &j) )
3066                         continue;
3067
3068                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3069                                                       struct spoolss_Notify,
3070                                                       info->count + 1);
3071                 if (info->notifies == NULL) {
3072                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3073                         free_a_printer(&printer, 2);
3074                         return false;
3075                 }
3076
3077                 current_data = &info->notifies[info->count];
3078
3079                 construct_info_data(current_data, type, field, id);
3080
3081                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3082                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3083
3084                 notify_info_data_table[j].fn(snum, current_data, queue,
3085                                              printer, mem_ctx);
3086
3087                 info->count++;
3088         }
3089
3090         free_a_printer(&printer, 2);
3091         return true;
3092 }
3093
3094 /*******************************************************************
3095  *
3096  * fill a notify_info struct with info asked
3097  *
3098  ********************************************************************/
3099
3100 static bool construct_notify_jobs_info(print_queue_struct *queue,
3101                                        struct spoolss_NotifyInfo *info,
3102                                        NT_PRINTER_INFO_LEVEL *printer,
3103                                        int snum,
3104                                        const struct spoolss_NotifyOptionType *option_type,
3105                                        uint32_t id,
3106                                        TALLOC_CTX *mem_ctx)
3107 {
3108         int field_num,j;
3109         enum spoolss_NotifyType type;
3110         uint16_t field;
3111         struct spoolss_Notify *current_data;
3112
3113         DEBUG(4,("construct_notify_jobs_info\n"));
3114
3115         type = option_type->type;
3116
3117         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3118                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3119                 option_type->count));
3120
3121         for(field_num=0; field_num<option_type->count; field_num++) {
3122                 field = option_type->fields[field_num].field;
3123
3124                 if (!search_notify(type, field, &j) )
3125                         continue;
3126
3127                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3128                                                       struct spoolss_Notify,
3129                                                       info->count + 1);
3130                 if (info->notifies == NULL) {
3131                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3132                         return false;
3133                 }
3134
3135                 current_data=&(info->notifies[info->count]);
3136
3137                 construct_info_data(current_data, type, field, id);
3138                 notify_info_data_table[j].fn(snum, current_data, queue,
3139                                              printer, mem_ctx);
3140                 info->count++;
3141         }
3142
3143         return true;
3144 }
3145
3146 /*
3147  * JFM: The enumeration is not that simple, it's even non obvious.
3148  *
3149  * let's take an example: I want to monitor the PRINTER SERVER for
3150  * the printer's name and the number of jobs currently queued.
3151  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3152  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3153  *
3154  * I have 3 printers on the back of my server.
3155  *
3156  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3157  * structures.
3158  *   Number     Data                    Id
3159  *      1       printer 1 name          1
3160  *      2       printer 1 cjob          1
3161  *      3       printer 2 name          2
3162  *      4       printer 2 cjob          2
3163  *      5       printer 3 name          3
3164  *      6       printer 3 name          3
3165  *
3166  * that's the print server case, the printer case is even worse.
3167  */
3168
3169 /*******************************************************************
3170  *
3171  * enumerate all printers on the printserver
3172  * fill a notify_info struct with info asked
3173  *
3174  ********************************************************************/
3175
3176 static WERROR printserver_notify_info(pipes_struct *p,
3177                                       struct policy_handle *hnd,
3178                                       struct spoolss_NotifyInfo *info,
3179                                       TALLOC_CTX *mem_ctx)
3180 {
3181         int snum;
3182         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3183         int n_services=lp_numservices();
3184         int i;
3185         struct spoolss_NotifyOption *option;
3186         struct spoolss_NotifyOptionType option_type;
3187
3188         DEBUG(4,("printserver_notify_info\n"));
3189
3190         if (!Printer)
3191                 return WERR_BADFID;
3192
3193         option = Printer->notify.option;
3194
3195         info->version   = 2;
3196         info->notifies  = NULL;
3197         info->count     = 0;
3198
3199         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3200            sending a ffpcn() request first */
3201
3202         if ( !option )
3203                 return WERR_BADFID;
3204
3205         for (i=0; i<option->count; i++) {
3206                 option_type = option->types[i];
3207
3208                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3209                         continue;
3210
3211                 for (snum=0; snum<n_services; snum++)
3212                 {
3213                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3214                                 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3215                 }
3216         }
3217
3218 #if 0
3219         /*
3220          * Debugging information, don't delete.
3221          */
3222
3223         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3224         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3225         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3226
3227         for (i=0; i<info->count; i++) {
3228                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3229                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3230                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3231         }
3232 #endif
3233
3234         return WERR_OK;
3235 }
3236
3237 /*******************************************************************
3238  *
3239  * fill a notify_info struct with info asked
3240  *
3241  ********************************************************************/
3242
3243 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3244                                   struct spoolss_NotifyInfo *info,
3245                                   TALLOC_CTX *mem_ctx)
3246 {
3247         int snum;
3248         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3249         int i;
3250         uint32_t id;
3251         struct spoolss_NotifyOption *option;
3252         struct spoolss_NotifyOptionType option_type;
3253         int count,j;
3254         print_queue_struct *queue=NULL;
3255         print_status_struct status;
3256
3257         DEBUG(4,("printer_notify_info\n"));
3258
3259         if (!Printer)
3260                 return WERR_BADFID;
3261
3262         option = Printer->notify.option;
3263         id = 0x0;
3264
3265         info->version   = 2;
3266         info->notifies  = NULL;
3267         info->count     = 0;
3268
3269         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3270            sending a ffpcn() request first */
3271
3272         if ( !option )
3273                 return WERR_BADFID;
3274
3275         get_printer_snum(p, hnd, &snum, NULL);
3276
3277         for (i=0; i<option->count; i++) {
3278                 option_type = option->types[i];
3279
3280                 switch (option_type.type) {
3281                 case PRINTER_NOTIFY_TYPE:
3282                         if(construct_notify_printer_info(Printer, info, snum,
3283                                                          &option_type, id,
3284                                                          mem_ctx))
3285                                 id--;
3286                         break;
3287
3288                 case JOB_NOTIFY_TYPE: {
3289                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3290
3291                         count = print_queue_status(snum, &queue, &status);
3292
3293                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3294                                 goto done;
3295
3296                         for (j=0; j<count; j++) {
3297                                 construct_notify_jobs_info(&queue[j], info,
3298                                                            printer, snum,
3299                                                            &option_type,
3300                                                            queue[j].job,
3301                                                            mem_ctx);
3302                         }
3303
3304                         free_a_printer(&printer, 2);
3305
3306                 done:
3307                         SAFE_FREE(queue);
3308                         break;
3309                 }
3310                 }
3311         }
3312
3313         /*
3314          * Debugging information, don't delete.
3315          */
3316         /*
3317         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3318         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3319         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3320
3321         for (i=0; i<info->count; i++) {
3322                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3323                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3324                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3325         }
3326         */
3327         return WERR_OK;
3328 }
3329
3330 /****************************************************************
3331  _spoolss_RouterRefreshPrinterChangeNotify
3332 ****************************************************************/
3333
3334 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3335                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3336 {
3337         struct spoolss_NotifyInfo *info;
3338
3339         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3340         WERROR result = WERR_BADFID;
3341
3342         /* we always have a spoolss_NotifyInfo struct */
3343         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3344         if (!info) {
3345                 result = WERR_NOMEM;
3346                 goto done;
3347         }
3348
3349         *r->out.info = info;
3350
3351         if (!Printer) {
3352                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3353                         "Invalid handle (%s:%u:%u).\n",
3354                         OUR_HANDLE(r->in.handle)));
3355                 goto done;
3356         }
3357
3358         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3359
3360         /*
3361          *      We are now using the change value, and
3362          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3363          *      I don't have a global notification system, I'm sending back all the
3364          *      informations even when _NOTHING_ has changed.
3365          */
3366
3367         /* We need to keep track of the change value to send back in
3368            RRPCN replies otherwise our updates are ignored. */
3369
3370         Printer->notify.fnpcn = true;
3371
3372         if (Printer->notify.client_connected) {
3373                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3374                         "Saving change value in request [%x]\n",
3375                         r->in.change_low));
3376                 Printer->notify.change = r->in.change_low;
3377         }
3378
3379         /* just ignore the spoolss_NotifyOption */
3380
3381         switch (Printer->printer_type) {
3382                 case SPLHND_SERVER:
3383                         result = printserver_notify_info(p, r->in.handle,
3384                                                          info, p->mem_ctx);
3385                         break;
3386
3387                 case SPLHND_PRINTER:
3388                         result = printer_notify_info(p, r->in.handle,
3389                                                      info, p->mem_ctx);
3390                         break;
3391         }
3392
3393         Printer->notify.fnpcn = false;
3394
3395 done:
3396         return result;
3397 }
3398
3399 /********************************************************************
3400  * construct_printer_info_0
3401  * fill a printer_info_0 struct
3402  ********************************************************************/
3403
3404 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3405                                       struct auth_serversupplied_info *server_info,
3406                                       struct spoolss_PrinterInfo2 *info2,
3407                                       struct spoolss_PrinterInfo0 *r,
3408                                       int snum)
3409 {
3410         int count;
3411         counter_printer_0 *session_counter;
3412         struct timeval setuptime;
3413         print_status_struct status;
3414
3415         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3416         W_ERROR_HAVE_NO_MEMORY(r->printername);
3417
3418         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3419         W_ERROR_HAVE_NO_MEMORY(r->servername);
3420
3421         count = print_queue_length(snum, &status);
3422
3423         /* check if we already have a counter for this printer */
3424         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3425                 if (session_counter->snum == snum)
3426                         break;
3427         }
3428
3429         /* it's the first time, add it to the list */
3430         if (session_counter == NULL) {
3431                 session_counter = SMB_MALLOC_P(counter_printer_0);
3432                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3433                 ZERO_STRUCTP(session_counter);
3434                 session_counter->snum           = snum;
3435                 session_counter->counter        = 0;
3436                 DLIST_ADD(counter_list, session_counter);
3437         }
3438
3439         /* increment it */
3440         session_counter->counter++;
3441
3442         r->cjobs                        = count;
3443         r->total_jobs                   = 0;
3444         r->total_bytes                  = 0;
3445
3446         get_startup_time(&setuptime);
3447         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3448
3449         /* JFM:
3450          * the global_counter should be stored in a TDB as it's common to all the clients
3451          * and should be zeroed on samba startup
3452          */
3453         r->global_counter               = session_counter->counter;
3454         r->total_pages                  = 0;
3455         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3456         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3457         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3458         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3459         r->spooling                     = 0;
3460         r->max_spooling                 = 0;
3461         r->session_counter              = session_counter->counter;
3462         r->num_error_out_of_paper       = 0x0;
3463         r->num_error_not_ready          = 0x0;          /* number of print failure */
3464         r->job_error                    = 0x0;
3465         r->number_of_processors         = 0x1;
3466         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3467         r->high_part_total_bytes        = 0x0;
3468         winreg_printer_get_changeid(mem_ctx, server_info, info2->sharename, &r->change_id); /* ChangeID in milliseconds*/
3469         r->last_error                   = WERR_OK;
3470         r->status                       = nt_printq_status(status.status);
3471         r->enumerate_network_printers   = 0x0;
3472         r->c_setprinter                 = 0x0;
3473         r->processor_architecture       = 0x0;
3474         r->processor_level              = 0x6;          /* 6  ???*/
3475         r->ref_ic                       = 0;
3476         r->reserved2                    = 0;
3477         r->reserved3                    = 0;
3478
3479         return WERR_OK;
3480 }
3481
3482
3483 /********************************************************************
3484  * construct_printer_info1
3485  * fill a spoolss_PrinterInfo1 struct
3486 ********************************************************************/
3487
3488 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3489                                       const struct spoolss_PrinterInfo2 *info2,
3490                                       uint32_t flags,
3491                                       struct spoolss_PrinterInfo1 *r,
3492                                       int snum)
3493 {
3494         r->flags                = flags;
3495
3496         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3497                                                   info2->printername,
3498                                                   info2->drivername,
3499                                                   info2->location);
3500         W_ERROR_HAVE_NO_MEMORY(r->description);
3501
3502         if (info2->comment == NULL || info2->comment[0] == '\0') {
3503                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3504         } else {
3505                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3506         }
3507         W_ERROR_HAVE_NO_MEMORY(r->comment);
3508
3509         r->name                 = talloc_strdup(mem_ctx, info2->printername);
3510         W_ERROR_HAVE_NO_MEMORY(r->name);
3511
3512         return WERR_OK;
3513 }
3514
3515 /********************************************************************
3516  * construct_printer_info2
3517  * fill a spoolss_PrinterInfo2 struct
3518 ********************************************************************/
3519
3520 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3521                                       const struct spoolss_PrinterInfo2 *info2,
3522                                       struct spoolss_PrinterInfo2 *r,
3523                                       int snum)
3524 {
3525         int count;
3526         print_status_struct status;
3527
3528         count = print_queue_length(snum, &status);
3529
3530         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3531         W_ERROR_HAVE_NO_MEMORY(r->servername);
3532         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3533         W_ERROR_HAVE_NO_MEMORY(r->printername);
3534         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3535         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3536         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3537         W_ERROR_HAVE_NO_MEMORY(r->portname);
3538         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3539         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3540
3541         if (info2->comment[0] == '\0') {
3542                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3543         } else {
3544                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3545         }
3546         W_ERROR_HAVE_NO_MEMORY(r->comment);
3547
3548         r->location             = talloc_strdup(mem_ctx, info2->location);
3549         W_ERROR_HAVE_NO_MEMORY(r->location);
3550         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3551         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3552         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3553         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3554         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3555         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3556         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3557         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3558
3559         r->attributes           = info2->attributes;
3560
3561         r->priority             = info2->priority;
3562         r->defaultpriority      = info2->defaultpriority;
3563         r->starttime            = info2->starttime;
3564         r->untiltime            = info2->untiltime;
3565         r->status               = nt_printq_status(status.status);
3566         r->cjobs                = count;
3567         r->averageppm           = info2->averageppm;
3568
3569         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3570         if (!r->devmode) {
3571                 DEBUG(8,("Returning NULL Devicemode!\n"));
3572         }
3573
3574         r->secdesc = NULL;
3575
3576         if (info2->secdesc != NULL) {
3577                 /* don't use talloc_steal() here unless you do a deep steal of all
3578                    the SEC_DESC members */
3579
3580                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
3581         }
3582
3583         return WERR_OK;
3584 }
3585
3586 /********************************************************************
3587  * construct_printer_info3
3588  * fill a spoolss_PrinterInfo3 struct
3589  ********************************************************************/
3590
3591 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3592                                       const struct spoolss_PrinterInfo2 *info2,
3593                                       struct spoolss_PrinterInfo3 *r,
3594                                       int snum)
3595 {
3596         /* These are the components of the SD we are returning. */
3597
3598         if (info2->secdesc != NULL) {
3599                 /* don't use talloc_steal() here unless you do a deep steal of all
3600                    the SEC_DESC members */
3601
3602                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3603                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3604         }
3605
3606         return WERR_OK;
3607 }
3608
3609 /********************************************************************
3610  * construct_printer_info4
3611  * fill a spoolss_PrinterInfo4 struct
3612  ********************************************************************/
3613
3614 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3615                                       const struct spoolss_PrinterInfo2 *info2,
3616                                       struct spoolss_PrinterInfo4 *r,
3617                                       int snum)
3618 {
3619         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3620         W_ERROR_HAVE_NO_MEMORY(r->printername);
3621         r->servername   = talloc_strdup(mem_ctx, info2->servername);
3622         W_ERROR_HAVE_NO_MEMORY(r->servername);
3623
3624         r->attributes   = info2->attributes;
3625
3626         return WERR_OK;
3627 }
3628
3629 /********************************************************************
3630  * construct_printer_info5
3631  * fill a spoolss_PrinterInfo5 struct
3632  ********************************************************************/
3633
3634 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3635                                       const struct spoolss_PrinterInfo2 *info2,
3636                                       struct spoolss_PrinterInfo5 *r,
3637                                       int snum)
3638 {
3639         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3640         W_ERROR_HAVE_NO_MEMORY(r->printername);
3641         r->portname     = talloc_strdup(mem_ctx, info2->portname);
3642         W_ERROR_HAVE_NO_MEMORY(r->portname);
3643
3644         r->attributes   = info2->attributes;
3645
3646         /* these two are not used by NT+ according to MSDN */
3647         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3648         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3649
3650         return WERR_OK;
3651 }
3652
3653 /********************************************************************
3654  * construct_printer_info_6
3655  * fill a spoolss_PrinterInfo6 struct
3656  ********************************************************************/
3657
3658 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3659                                       const struct spoolss_PrinterInfo2 *info2,
3660                                       struct spoolss_PrinterInfo6 *r,
3661                                       int snum)
3662 {
3663         int count;
3664         print_status_struct status;
3665
3666         count = print_queue_length(snum, &status);
3667
3668         r->status = nt_printq_status(status.status);
3669
3670         return WERR_OK;
3671 }
3672
3673 /********************************************************************
3674  * construct_printer_info7
3675  * fill a spoolss_PrinterInfo7 struct
3676  ********************************************************************/
3677
3678 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3679                                       Printer_entry *print_hnd,
3680                                       struct spoolss_PrinterInfo7 *r,
3681                                       int snum)
3682 {
3683         struct GUID guid;
3684
3685         if (is_printer_published(print_hnd, snum, &guid)) {
3686                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3687                 r->action = DSPRINT_PUBLISH;
3688         } else {
3689                 r->guid = talloc_strdup(mem_ctx, "");
3690                 r->action = DSPRINT_UNPUBLISH;
3691         }
3692         W_ERROR_HAVE_NO_MEMORY(r->guid);
3693
3694         return WERR_OK;
3695 }
3696
3697 /********************************************************************
3698  * construct_printer_info8
3699  * fill a spoolss_PrinterInfo8 struct
3700  ********************************************************************/
3701
3702 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3703                                       const struct spoolss_PrinterInfo2 *info2,
3704                                       struct spoolss_DeviceModeInfo *r,
3705                                       int snum)
3706 {
3707         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3708         if (!r->devmode) {
3709                 DEBUG(8,("Returning NULL Devicemode!\n"));
3710         }
3711
3712         return WERR_OK;
3713 }
3714
3715
3716 /********************************************************************
3717 ********************************************************************/
3718
3719 static bool snum_is_shared_printer(int snum)
3720 {
3721         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3722 }
3723
3724 /********************************************************************
3725  Spoolss_enumprinters.
3726 ********************************************************************/
3727
3728 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3729                                            struct auth_serversupplied_info *server_info,
3730                                            uint32_t level,
3731                                            uint32_t flags,
3732                                            union spoolss_PrinterInfo **info_p,
3733                                            uint32_t *count_p)
3734 {
3735         int snum;
3736         int n_services = lp_numservices();
3737         union spoolss_PrinterInfo *info = NULL;
3738         uint32_t count = 0;
3739         WERROR result = WERR_OK;
3740
3741         *count_p = 0;
3742         *info_p = NULL;
3743
3744         for (snum = 0; snum < n_services; snum++) {
3745
3746                 const char *printer;
3747                 struct spoolss_PrinterInfo2 *info2;
3748
3749                 if (!snum_is_shared_printer(snum)) {
3750                         continue;
3751                 }
3752
3753                 printer = lp_const_servicename(snum);
3754
3755                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3756                         printer, snum));
3757
3758                 result = winreg_create_printer(mem_ctx,
3759                                                server_info,
3760                                                NULL,
3761                                                printer);
3762                 if (!W_ERROR_IS_OK(result)) {
3763                         goto out;
3764                 }
3765
3766                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3767                                             union spoolss_PrinterInfo,
3768                                             count + 1);
3769                 if (!info) {
3770                         result = WERR_NOMEM;
3771                         goto out;
3772                 }
3773
3774                 result = winreg_get_printer(mem_ctx, server_info,
3775                                             NULL, printer, &info2);
3776                 if (!W_ERROR_IS_OK(result)) {
3777                         goto out;
3778                 }
3779
3780                 switch (level) {
3781                 case 0:
3782                         result = construct_printer_info0(info, server_info, info2,
3783                                                          &info[count].info0, snum);
3784                         break;
3785                 case 1:
3786                         result = construct_printer_info1(info, info2, flags,
3787                                                          &info[count].info1, snum);
3788                         break;
3789                 case 2:
3790                         result = construct_printer_info2(info, info2,
3791                                                          &info[count].info2, snum);
3792                         break;
3793                 case 4:
3794                         result = construct_printer_info4(info, info2,
3795                                                          &info[count].info4, snum);
3796                         break;
3797                 case 5:
3798                         result = construct_printer_info5(info, info2,
3799                                                          &info[count].info5, snum);
3800                         break;
3801
3802                 default:
3803                         result = WERR_UNKNOWN_LEVEL;
3804                         goto out;
3805                 }
3806
3807                 if (!W_ERROR_IS_OK(result)) {
3808                         goto out;
3809                 }
3810
3811                 count++;
3812         }
3813
3814         *count_p = count;
3815         *info_p = info;
3816
3817  out:
3818         if (!W_ERROR_IS_OK(result)) {
3819                 TALLOC_FREE(info);
3820                 return result;
3821         }
3822
3823         *info_p = info;
3824
3825         return WERR_OK;
3826 }
3827
3828 /********************************************************************
3829  * handle enumeration of printers at level 0
3830  ********************************************************************/
3831
3832 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3833                                   struct auth_serversupplied_info *server_info,
3834                                   uint32_t flags,
3835                                   const char *servername,
3836                                   union spoolss_PrinterInfo **info,
3837                                   uint32_t *count)
3838 {
3839         DEBUG(4,("enum_all_printers_info_0\n"));
3840
3841         return enum_all_printers_info_level(mem_ctx, server_info, 0, flags, info, count);
3842 }
3843
3844
3845 /********************************************************************
3846 ********************************************************************/
3847
3848 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3849                                        struct auth_serversupplied_info *server_info,
3850                                        uint32_t flags,
3851                                        union spoolss_PrinterInfo **info,
3852                                        uint32_t *count)
3853 {
3854         DEBUG(4,("enum_all_printers_info_1\n"));
3855
3856         return enum_all_printers_info_level(mem_ctx, server_info, 1, flags, info, count);
3857 }
3858
3859 /********************************************************************
3860  enum_all_printers_info_1_local.
3861 *********************************************************************/
3862
3863 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3864                                              struct auth_serversupplied_info *server_info,
3865                                              union spoolss_PrinterInfo **info,
3866                                              uint32_t *count)
3867 {
3868         DEBUG(4,("enum_all_printers_info_1_local\n"));
3869
3870         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3871 }
3872
3873 /********************************************************************
3874  enum_all_printers_info_1_name.
3875 *********************************************************************/
3876
3877 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3878                                             struct auth_serversupplied_info *server_info,
3879                                             const char *name,
3880                                             union spoolss_PrinterInfo **info,
3881                                             uint32_t *count)
3882 {
3883         const char *s = name;
3884
3885         DEBUG(4,("enum_all_printers_info_1_name\n"));
3886
3887         if ((name[0] == '\\') && (name[1] == '\\')) {
3888                 s = name + 2;
3889         }
3890
3891         if (!is_myname_or_ipaddr(s)) {
3892                 return WERR_INVALID_NAME;
3893         }
3894
3895         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_ICON8, info, count);
3896 }
3897
3898 /********************************************************************
3899  enum_all_printers_info_1_network.
3900 *********************************************************************/
3901
3902 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3903                                                struct auth_serversupplied_info *server_info,
3904                                                const char *name,
3905                                                union spoolss_PrinterInfo **info,
3906                                                uint32_t *count)
3907 {
3908         const char *s = name;
3909
3910         DEBUG(4,("enum_all_printers_info_1_network\n"));
3911
3912         /* If we respond to a enum_printers level 1 on our name with flags
3913            set to PRINTER_ENUM_REMOTE with a list of printers then these
3914            printers incorrectly appear in the APW browse list.
3915            Specifically the printers for the server appear at the workgroup
3916            level where all the other servers in the domain are
3917            listed. Windows responds to this call with a
3918            WERR_CAN_NOT_COMPLETE so we should do the same. */
3919
3920         if (name[0] == '\\' && name[1] == '\\') {
3921                  s = name + 2;
3922         }
3923
3924         if (is_myname_or_ipaddr(s)) {
3925                  return WERR_CAN_NOT_COMPLETE;
3926         }
3927
3928         return enum_all_printers_info_1(mem_ctx, server_info, PRINTER_ENUM_NAME, info, count);
3929 }
3930
3931 /********************************************************************
3932  * api_spoolss_enumprinters
3933  *
3934  * called from api_spoolss_enumprinters (see this to understand)
3935  ********************************************************************/
3936
3937 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3938                                        struct auth_serversupplied_info *server_info,
3939                                        union spoolss_PrinterInfo **info,
3940                                        uint32_t *count)
3941 {
3942         DEBUG(4,("enum_all_printers_info_2\n"));
3943
3944         return enum_all_printers_info_level(mem_ctx, server_info, 2, 0, info, count);
3945 }
3946
3947 /********************************************************************
3948  * handle enumeration of printers at level 1
3949  ********************************************************************/
3950
3951 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3952                                   struct auth_serversupplied_info *server_info,
3953                                   uint32_t flags,
3954                                   const char *name,
3955                                   union spoolss_PrinterInfo **info,
3956                                   uint32_t *count)
3957 {
3958         /* Not all the flags are equals */
3959
3960         if (flags & PRINTER_ENUM_LOCAL) {
3961                 return enum_all_printers_info_1_local(mem_ctx, server_info, info, count);
3962         }
3963
3964         if (flags & PRINTER_ENUM_NAME) {
3965                 return enum_all_printers_info_1_name(mem_ctx, server_info, name, info, count);
3966         }
3967
3968         if (flags & PRINTER_ENUM_NETWORK) {
3969                 return enum_all_printers_info_1_network(mem_ctx, server_info, name, info, count);
3970         }
3971
3972         return WERR_OK; /* NT4sp5 does that */
3973 }
3974
3975 /********************************************************************
3976  * handle enumeration of printers at level 2
3977  ********************************************************************/
3978
3979 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
3980                                   struct auth_serversupplied_info *server_info,
3981                                   uint32_t flags,
3982                                   const char *servername,
3983                                   union spoolss_PrinterInfo **info,
3984                                   uint32_t *count)
3985 {
3986         if (flags & PRINTER_ENUM_LOCAL) {
3987                 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
3988         }
3989
3990         if (flags & PRINTER_ENUM_NAME) {
3991                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
3992                         return WERR_INVALID_NAME;
3993                 }
3994
3995                 return enum_all_printers_info_2(mem_ctx, server_info, info, count);
3996         }
3997
3998         if (flags & PRINTER_ENUM_REMOTE) {
3999                 return WERR_UNKNOWN_LEVEL;
4000         }
4001
4002         return WERR_OK;
4003 }
4004
4005 /********************************************************************
4006  * handle enumeration of printers at level 4
4007  ********************************************************************/
4008
4009 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4010                                   struct auth_serversupplied_info *server_info,
4011                                   uint32_t flags,
4012                                   const char *servername,
4013                                   union spoolss_PrinterInfo **info,
4014                                   uint32_t *count)
4015 {
4016         DEBUG(4,("enum_all_printers_info_4\n"));
4017
4018         return enum_all_printers_info_level(mem_ctx, server_info, 4, flags, info, count);
4019 }
4020
4021
4022 /********************************************************************
4023  * handle enumeration of printers at level 5
4024  ********************************************************************/
4025
4026 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4027                                   struct auth_serversupplied_info *server_info,
4028                                   uint32_t flags,
4029                                   const char *servername,
4030                                   union spoolss_PrinterInfo **info,
4031                                   uint32_t *count)
4032 {
4033         DEBUG(4,("enum_all_printers_info_5\n"));
4034
4035         return enum_all_printers_info_level(mem_ctx, server_info, 5, flags, info, count);
4036 }
4037
4038 /****************************************************************
4039  _spoolss_EnumPrinters
4040 ****************************************************************/
4041
4042 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4043                              struct spoolss_EnumPrinters *r)
4044 {
4045         const char *name = NULL;
4046         WERROR result;
4047
4048         /* that's an [in out] buffer */
4049
4050         if (!r->in.buffer && (r->in.offered != 0)) {
4051                 return WERR_INVALID_PARAM;
4052         }
4053
4054         DEBUG(4,("_spoolss_EnumPrinters\n"));
4055
4056         *r->out.needed = 0;
4057         *r->out.count = 0;
4058         *r->out.info = NULL;
4059
4060         /*
4061          * Level 1:
4062          *          flags==PRINTER_ENUM_NAME
4063          *           if name=="" then enumerates all printers
4064          *           if name!="" then enumerate the printer
4065          *          flags==PRINTER_ENUM_REMOTE
4066          *          name is NULL, enumerate printers
4067          * Level 2: name!="" enumerates printers, name can't be NULL
4068          * Level 3: doesn't exist
4069          * Level 4: does a local registry lookup
4070          * Level 5: same as Level 2
4071          */
4072
4073         if (r->in.server) {
4074                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4075                 W_ERROR_HAVE_NO_MEMORY(name);
4076         }
4077
4078         switch (r->in.level) {
4079         case 0:
4080                 result = enumprinters_level0(p->mem_ctx, p->server_info,
4081                                              r->in.flags, name,
4082                                              r->out.info, r->out.count);
4083                 break;
4084         case 1:
4085                 result = enumprinters_level1(p->mem_ctx, p->server_info,
4086                                              r->in.flags, name,
4087                                              r->out.info, r->out.count);
4088                 break;
4089         case 2:
4090                 result = enumprinters_level2(p->mem_ctx, p->server_info,
4091                                              r->in.flags, name,
4092                                              r->out.info, r->out.count);
4093                 break;
4094         case 4:
4095                 result = enumprinters_level4(p->mem_ctx, p->server_info,
4096                                              r->in.flags, name,
4097                                              r->out.info, r->out.count);
4098                 break;
4099         case 5:
4100                 result = enumprinters_level5(p->mem_ctx, p->server_info,
4101                                              r->in.flags, name,
4102                                              r->out.info, r->out.count);
4103                 break;
4104         default:
4105                 return WERR_UNKNOWN_LEVEL;
4106         }
4107
4108         if (!W_ERROR_IS_OK(result)) {
4109                 return result;
4110         }
4111
4112         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4113                                                      spoolss_EnumPrinters, 
4114                                                      *r->out.info, r->in.level,
4115                                                      *r->out.count);
4116         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4117         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4118
4119         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4120 }
4121
4122 /****************************************************************
4123  _spoolss_GetPrinter
4124 ****************************************************************/
4125
4126 WERROR _spoolss_GetPrinter(pipes_struct *p,
4127                            struct spoolss_GetPrinter *r)
4128 {
4129         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4130         struct spoolss_PrinterInfo2 *info2 = NULL;
4131         WERROR result = WERR_OK;
4132         const char *servername = NULL;
4133         int snum;
4134
4135         /* that's an [in out] buffer */
4136
4137         if (!r->in.buffer && (r->in.offered != 0)) {
4138                 return WERR_INVALID_PARAM;
4139         }
4140
4141         *r->out.needed = 0;
4142
4143         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4144                 return WERR_BADFID;
4145         }
4146
4147         if (Printer != NULL || Printer->servername != NULL) {
4148                 servername = Printer->servername;
4149         }
4150
4151         result = winreg_get_printer(p->mem_ctx,
4152                                     p->server_info,
4153                                     servername,
4154                                     lp_const_servicename(snum),
4155                                     &info2);
4156         if (!W_ERROR_IS_OK(result)) {
4157                 return result;
4158         }
4159
4160         switch (r->in.level) {
4161         case 0:
4162                 result = construct_printer_info0(p->mem_ctx, p->server_info,
4163                                                  info2,
4164                                                  &r->out.info->info0, snum);
4165                 break;
4166         case 1:
4167                 result = construct_printer_info1(p->mem_ctx, info2,
4168                                                  PRINTER_ENUM_ICON8,
4169                                                  &r->out.info->info1, snum);
4170                 break;
4171         case 2:
4172                 result = construct_printer_info2(p->mem_ctx, info2,
4173                                                  &r->out.info->info2, snum);
4174                 break;
4175         case 3:
4176                 result = construct_printer_info3(p->mem_ctx, info2,
4177                                                  &r->out.info->info3, snum);
4178                 break;
4179         case 4:
4180                 result = construct_printer_info4(p->mem_ctx, info2,
4181                                                  &r->out.info->info4, snum);
4182                 break;
4183         case 5:
4184                 result = construct_printer_info5(p->mem_ctx, info2,
4185                                                  &r->out.info->info5, snum);
4186                 break;
4187         case 6:
4188                 result = construct_printer_info6(p->mem_ctx, info2,
4189                                                  &r->out.info->info6, snum);
4190                 break;
4191         case 7:
4192                 result = construct_printer_info7(p->mem_ctx, Printer,
4193                                                  &r->out.info->info7, snum);
4194                 break;
4195         case 8:
4196                 result = construct_printer_info8(p->mem_ctx, info2,
4197                                                  &r->out.info->info8, snum);
4198                 break;
4199         default:
4200                 result = WERR_UNKNOWN_LEVEL;
4201                 break;
4202         }
4203
4204         if (!W_ERROR_IS_OK(result)) {
4205                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4206                           r->in.level, win_errstr(result)));
4207                 TALLOC_FREE(r->out.info);
4208                 return result;
4209         }
4210
4211         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4212                                                r->out.info, r->in.level);
4213         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4214
4215         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4216 }
4217
4218 /********************************************************************
4219  ********************************************************************/
4220
4221 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4222                                                   const char **string_array,
4223                                                   const char *cservername)
4224 {
4225         int i, num_strings = 0;
4226         const char **array = NULL;
4227
4228         if (!string_array) {
4229                 return NULL;
4230         }
4231
4232         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4233
4234                 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4235                                                   cservername, string_array[i]);
4236                 if (!str) {
4237                         TALLOC_FREE(array);
4238                         return NULL;
4239                 }
4240
4241
4242                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4243                         TALLOC_FREE(array);
4244                         return NULL;
4245                 }
4246         }
4247
4248         if (i > 0) {
4249                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4250                              &array, &num_strings);
4251         }
4252
4253         return array;
4254 }
4255
4256 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4257         do { \
4258                 if (in && strlen(in)) { \
4259                         out = talloc_strdup(mem_ctx, in); \
4260                         W_ERROR_HAVE_NO_MEMORY(out); \
4261                 } else { \
4262                         out = NULL; \
4263                 } \
4264         } while (0);
4265
4266 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4267         do { \
4268                 if (in && strlen(in)) { \
4269                         out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4270                 } else { \
4271                         out = talloc_strdup(mem_ctx, ""); \
4272                 } \
4273                 W_ERROR_HAVE_NO_MEMORY(out); \
4274         } while (0);
4275
4276 /********************************************************************
4277  * fill a spoolss_DriverInfo1 struct
4278  ********************************************************************/
4279
4280 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4281                                         struct spoolss_DriverInfo1 *r,
4282                                         const struct spoolss_DriverInfo8 *driver,
4283                                         const char *servername)
4284 {
4285         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4286         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4287
4288         return WERR_OK;
4289 }
4290
4291 /********************************************************************
4292  * fill a spoolss_DriverInfo2 struct
4293  ********************************************************************/
4294
4295 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4296                                         struct spoolss_DriverInfo2 *r,
4297                                         const struct spoolss_DriverInfo8 *driver,
4298                                         const char *servername)
4299
4300 {
4301         const char *cservername = canon_servername(servername);
4302
4303         r->version              = driver->version;
4304
4305         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4306         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4307         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4308         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4309
4310         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4311                                driver->driver_path,
4312                                r->driver_path);
4313
4314         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4315                                driver->data_file,
4316                                r->data_file);
4317
4318         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4319                                driver->config_file,
4320                                r->config_file);
4321
4322         return WERR_OK;
4323 }
4324
4325 /********************************************************************
4326  * fill a spoolss_DriverInfo3 struct
4327  ********************************************************************/
4328
4329 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4330                                         struct spoolss_DriverInfo3 *r,
4331                                         const struct spoolss_DriverInfo8 *driver,
4332                                         const char *servername)
4333 {
4334         const char *cservername = canon_servername(servername);
4335
4336         r->version              = driver->version;
4337
4338         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4339         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4340         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4341         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4342
4343         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4344                                driver->driver_path,
4345                                r->driver_path);
4346
4347         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4348                                driver->data_file,
4349                                r->data_file);
4350
4351         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4352                                driver->config_file,
4353                                r->config_file);
4354
4355         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4356                                driver->help_file,
4357                                r->help_file);
4358
4359         FILL_DRIVER_STRING(mem_ctx,
4360                            driver->monitor_name,
4361                            r->monitor_name);
4362
4363         FILL_DRIVER_STRING(mem_ctx,
4364                            driver->default_datatype,
4365                            r->default_datatype);
4366
4367         r->dependent_files = string_array_from_driver_info(mem_ctx,
4368                                                            driver->dependent_files,
4369                                                            cservername);
4370         return WERR_OK;
4371 }
4372
4373 /********************************************************************
4374  * fill a spoolss_DriverInfo4 struct
4375  ********************************************************************/
4376
4377 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4378                                         struct spoolss_DriverInfo4 *r,
4379                                         const struct spoolss_DriverInfo8 *driver,
4380                                         const char *servername)
4381 {
4382         const char *cservername = canon_servername(servername);
4383
4384         r->version              = driver->version;
4385
4386         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4387         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4388         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4389         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4390
4391         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4392                                driver->driver_path,
4393                                r->driver_path);
4394
4395         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4396                                driver->data_file,
4397                                r->data_file);
4398
4399         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4400                                driver->config_file,
4401                                r->config_file);
4402
4403         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4404                                driver->help_file,
4405                                r->help_file);
4406
4407         r->dependent_files = string_array_from_driver_info(mem_ctx,
4408                                                            driver->dependent_files,
4409                                                            cservername);
4410
4411         FILL_DRIVER_STRING(mem_ctx,
4412                            driver->monitor_name,
4413                            r->monitor_name);
4414
4415         FILL_DRIVER_STRING(mem_ctx,
4416                            driver->default_datatype,
4417                            r->default_datatype);
4418
4419         r->previous_names = string_array_from_driver_info(mem_ctx,
4420                                                           driver->previous_names,
4421                                                           cservername);
4422
4423         return WERR_OK;
4424 }
4425
4426 /********************************************************************
4427  * fill a spoolss_DriverInfo5 struct
4428  ********************************************************************/
4429
4430 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4431                                         struct spoolss_DriverInfo5 *r,
4432                                         const struct spoolss_DriverInfo8 *driver,
4433                                         const char *servername)
4434 {
4435         const char *cservername = canon_servername(servername);
4436
4437         r->version              = driver->version;
4438
4439         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4440         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4441         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4442         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4443
4444         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4445                                driver->driver_path,
4446                                r->driver_path);
4447
4448         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4449                                driver->data_file,
4450                                r->data_file);
4451
4452         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4453                                driver->config_file,
4454                                r->config_file);
4455
4456         r->driver_attributes    = 0;
4457         r->config_version       = 0;
4458         r->driver_version       = 0;
4459
4460         return WERR_OK;
4461 }
4462 /********************************************************************
4463  * fill a spoolss_DriverInfo6 struct
4464  ********************************************************************/
4465
4466 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4467                                         struct spoolss_DriverInfo6 *r,
4468                                         const struct spoolss_DriverInfo8 *driver,
4469                                         const char *servername)
4470 {
4471         const char *cservername = canon_servername(servername);
4472
4473         r->version              = driver->version;
4474
4475         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4476         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4477         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4478         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4479
4480         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4481                                driver->driver_path,
4482                                r->driver_path);
4483
4484         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4485                                driver->data_file,
4486                                r->data_file);
4487
4488         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4489                                driver->config_file,
4490                                r->config_file);
4491
4492         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4493                                driver->help_file,
4494                                r->help_file);
4495
4496         FILL_DRIVER_STRING(mem_ctx,
4497                            driver->monitor_name,
4498                            r->monitor_name);
4499
4500         FILL_DRIVER_STRING(mem_ctx,
4501                            driver->default_datatype,
4502                            r->default_datatype);
4503
4504         r->dependent_files = string_array_from_driver_info(mem_ctx,
4505                                                            driver->dependent_files,
4506                                                            cservername);
4507         r->previous_names = string_array_from_driver_info(mem_ctx,
4508                                                           driver->previous_names,
4509                                                           cservername);
4510
4511         r->driver_date          = driver->driver_date;
4512         r->driver_version       = driver->driver_version;
4513
4514         FILL_DRIVER_STRING(mem_ctx,
4515                            driver->manufacturer_name,
4516                            r->manufacturer_name);
4517         FILL_DRIVER_STRING(mem_ctx,
4518                            driver->manufacturer_url,
4519                            r->manufacturer_url);
4520         FILL_DRIVER_STRING(mem_ctx,
4521                            driver->hardware_id,
4522                            r->hardware_id);
4523         FILL_DRIVER_STRING(mem_ctx,
4524                            driver->provider,
4525                            r->provider);
4526
4527         return WERR_OK;
4528 }
4529
4530 /********************************************************************
4531  * fill a spoolss_DriverInfo8 struct
4532  ********************************************************************/
4533
4534 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4535                                         struct spoolss_DriverInfo8 *r,
4536                                         const struct spoolss_DriverInfo8 *driver,
4537                                         const char *servername)
4538 {
4539         const char *cservername = canon_servername(servername);
4540
4541         r->version              = driver->version;
4542
4543         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4544         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4545         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4546         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4547
4548         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4549                                driver->driver_path,
4550                                r->driver_path);
4551
4552         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4553                                driver->data_file,
4554                                r->data_file);
4555
4556         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4557                                driver->config_file,
4558                                r->config_file);
4559
4560         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4561                                driver->help_file,
4562                                r->help_file);
4563
4564         FILL_DRIVER_STRING(mem_ctx,
4565                            driver->monitor_name,
4566                            r->monitor_name);
4567
4568         FILL_DRIVER_STRING(mem_ctx,
4569                            driver->default_datatype,
4570                            r->default_datatype);
4571
4572         r->dependent_files = string_array_from_driver_info(mem_ctx,
4573                                                            driver->dependent_files,
4574                                                            cservername);
4575         r->previous_names = string_array_from_driver_info(mem_ctx,
4576                                                           driver->previous_names,
4577                                                           cservername);
4578
4579         r->driver_date          = driver->driver_date;
4580         r->driver_version       = driver->driver_version;
4581
4582         FILL_DRIVER_STRING(mem_ctx,
4583                            driver->manufacturer_name,
4584                            r->manufacturer_name);
4585         FILL_DRIVER_STRING(mem_ctx,
4586                            driver->manufacturer_url,
4587                            r->manufacturer_url);
4588         FILL_DRIVER_STRING(mem_ctx,
4589                            driver->hardware_id,
4590                            r->hardware_id);
4591         FILL_DRIVER_STRING(mem_ctx,
4592                            driver->provider,
4593                            r->provider);
4594
4595         FILL_DRIVER_STRING(mem_ctx,
4596                            driver->print_processor,
4597                            r->print_processor);
4598         FILL_DRIVER_STRING(mem_ctx,
4599                            driver->vendor_setup,
4600                            r->vendor_setup);
4601
4602         r->color_profiles = string_array_from_driver_info(mem_ctx,
4603                                                           driver->color_profiles,
4604                                                           cservername);
4605
4606         FILL_DRIVER_STRING(mem_ctx,
4607                            driver->inf_path,
4608                            r->inf_path);
4609
4610         r->printer_driver_attributes    = driver->printer_driver_attributes;
4611
4612         r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4613                                                                     driver->core_driver_dependencies,
4614                                                                     cservername);
4615
4616         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
4617         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4618
4619         return WERR_OK;
4620 }
4621
4622 #if 0 /* disabled until marshalling issues are resolved - gd */
4623 /********************************************************************
4624  ********************************************************************/
4625
4626 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4627                                           struct spoolss_DriverFileInfo *r,
4628                                           const char *cservername,
4629                                           const char *file_name,
4630                                           enum spoolss_DriverFileType file_type,
4631                                           uint32_t file_version)
4632 {
4633         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
4634                                           cservername, file_name);
4635         W_ERROR_HAVE_NO_MEMORY(r->file_name);
4636         r->file_type    = file_type;
4637         r->file_version = file_version;
4638
4639         return WERR_OK;
4640 }
4641
4642 /********************************************************************
4643  ********************************************************************/
4644
4645 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4646                                                  const struct spoolss_DriverInfo8 *driver,
4647                                                  const char *cservername,
4648                                                  struct spoolss_DriverFileInfo **info_p,
4649                                                  uint32_t *count_p)
4650 {
4651         struct spoolss_DriverFileInfo *info = NULL;
4652         uint32_t count = 0;
4653         WERROR result;
4654         uint32_t i;
4655
4656         *info_p = NULL;
4657         *count_p = 0;
4658
4659         if (strlen(driver->driver_path)) {
4660                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4661                                             struct spoolss_DriverFileInfo,
4662                                             count + 1);
4663                 W_ERROR_HAVE_NO_MEMORY(info);
4664                 result = fill_spoolss_DriverFileInfo(info,
4665                                                      &info[count],
4666                                                      cservername,
4667                                                      driver->driver_path,
4668                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4669                                                      0);
4670                 W_ERROR_NOT_OK_RETURN(result);
4671                 count++;
4672         }
4673
4674         if (strlen(driver->config_file)) {
4675                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4676                                             struct spoolss_DriverFileInfo,
4677                                             count + 1);
4678                 W_ERROR_HAVE_NO_MEMORY(info);
4679                 result = fill_spoolss_DriverFileInfo(info,
4680                                                      &info[count],
4681                                                      cservername,
4682                                                      driver->config_file,
4683                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4684                                                      0);
4685                 W_ERROR_NOT_OK_RETURN(result);
4686                 count++;
4687         }
4688
4689         if (strlen(driver->data_file)) {
4690                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4691                                             struct spoolss_DriverFileInfo,
4692                                             count + 1);
4693                 W_ERROR_HAVE_NO_MEMORY(info);
4694                 result = fill_spoolss_DriverFileInfo(info,
4695                                                      &info[count],
4696                                                      cservername,
4697                                                      driver->data_file,
4698                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
4699                                                      0);
4700                 W_ERROR_NOT_OK_RETURN(result);
4701                 count++;
4702         }
4703
4704         if (strlen(driver->help_file)) {
4705                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4706                                             struct spoolss_DriverFileInfo,
4707                                             count + 1);
4708                 W_ERROR_HAVE_NO_MEMORY(info);
4709                 result = fill_spoolss_DriverFileInfo(info,
4710                                                      &info[count],
4711                                                      cservername,
4712                                                      driver->help_file,
4713                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
4714                                                      0);
4715                 W_ERROR_NOT_OK_RETURN(result);
4716                 count++;
4717         }
4718
4719         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4720                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4721                                             struct spoolss_DriverFileInfo,
4722                                             count + 1);
4723                 W_ERROR_HAVE_NO_MEMORY(info);
4724                 result = fill_spoolss_DriverFileInfo(info,
4725                                                      &info[count],
4726                                                      cservername,
4727                                                      driver->dependent_files[i],
4728                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4729                                                      0);
4730                 W_ERROR_NOT_OK_RETURN(result);
4731                 count++;
4732         }
4733
4734         *info_p = info;
4735         *count_p = count;
4736
4737         return WERR_OK;
4738 }
4739
4740 /********************************************************************
4741  * fill a spoolss_DriverInfo101 struct
4742  ********************************************************************/
4743
4744 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4745                                           struct spoolss_DriverInfo101 *r,
4746                                           const struct spoolss_DriverInfo8 *driver,
4747                                           const char *servername)
4748 {
4749         const char *cservername = canon_servername(servername);
4750         WERROR result;
4751
4752         r->version              = driver->version;
4753
4754         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4755         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4756         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4757         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4758
4759         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4760                                                     cservername,
4761                                                     &r->file_info,
4762                                                     &r->file_count);
4763         if (!W_ERROR_IS_OK(result)) {
4764                 return result;
4765         }
4766
4767         FILL_DRIVER_STRING(mem_ctx,
4768                            driver->monitor_name,
4769                            r->monitor_name);
4770
4771         FILL_DRIVER_STRING(mem_ctx,
4772                            driver->default_datatype,
4773                            r->default_datatype);
4774
4775         r->previous_names = string_array_from_driver_info(mem_ctx,
4776                                                           driver->previous_names,
4777                                                           cservername);
4778         r->driver_date          = driver->driver_date;
4779         r->driver_version       = driver->driver_version;
4780
4781         FILL_DRIVER_STRING(mem_ctx,
4782                            driver->manufacturer_name,
4783                            r->manufacturer_name);
4784         FILL_DRIVER_STRING(mem_ctx,
4785                            driver->manufacturer_url,
4786                            r->manufacturer_url);
4787         FILL_DRIVER_STRING(mem_ctx,
4788                            driver->hardware_id,
4789                            r->hardware_id);
4790         FILL_DRIVER_STRING(mem_ctx,
4791                            driver->provider,
4792                            r->provider);
4793
4794         return WERR_OK;
4795 }
4796 #endif
4797 /********************************************************************
4798  ********************************************************************/
4799
4800 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4801                                                   struct auth_serversupplied_info *server_info,
4802                                                   uint32_t level,
4803                                                   union spoolss_DriverInfo *r,
4804                                                   int snum,
4805                                                   const char *servername,
4806                                                   const char *architecture,
4807                                                   uint32_t version)
4808 {
4809         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4810         struct spoolss_DriverInfo8 *driver;
4811         WERROR result;
4812
4813         result = winreg_get_printer(mem_ctx,
4814                                     server_info,
4815                                     servername,
4816                                     lp_const_servicename(snum),
4817                                     &pinfo2);
4818
4819         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4820                 win_errstr(result)));
4821
4822         if (!W_ERROR_IS_OK(result)) {
4823                 return WERR_INVALID_PRINTER_NAME;
4824         }
4825
4826         result = winreg_get_driver(mem_ctx, server_info, architecture,
4827                                    pinfo2->drivername, version, &driver);
4828
4829         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4830                 win_errstr(result)));
4831
4832         if (!W_ERROR_IS_OK(result)) {
4833                 /*
4834                  * Is this a W2k client ?
4835                  */
4836
4837                 if (version < 3) {
4838                         talloc_free(pinfo2);
4839                         return WERR_UNKNOWN_PRINTER_DRIVER;
4840                 }
4841
4842                 /* Yes - try again with a WinNT driver. */
4843                 version = 2;
4844                 result = winreg_get_driver(mem_ctx, server_info, architecture,
4845                                            pinfo2->drivername,
4846                                            version, &driver);
4847                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4848                         win_errstr(result)));
4849                 if (!W_ERROR_IS_OK(result)) {
4850                         talloc_free(pinfo2);
4851                         return WERR_UNKNOWN_PRINTER_DRIVER;
4852                 }
4853         }
4854
4855         switch (level) {
4856         case 1:
4857                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4858                 break;
4859         case 2:
4860                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4861                 break;
4862         case 3:
4863                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4864                 break;
4865         case 4:
4866                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4867                 break;
4868         case 5:
4869                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4870                 break;
4871         case 6:
4872                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4873                 break;
4874         case 8:
4875                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4876                 break;
4877 #if 0 /* disabled until marshalling issues are resolved - gd */
4878         case 101:
4879                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4880                 break;
4881 #endif
4882         default:
4883                 result = WERR_UNKNOWN_LEVEL;
4884                 break;
4885         }
4886
4887         talloc_free(pinfo2);
4888         talloc_free(driver);
4889
4890         return result;
4891 }
4892
4893 /****************************************************************
4894  _spoolss_GetPrinterDriver2
4895 ****************************************************************/
4896
4897 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4898                                   struct spoolss_GetPrinterDriver2 *r)
4899 {
4900         Printer_entry *printer;
4901         WERROR result;
4902
4903         const char *servername;
4904         int snum;
4905
4906         /* that's an [in out] buffer */
4907
4908         if (!r->in.buffer && (r->in.offered != 0)) {
4909                 return WERR_INVALID_PARAM;
4910         }
4911
4912         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4913
4914         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4915                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4916                 return WERR_INVALID_PRINTER_NAME;
4917         }
4918
4919         *r->out.needed = 0;
4920         *r->out.server_major_version = 0;
4921         *r->out.server_minor_version = 0;
4922
4923         servername = get_server_name(printer);
4924
4925         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4926                 return WERR_BADFID;
4927         }
4928
4929         result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
4930                                                      r->in.level, r->out.info,
4931                                                      snum, servername,
4932                                                      r->in.architecture,
4933                                                      r->in.client_major_version);
4934         if (!W_ERROR_IS_OK(result)) {
4935                 TALLOC_FREE(r->out.info);
4936                 return result;
4937         }
4938
4939         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
4940                                                r->out.info, r->in.level);
4941         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4942
4943         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4944 }
4945
4946
4947 /****************************************************************
4948  _spoolss_StartPagePrinter
4949 ****************************************************************/
4950
4951 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4952                                  struct spoolss_StartPagePrinter *r)
4953 {
4954         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4955
4956         if (!Printer) {
4957                 DEBUG(3,("_spoolss_StartPagePrinter: "
4958                         "Error in startpageprinter printer handle\n"));
4959                 return WERR_BADFID;
4960         }
4961
4962         Printer->page_started = true;
4963         return WERR_OK;
4964 }
4965
4966 /****************************************************************
4967  _spoolss_EndPagePrinter
4968 ****************************************************************/
4969
4970 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4971                                struct spoolss_EndPagePrinter *r)
4972 {
4973         int snum;
4974
4975         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4976
4977         if (!Printer) {
4978                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
4979                         OUR_HANDLE(r->in.handle)));
4980                 return WERR_BADFID;
4981         }
4982
4983         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
4984                 return WERR_BADFID;
4985
4986         Printer->page_started = false;
4987         print_job_endpage(snum, Printer->jobid);
4988
4989         return WERR_OK;
4990 }
4991
4992 /****************************************************************
4993  _spoolss_StartDocPrinter
4994 ****************************************************************/
4995
4996 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
4997                                 struct spoolss_StartDocPrinter *r)
4998 {
4999         struct spoolss_DocumentInfo1 *info_1;
5000         int snum;
5001         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5002
5003         if (!Printer) {
5004                 DEBUG(2,("_spoolss_StartDocPrinter: "
5005                         "Invalid handle (%s:%u:%u)\n",
5006                         OUR_HANDLE(r->in.handle)));
5007                 return WERR_BADFID;
5008         }
5009
5010         if (r->in.level != 1) {
5011                 return WERR_UNKNOWN_LEVEL;
5012         }
5013
5014         info_1 = r->in.info.info1;
5015
5016         /*
5017          * a nice thing with NT is it doesn't listen to what you tell it.
5018          * when asked to send _only_ RAW datas, it tries to send datas
5019          * in EMF format.
5020          *
5021          * So I add checks like in NT Server ...
5022          */
5023
5024         if (info_1->datatype) {
5025                 if (strcmp(info_1->datatype, "RAW") != 0) {
5026                         *r->out.job_id = 0;
5027                         return WERR_INVALID_DATATYPE;
5028                 }
5029         }
5030
5031         /* get the share number of the printer */
5032         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5033                 return WERR_BADFID;
5034         }
5035
5036         Printer->jobid = print_job_start(p->server_info, snum,
5037                                          info_1->document_name,
5038                                          Printer->devmode);
5039
5040         /* An error occured in print_job_start() so return an appropriate
5041            NT error code. */
5042
5043         if (Printer->jobid == -1) {
5044                 return map_werror_from_unix(errno);
5045         }
5046
5047         Printer->document_started = true;
5048         *r->out.job_id = Printer->jobid;
5049
5050         return WERR_OK;
5051 }
5052
5053 /****************************************************************
5054  _spoolss_EndDocPrinter
5055 ****************************************************************/
5056
5057 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5058                               struct spoolss_EndDocPrinter *r)
5059 {
5060         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5061         int snum;
5062
5063         if (!Printer) {
5064                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5065                         OUR_HANDLE(r->in.handle)));
5066                 return WERR_BADFID;
5067         }
5068
5069         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5070                 return WERR_BADFID;
5071         }
5072
5073         Printer->document_started = false;
5074         print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5075         /* error codes unhandled so far ... */
5076
5077         return WERR_OK;
5078 }
5079
5080 /****************************************************************
5081  _spoolss_WritePrinter
5082 ****************************************************************/
5083
5084 WERROR _spoolss_WritePrinter(pipes_struct *p,
5085                              struct spoolss_WritePrinter *r)
5086 {
5087         ssize_t buffer_written;
5088         int snum;
5089         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5090
5091         if (!Printer) {
5092                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5093                         OUR_HANDLE(r->in.handle)));
5094                 *r->out.num_written = r->in._data_size;
5095                 return WERR_BADFID;
5096         }
5097
5098         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5099                 return WERR_BADFID;
5100
5101         buffer_written = print_job_write(snum, Printer->jobid,
5102                                                    (const char *)r->in.data.data,
5103                                                    (SMB_OFF_T)-1,
5104                                                    (size_t)r->in._data_size);
5105         if (buffer_written == (ssize_t)-1) {
5106                 *r->out.num_written = 0;
5107                 if (errno == ENOSPC)
5108                         return WERR_NO_SPOOL_SPACE;
5109                 else
5110                         return WERR_ACCESS_DENIED;
5111         }
5112
5113         *r->out.num_written = r->in._data_size;
5114
5115         return WERR_OK;
5116 }
5117
5118 /********************************************************************
5119  * api_spoolss_getprinter
5120  * called from the spoolss dispatcher
5121  *
5122  ********************************************************************/
5123
5124 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5125                               pipes_struct *p)
5126 {
5127         int snum;
5128         WERROR errcode = WERR_BADFUNC;
5129         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5130
5131         if (!Printer) {
5132                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5133                         OUR_HANDLE(handle)));
5134                 return WERR_BADFID;
5135         }
5136
5137         if (!get_printer_snum(p, handle, &snum, NULL))
5138                 return WERR_BADFID;
5139
5140         switch (command) {
5141         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5142                 errcode = print_queue_pause(p->server_info, snum);
5143                 break;
5144         case SPOOLSS_PRINTER_CONTROL_RESUME:
5145         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5146                 errcode = print_queue_resume(p->server_info, snum);
5147                 break;
5148         case SPOOLSS_PRINTER_CONTROL_PURGE:
5149                 errcode = print_queue_purge(p->server_info, snum);
5150                 break;
5151         default:
5152                 return WERR_UNKNOWN_LEVEL;
5153         }
5154
5155         return errcode;
5156 }
5157
5158
5159 /****************************************************************
5160  _spoolss_AbortPrinter
5161  * From MSDN: "Deletes printer's spool file if printer is configured
5162  * for spooling"
5163 ****************************************************************/
5164
5165 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5166                              struct spoolss_AbortPrinter *r)
5167 {
5168         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5169         int             snum;
5170         WERROR          errcode = WERR_OK;
5171
5172         if (!Printer) {
5173                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5174                         OUR_HANDLE(r->in.handle)));
5175                 return WERR_BADFID;
5176         }
5177
5178         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5179                 return WERR_BADFID;
5180
5181         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5182
5183         return errcode;
5184 }
5185
5186 /********************************************************************
5187  * called by spoolss_api_setprinter
5188  * when updating a printer description
5189  ********************************************************************/
5190
5191 static WERROR update_printer_sec(struct policy_handle *handle,
5192                                  pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5193 {
5194         struct spoolss_security_descriptor *new_secdesc = NULL;
5195         struct spoolss_security_descriptor *old_secdesc = NULL;
5196         const char *printer;
5197         WERROR result;
5198         int snum;
5199
5200         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5201
5202         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5203                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5204                          OUR_HANDLE(handle)));
5205
5206                 result = WERR_BADFID;
5207                 goto done;
5208         }
5209
5210         if (secdesc_ctr == NULL) {
5211                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5212                 result = WERR_INVALID_PARAM;
5213                 goto done;
5214         }
5215         printer = lp_const_servicename(snum);
5216
5217         /* Check the user has permissions to change the security
5218            descriptor.  By experimentation with two NT machines, the user
5219            requires Full Access to the printer to change security
5220            information. */
5221
5222         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5223                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5224                 result = WERR_ACCESS_DENIED;
5225                 goto done;
5226         }
5227
5228         /* NT seems to like setting the security descriptor even though
5229            nothing may have actually changed. */
5230         result = winreg_get_printer_secdesc(p->mem_ctx,
5231                                             p->server_info,
5232                                             printer,
5233                                             &old_secdesc);
5234         if (!W_ERROR_IS_OK(result)) {
5235                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5236                 result = WERR_BADFID;
5237                 goto done;
5238         }
5239
5240         if (DEBUGLEVEL >= 10) {
5241                 struct security_acl *the_acl;
5242                 int i;
5243
5244                 the_acl = secdesc_ctr->sd->dacl;
5245                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5246                            printer, the_acl->num_aces));
5247
5248                 for (i = 0; i < the_acl->num_aces; i++) {
5249                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5250                                            &the_acl->aces[i].trustee),
5251                                   the_acl->aces[i].access_mask));
5252                 }
5253
5254                 the_acl = secdesc_ctr->sd->dacl;
5255
5256                 if (the_acl) {
5257                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5258                                    printer, the_acl->num_aces));
5259
5260                         for (i = 0; i < the_acl->num_aces; i++) {
5261                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5262                                                    &the_acl->aces[i].trustee),
5263                                            the_acl->aces[i].access_mask));
5264                         }
5265                 } else {
5266                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5267                 }
5268         }
5269
5270         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5271         if (new_secdesc == NULL) {
5272                 result = WERR_NOMEM;
5273                 goto done;
5274         }
5275
5276         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5277                 result = WERR_OK;
5278                 goto done;
5279         }
5280
5281         result = winreg_set_printer_secdesc(p->mem_ctx,
5282                                             p->server_info,
5283                                             printer,
5284                                             new_secdesc);
5285
5286  done:
5287         return result;
5288 }
5289
5290 /********************************************************************
5291  Canonicalize printer info from a client
5292
5293  ATTN: It does not matter what we set the servername to hear
5294  since we do the necessary work in get_a_printer() to set it to
5295  the correct value based on what the client sent in the
5296  _spoolss_open_printer_ex().
5297  ********************************************************************/
5298
5299 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5300                              struct spoolss_SetPrinterInfo2 *info2,
5301                              int snum)
5302 {
5303         fstring printername;
5304         const char *p;
5305
5306         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5307                 "portname=%s drivername=%s comment=%s location=%s\n",
5308                 info2->servername, info2->printername, info2->sharename,
5309                 info2->portname, info2->drivername, info2->comment,
5310                 info2->location));
5311
5312         /* we force some elements to "correct" values */
5313         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5314         if (info2->servername == NULL) {
5315                 return false;
5316         }
5317         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5318         if (info2->sharename == NULL) {
5319                 return false;
5320         }
5321
5322         /* check to see if we allow printername != sharename */
5323         if (lp_force_printername(snum)) {
5324                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5325                                         global_myname(), info2->sharename);
5326         } else {
5327                 /* make sure printername is in \\server\printername format */
5328                 fstrcpy(printername, info2->printername);
5329                 p = printername;
5330                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5331                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5332                                 p++;
5333                 }
5334
5335                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5336                                         global_myname(), p);
5337         }
5338         if (info2->printername == NULL) {
5339                 return false;
5340         }
5341
5342         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5343         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5344
5345         return true;
5346 }
5347
5348 /****************************************************************************
5349 ****************************************************************************/
5350
5351 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5352 {
5353         char *cmd = lp_addport_cmd();
5354         char *command = NULL;
5355         int ret;
5356         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5357         bool is_print_op = false;
5358
5359         if ( !*cmd ) {
5360                 return WERR_ACCESS_DENIED;
5361         }
5362
5363         command = talloc_asprintf(ctx,
5364                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5365         if (!command) {
5366                 return WERR_NOMEM;
5367         }
5368
5369         if ( token )
5370                 is_print_op = user_has_privileges( token, &se_printop );
5371
5372         DEBUG(10,("Running [%s]\n", command));
5373
5374         /********* BEGIN SePrintOperatorPrivilege **********/
5375
5376         if ( is_print_op )
5377                 become_root();
5378
5379         ret = smbrun(command, NULL);
5380
5381         if ( is_print_op )
5382                 unbecome_root();
5383
5384         /********* END SePrintOperatorPrivilege **********/
5385
5386         DEBUGADD(10,("returned [%d]\n", ret));
5387
5388         TALLOC_FREE(command);
5389
5390         if ( ret != 0 ) {
5391                 return WERR_ACCESS_DENIED;
5392         }
5393
5394         return WERR_OK;
5395 }
5396
5397 /****************************************************************************
5398 ****************************************************************************/
5399
5400 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5401                       struct spoolss_SetPrinterInfo2 *info2)
5402 {
5403         char *cmd = lp_addprinter_cmd();
5404         char **qlines;
5405         char *command = NULL;
5406         int numlines;
5407         int ret;
5408         int fd;
5409         SE_PRIV se_printop = SE_PRINT_OPERATOR;
5410         bool is_print_op = false;
5411         char *remote_machine = talloc_strdup(ctx, "%m");
5412
5413         if (!remote_machine) {
5414                 return false;
5415         }
5416         remote_machine = talloc_sub_basic(ctx,
5417                                 current_user_info.smb_name,
5418                                 current_user_info.domain,
5419                                 remote_machine);
5420         if (!remote_machine) {
5421                 return false;
5422         }
5423
5424         command = talloc_asprintf(ctx,
5425                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5426                         cmd, info2->printername, info2->sharename,
5427                         info2->portname, info2->drivername,
5428                         info2->location, info2->comment, remote_machine);
5429         if (!command) {
5430                 return false;
5431         }
5432
5433         if ( token )
5434                 is_print_op = user_has_privileges( token, &se_printop );
5435
5436         DEBUG(10,("Running [%s]\n", command));
5437
5438         /********* BEGIN SePrintOperatorPrivilege **********/
5439
5440         if ( is_print_op )
5441                 become_root();
5442
5443         if ( (ret = smbrun(command, &fd)) == 0 ) {
5444                 /* Tell everyone we updated smb.conf. */
5445                 message_send_all(smbd_messaging_context(),
5446                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5447         }
5448
5449         if ( is_print_op )
5450                 unbecome_root();
5451
5452         /********* END SePrintOperatorPrivilege **********/
5453
5454         DEBUGADD(10,("returned [%d]\n", ret));
5455
5456         TALLOC_FREE(command);
5457         TALLOC_FREE(remote_machine);
5458
5459         if ( ret != 0 ) {
5460                 if (fd != -1)
5461                         close(fd);
5462                 return false;
5463         }
5464
5465         /* reload our services immediately */
5466         become_root();
5467         reload_services(false);
5468         unbecome_root();
5469
5470         numlines = 0;
5471         /* Get lines and convert them back to dos-codepage */
5472         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5473         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5474         close(fd);
5475
5476         /* Set the portname to what the script says the portname should be. */
5477         /* but don't require anything to be return from the script exit a good error code */
5478
5479         if (numlines) {
5480                 /* Set the portname to what the script says the portname should be. */
5481                 info2->portname = talloc_strdup(ctx, qlines[0]);
5482                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5483         }
5484
5485         TALLOC_FREE(qlines);
5486         return true;
5487 }
5488
5489
5490 /********************************************************************
5491  * Called by spoolss_api_setprinter
5492  * when updating a printer description.
5493  ********************************************************************/
5494
5495 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5496                              struct spoolss_SetPrinterInfoCtr *info_ctr,
5497                              struct spoolss_DeviceMode *devmode)
5498 {
5499         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
5500         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
5501         struct spoolss_PrinterInfo2 *old_printer;
5502         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5503         const char *servername = NULL;
5504         int snum;
5505         WERROR result;
5506         DATA_BLOB buffer;
5507         fstring asc_buffer;
5508
5509         DEBUG(8,("update_printer\n"));
5510
5511         result = WERR_OK;
5512
5513         if (!Printer) {
5514                 result = WERR_BADFID;
5515                 goto done;
5516         }
5517
5518         if (!get_printer_snum(p, handle, &snum, NULL)) {
5519                 result = WERR_BADFID;
5520                 goto done;
5521         }
5522
5523         if (Printer != NULL || Printer->servername != NULL) {
5524                 servername = Printer->servername;
5525         }
5526
5527         result = winreg_get_printer(p->mem_ctx,
5528                                     p->server_info,
5529                                     servername,
5530                                     lp_const_servicename(snum),
5531                                     &old_printer);
5532         if (!W_ERROR_IS_OK(result)) {
5533                 result = WERR_BADFID;
5534                 goto done;
5535         }
5536
5537         /* Do sanity check on the requested changes for Samba */
5538         if (!check_printer_ok(p->mem_ctx, printer, snum)) {
5539                 result = WERR_INVALID_PARAM;
5540                 goto done;
5541         }
5542
5543         /* FIXME!!! If the driver has changed we really should verify that
5544            it is installed before doing much else   --jerry */
5545
5546         /* Check calling user has permission to update printer description */
5547         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5548                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5549                 result = WERR_ACCESS_DENIED;
5550                 goto done;
5551         }
5552
5553         /* Call addprinter hook */
5554         /* Check changes to see if this is really needed */
5555
5556         if (*lp_addprinter_cmd() &&
5557                         (!strequal(printer->drivername, old_printer->drivername) ||
5558                          !strequal(printer->comment, old_printer->comment) ||
5559                          !strequal(printer->portname, old_printer->portname) ||
5560                          !strequal(printer->location, old_printer->location)) )
5561         {
5562                 /* add_printer_hook() will call reload_services() */
5563                 if (!add_printer_hook(p->mem_ctx, p->server_info->ptok,
5564                                       printer) ) {
5565                         result = WERR_ACCESS_DENIED;
5566                         goto done;
5567                 }
5568         }
5569
5570         /*
5571          * When a *new* driver is bound to a printer, the drivername is used to
5572          * lookup previously saved driver initialization info, which is then
5573          * bound to the printer, simulating what happens in the Windows arch.
5574          */
5575         if (!strequal(printer->drivername, old_printer->drivername)) {
5576                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
5577                         printer->drivername));
5578
5579                 notify_printer_driver(snum, printer->drivername);
5580         }
5581
5582         /*
5583          * flag which changes actually occured.  This is a small subset of
5584          * all the possible changes.  We also have to update things in the
5585          * DsSpooler key.
5586          */
5587         if (!strequal(printer->comment, old_printer->comment)) {
5588                 push_reg_sz(talloc_tos(), &buffer, printer->comment);
5589                 winreg_set_printer_dataex(p->mem_ctx,
5590                                           p->server_info,
5591                                           printer->sharename,
5592                                           SPOOL_DSSPOOLER_KEY,
5593                                           "description",
5594                                           REG_SZ,
5595                                           buffer.data,
5596                                           buffer.length);
5597
5598                 notify_printer_comment(snum, printer->comment);
5599         }
5600
5601         if (!strequal(printer->sharename, old_printer->sharename)) {
5602                 push_reg_sz(talloc_tos(), &buffer, printer->sharename);
5603                 winreg_set_printer_dataex(p->mem_ctx,
5604                                           p->server_info,
5605                                           printer->sharename,
5606                                           SPOOL_DSSPOOLER_KEY,
5607                                           "shareName",
5608                                           REG_SZ,
5609                                           buffer.data,
5610                                           buffer.length);
5611
5612                 notify_printer_sharename(snum, printer->sharename);
5613         }
5614
5615         if (!strequal(printer->printername, old_printer->printername)) {
5616                 const char *pname;
5617
5618                 if ( (pname = strchr_m( printer->printername+2, '\\' )) != NULL )
5619                         pname++;
5620                 else
5621                         pname = printer->printername;
5622
5623                 push_reg_sz(talloc_tos(), &buffer, pname);
5624                 winreg_set_printer_dataex(p->mem_ctx,
5625                                           p->server_info,
5626                                           printer->sharename,
5627                                           SPOOL_DSSPOOLER_KEY,
5628                                           "printerName",
5629                                           REG_SZ,
5630                                           buffer.data,
5631                                           buffer.length);
5632
5633                 notify_printer_printername( snum, pname );
5634         }
5635
5636         if (!strequal(printer->portname, old_printer->portname)) {
5637                 push_reg_sz(talloc_tos(), &buffer, printer->portname);
5638                 winreg_set_printer_dataex(p->mem_ctx,
5639                                           p->server_info,
5640                                           printer->sharename,
5641                                           SPOOL_DSSPOOLER_KEY,
5642                                           "portName",
5643                                           REG_SZ,
5644                                           buffer.data,
5645                                           buffer.length);
5646
5647                 notify_printer_port(snum, printer->portname);
5648         }
5649
5650         if (!strequal(printer->location, old_printer->location)) {
5651                 push_reg_sz(talloc_tos(), &buffer, printer->location);
5652                 winreg_set_printer_dataex(p->mem_ctx,
5653                                           p->server_info,
5654                                           printer->sharename,
5655                                           SPOOL_DSSPOOLER_KEY,
5656                                           "location",
5657                                           REG_SZ,
5658                                           buffer.data,
5659                                           buffer.length);
5660
5661                 notify_printer_location(snum, printer->location);
5662         }
5663
5664         /* here we need to update some more DsSpooler keys */
5665         /* uNCName, serverName, shortServerName */
5666
5667         push_reg_sz(talloc_tos(), &buffer, global_myname());
5668         winreg_set_printer_dataex(p->mem_ctx,
5669                                   p->server_info,
5670                                   printer->sharename,
5671                                   SPOOL_DSSPOOLER_KEY,
5672                                   "serverName",
5673                                   REG_SZ,
5674                                   buffer.data,
5675                                   buffer.length);
5676         winreg_set_printer_dataex(p->mem_ctx,
5677                                   p->server_info,
5678                                   printer->sharename,
5679                                   SPOOL_DSSPOOLER_KEY,
5680                                   "shortServerName",
5681                                   REG_SZ,
5682                                   buffer.data,
5683                                   buffer.length);
5684
5685         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5686                  global_myname(), printer->sharename );
5687         push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5688         winreg_set_printer_dataex(p->mem_ctx,
5689                                   p->server_info,
5690                                   printer->sharename,
5691                                   SPOOL_DSSPOOLER_KEY,
5692                                   "uNCName",
5693                                   REG_SZ,
5694                                   buffer.data,
5695                                   buffer.length);
5696
5697         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
5698
5699         if (devmode == NULL) {
5700                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
5701         }
5702         result = winreg_update_printer(p->mem_ctx,
5703                                        p->server_info,
5704                                        printer->sharename,
5705                                        printer_mask,
5706                                        printer,
5707                                        devmode,
5708                                        NULL);
5709
5710 done:
5711         talloc_free(old_printer);
5712
5713         return result;
5714 }
5715
5716 /****************************************************************************
5717 ****************************************************************************/
5718 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5719                                            struct policy_handle *handle,
5720                                            struct spoolss_SetPrinterInfo7 *info7)
5721 {
5722 #ifdef HAVE_ADS
5723         int snum;
5724         Printer_entry *Printer;
5725
5726         if ( lp_security() != SEC_ADS ) {
5727                 return WERR_UNKNOWN_LEVEL;
5728         }
5729
5730         Printer = find_printer_index_by_hnd(p, handle);
5731
5732         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5733
5734         if (!Printer)
5735                 return WERR_BADFID;
5736
5737         if (!get_printer_snum(p, handle, &snum, NULL))
5738                 return WERR_BADFID;
5739
5740         nt_printer_publish(Printer, snum, info7->action);
5741
5742         return WERR_OK;
5743 #else
5744         return WERR_UNKNOWN_LEVEL;
5745 #endif
5746 }
5747
5748 /********************************************************************
5749  ********************************************************************/
5750
5751 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5752                                      struct spoolss_DeviceMode *devmode)
5753 {
5754         int snum;
5755         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5756         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
5757
5758         DEBUG(8,("update_printer_devmode\n"));
5759
5760         if (!Printer) {
5761                 return WERR_BADFID;
5762         }
5763
5764         if (!get_printer_snum(p, handle, &snum, NULL)) {
5765                 return WERR_BADFID;
5766         }
5767
5768         /* Check calling user has permission to update printer description */
5769         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5770                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5771                 return WERR_ACCESS_DENIED;
5772         }
5773
5774         return winreg_update_printer(p->mem_ctx,
5775                                      p->server_info,
5776                                      lp_const_servicename(snum),
5777                                      info2_mask,
5778                                      NULL,
5779                                      devmode,
5780                                      NULL);
5781 }
5782
5783
5784 /****************************************************************
5785  _spoolss_SetPrinter
5786 ****************************************************************/
5787
5788 WERROR _spoolss_SetPrinter(pipes_struct *p,
5789                            struct spoolss_SetPrinter *r)
5790 {
5791         WERROR result;
5792
5793         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5794
5795         if (!Printer) {
5796                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5797                         OUR_HANDLE(r->in.handle)));
5798                 return WERR_BADFID;
5799         }
5800
5801         /* check the level */
5802         switch (r->in.info_ctr->level) {
5803                 case 0:
5804                         return control_printer(r->in.handle, r->in.command, p);
5805                 case 2:
5806                         result = update_printer(p, r->in.handle,
5807                                                 r->in.info_ctr,
5808                                                 r->in.devmode_ctr->devmode);
5809                         if (!W_ERROR_IS_OK(result))
5810                                 return result;
5811                         if (r->in.secdesc_ctr->sd)
5812                                 result = update_printer_sec(r->in.handle, p,
5813                                                             r->in.secdesc_ctr);
5814                         return result;
5815                 case 3:
5816                         return update_printer_sec(r->in.handle, p,
5817                                                   r->in.secdesc_ctr);
5818                 case 7:
5819                         return publish_or_unpublish_printer(p, r->in.handle,
5820                                                             r->in.info_ctr->info.info7);
5821                 case 8:
5822                         return update_printer_devmode(p, r->in.handle,
5823                                                       r->in.devmode_ctr->devmode);
5824                 default:
5825                         return WERR_UNKNOWN_LEVEL;
5826         }
5827 }
5828
5829 /****************************************************************
5830  _spoolss_FindClosePrinterNotify
5831 ****************************************************************/
5832
5833 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5834                                        struct spoolss_FindClosePrinterNotify *r)
5835 {
5836         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5837
5838         if (!Printer) {
5839                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5840                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5841                 return WERR_BADFID;
5842         }
5843
5844         if (Printer->notify.client_connected == true) {
5845                 int snum = -1;
5846
5847                 if ( Printer->printer_type == SPLHND_SERVER)
5848                         snum = -1;
5849                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5850                                 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5851                         return WERR_BADFID;
5852
5853                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5854         }
5855
5856         Printer->notify.flags=0;
5857         Printer->notify.options=0;
5858         Printer->notify.localmachine[0]='\0';
5859         Printer->notify.printerlocal=0;
5860         TALLOC_FREE(Printer->notify.option);
5861         Printer->notify.client_connected = false;
5862
5863         return WERR_OK;
5864 }
5865
5866 /****************************************************************
5867  _spoolss_AddJob
5868 ****************************************************************/
5869
5870 WERROR _spoolss_AddJob(pipes_struct *p,
5871                        struct spoolss_AddJob *r)
5872 {
5873         if (!r->in.buffer && (r->in.offered != 0)) {
5874                 return WERR_INVALID_PARAM;
5875         }
5876
5877         /* this is what a NT server returns for AddJob. AddJob must fail on
5878          * non-local printers */
5879
5880         if (r->in.level != 1) {
5881                 return WERR_UNKNOWN_LEVEL;
5882         }
5883
5884         return WERR_INVALID_PARAM;
5885 }
5886
5887 /****************************************************************************
5888 fill_job_info1
5889 ****************************************************************************/
5890
5891 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5892                              struct spoolss_JobInfo1 *r,
5893                              const print_queue_struct *queue,
5894                              int position, int snum,
5895                              struct spoolss_PrinterInfo2 *pinfo2)
5896 {
5897         struct tm *t;
5898
5899         t = gmtime(&queue->time);
5900
5901         r->job_id               = queue->job;
5902
5903         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
5904         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5905         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
5906         W_ERROR_HAVE_NO_MEMORY(r->server_name);
5907         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
5908         W_ERROR_HAVE_NO_MEMORY(r->user_name);
5909         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
5910         W_ERROR_HAVE_NO_MEMORY(r->document_name);
5911         r->data_type            = talloc_strdup(mem_ctx, "RAW");
5912         W_ERROR_HAVE_NO_MEMORY(r->data_type);
5913         r->text_status          = talloc_strdup(mem_ctx, "");
5914         W_ERROR_HAVE_NO_MEMORY(r->text_status);
5915
5916         r->status               = nt_printj_status(queue->status);
5917         r->priority             = queue->priority;
5918         r->position             = position;
5919         r->total_pages          = queue->page_count;
5920         r->pages_printed        = 0; /* ??? */
5921
5922         init_systemtime(&r->submitted, t);
5923
5924         return WERR_OK;
5925 }
5926
5927 /****************************************************************************
5928 fill_job_info2
5929 ****************************************************************************/
5930
5931 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5932                              struct spoolss_JobInfo2 *r,
5933                              const print_queue_struct *queue,
5934                              int position, int snum,
5935                              struct spoolss_PrinterInfo2 *pinfo2,
5936                              struct spoolss_DeviceMode *devmode)
5937 {
5938         struct tm *t;
5939
5940         t = gmtime(&queue->time);
5941
5942         r->job_id               = queue->job;
5943
5944         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
5945         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5946         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
5947         W_ERROR_HAVE_NO_MEMORY(r->server_name);
5948         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
5949         W_ERROR_HAVE_NO_MEMORY(r->user_name);
5950         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
5951         W_ERROR_HAVE_NO_MEMORY(r->document_name);
5952         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
5953         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5954         r->data_type            = talloc_strdup(mem_ctx, "RAW");
5955         W_ERROR_HAVE_NO_MEMORY(r->data_type);
5956         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
5957         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5958         r->parameters           = talloc_strdup(mem_ctx, "");
5959         W_ERROR_HAVE_NO_MEMORY(r->parameters);
5960         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
5961         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5962
5963         r->devmode              = devmode;
5964
5965         r->text_status          = talloc_strdup(mem_ctx, "");
5966         W_ERROR_HAVE_NO_MEMORY(r->text_status);
5967
5968         r->secdesc              = NULL;
5969
5970         r->status               = nt_printj_status(queue->status);
5971         r->priority             = queue->priority;
5972         r->position             = position;
5973         r->start_time           = 0;
5974         r->until_time           = 0;
5975         r->total_pages          = queue->page_count;
5976         r->size                 = queue->size;
5977         init_systemtime(&r->submitted, t);
5978         r->time                 = 0;
5979         r->pages_printed        = 0; /* ??? */
5980
5981         return WERR_OK;
5982 }
5983
5984 /****************************************************************************
5985 fill_job_info3
5986 ****************************************************************************/
5987
5988 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
5989                              struct spoolss_JobInfo3 *r,
5990                              const print_queue_struct *queue,
5991                              const print_queue_struct *next_queue,
5992                              int position, int snum,
5993                              struct spoolss_PrinterInfo2 *pinfo2)
5994 {
5995         r->job_id               = queue->job;
5996         r->next_job_id          = 0;
5997         if (next_queue) {
5998                 r->next_job_id  = next_queue->job;
5999         }
6000         r->reserved             = 0;
6001
6002         return WERR_OK;
6003 }
6004
6005 /****************************************************************************
6006  Enumjobs at level 1.
6007 ****************************************************************************/
6008
6009 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6010                               const print_queue_struct *queue,
6011                               uint32_t num_queues, int snum,
6012                               struct spoolss_PrinterInfo2 *pinfo2,
6013                               union spoolss_JobInfo **info_p,
6014                               uint32_t *count)
6015 {
6016         union spoolss_JobInfo *info;
6017         int i;
6018         WERROR result = WERR_OK;
6019
6020         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6021         W_ERROR_HAVE_NO_MEMORY(info);
6022
6023         *count = num_queues;
6024
6025         for (i=0; i<*count; i++) {
6026                 result = fill_job_info1(info,
6027                                         &info[i].info1,
6028                                         &queue[i],
6029                                         i,
6030                                         snum,
6031                                         pinfo2);
6032                 if (!W_ERROR_IS_OK(result)) {
6033                         goto out;
6034                 }
6035         }
6036
6037  out:
6038         if (!W_ERROR_IS_OK(result)) {
6039                 TALLOC_FREE(info);
6040                 *count = 0;
6041                 return result;
6042         }
6043
6044         *info_p = info;
6045
6046         return WERR_OK;
6047 }
6048
6049 /****************************************************************************
6050  Enumjobs at level 2.
6051 ****************************************************************************/
6052
6053 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6054                               const print_queue_struct *queue,
6055                               uint32_t num_queues, int snum,
6056                               struct spoolss_PrinterInfo2 *pinfo2,
6057                               union spoolss_JobInfo **info_p,
6058                               uint32_t *count)
6059 {
6060         struct spoolss_DeviceMode *devmode;
6061         union spoolss_JobInfo *info;
6062         int i;
6063         WERROR result = WERR_OK;
6064
6065         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6066         W_ERROR_HAVE_NO_MEMORY(info);
6067
6068         *count = num_queues;
6069
6070         for (i=0; i<*count; i++) {
6071
6072                 if (!pinfo2->devmode) {
6073                         result = spoolss_create_default_devmode(info,
6074                                                         pinfo2->printername,
6075                                                         &devmode);
6076                 } else {
6077                         result = copy_devicemode(info,
6078                                                  pinfo2->devmode,
6079                                                  &devmode);
6080                 }
6081                 if (!W_ERROR_IS_OK(result)) {
6082                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6083                         goto out;
6084                 }
6085
6086                 result = fill_job_info2(info,
6087                                         &info[i].info2,
6088                                         &queue[i],
6089                                         i,
6090                                         snum,
6091                                         pinfo2,
6092                                         devmode);
6093                 if (!W_ERROR_IS_OK(result)) {
6094                         goto out;
6095                 }
6096         }
6097
6098  out:
6099         if (!W_ERROR_IS_OK(result)) {
6100                 TALLOC_FREE(info);
6101                 *count = 0;
6102                 return result;
6103         }
6104
6105         *info_p = info;
6106
6107         return WERR_OK;
6108 }
6109
6110 /****************************************************************************
6111  Enumjobs at level 3.
6112 ****************************************************************************/
6113
6114 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6115                               const print_queue_struct *queue,
6116                               uint32_t num_queues, int snum,
6117                               struct spoolss_PrinterInfo2 *pinfo2,
6118                               union spoolss_JobInfo **info_p,
6119                               uint32_t *count)
6120 {
6121         union spoolss_JobInfo *info;
6122         int i;
6123         WERROR result = WERR_OK;
6124
6125         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6126         W_ERROR_HAVE_NO_MEMORY(info);
6127
6128         *count = num_queues;
6129
6130         for (i=0; i<*count; i++) {
6131                 const print_queue_struct *next_queue = NULL;
6132
6133                 if (i+1 < *count) {
6134                         next_queue = &queue[i+1];
6135                 }
6136
6137                 result = fill_job_info3(info,
6138                                         &info[i].info3,
6139                                         &queue[i],
6140                                         next_queue,
6141                                         i,
6142                                         snum,
6143                                         pinfo2);
6144                 if (!W_ERROR_IS_OK(result)) {
6145                         goto out;
6146                 }
6147         }
6148
6149  out:
6150         if (!W_ERROR_IS_OK(result)) {
6151                 TALLOC_FREE(info);
6152                 *count = 0;
6153                 return result;
6154         }
6155
6156         *info_p = info;
6157
6158         return WERR_OK;
6159 }
6160
6161 /****************************************************************
6162  _spoolss_EnumJobs
6163 ****************************************************************/
6164
6165 WERROR _spoolss_EnumJobs(pipes_struct *p,
6166                          struct spoolss_EnumJobs *r)
6167 {
6168         WERROR result;
6169         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6170         int snum;
6171         print_status_struct prt_status;
6172         print_queue_struct *queue = NULL;
6173         uint32_t count;
6174
6175         /* that's an [in out] buffer */
6176
6177         if (!r->in.buffer && (r->in.offered != 0)) {
6178                 return WERR_INVALID_PARAM;
6179         }
6180
6181         DEBUG(4,("_spoolss_EnumJobs\n"));
6182
6183         *r->out.needed = 0;
6184         *r->out.count = 0;
6185         *r->out.info = NULL;
6186
6187         /* lookup the printer snum and tdb entry */
6188
6189         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6190                 return WERR_BADFID;
6191         }
6192
6193         result = winreg_get_printer(talloc_tos(), p->server_info, NULL,
6194                                     lp_servicename(snum), &pinfo2);
6195         if (!W_ERROR_IS_OK(result)) {
6196                 return result;
6197         }
6198
6199         count = print_queue_status(snum, &queue, &prt_status);
6200         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6201                 count, prt_status.status, prt_status.message));
6202
6203         if (count == 0) {
6204                 SAFE_FREE(queue);
6205                 TALLOC_FREE(pinfo2);
6206                 return WERR_OK;
6207         }
6208
6209         switch (r->in.level) {
6210         case 1:
6211                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6212                                          pinfo2, r->out.info, r->out.count);
6213                 break;
6214         case 2:
6215                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6216                                          pinfo2, r->out.info, r->out.count);
6217                 break;
6218         case 3:
6219                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6220                                          pinfo2, r->out.info, r->out.count);
6221                 break;
6222         default:
6223                 result = WERR_UNKNOWN_LEVEL;
6224                 break;
6225         }
6226
6227         SAFE_FREE(queue);
6228         TALLOC_FREE(pinfo2);
6229
6230         if (!W_ERROR_IS_OK(result)) {
6231                 return result;
6232         }
6233
6234         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6235                                                      spoolss_EnumJobs, 
6236                                                      *r->out.info, r->in.level,
6237                                                      *r->out.count);
6238         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6239         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6240
6241         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6242 }
6243
6244 /****************************************************************
6245  _spoolss_ScheduleJob
6246 ****************************************************************/
6247
6248 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6249                             struct spoolss_ScheduleJob *r)
6250 {
6251         return WERR_OK;
6252 }
6253
6254 /****************************************************************
6255 ****************************************************************/
6256
6257 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6258                                const char *printer_name,
6259                                uint32_t job_id,
6260                                struct spoolss_SetJobInfo1 *r)
6261 {
6262         char *old_doc_name;
6263
6264         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6265                 return WERR_BADFID;
6266         }
6267
6268         if (strequal(old_doc_name, r->document_name)) {
6269                 return WERR_OK;
6270         }
6271
6272         if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6273                 return WERR_BADFID;
6274         }
6275
6276         return WERR_OK;
6277 }
6278
6279 /****************************************************************
6280  _spoolss_SetJob
6281 ****************************************************************/
6282
6283 WERROR _spoolss_SetJob(pipes_struct *p,
6284                        struct spoolss_SetJob *r)
6285 {
6286         int snum;
6287         WERROR errcode = WERR_BADFUNC;
6288
6289         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6290                 return WERR_BADFID;
6291         }
6292
6293         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6294                 return WERR_INVALID_PRINTER_NAME;
6295         }
6296
6297         switch (r->in.command) {
6298         case SPOOLSS_JOB_CONTROL_CANCEL:
6299         case SPOOLSS_JOB_CONTROL_DELETE:
6300                 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6301                         errcode = WERR_OK;
6302                 }
6303                 break;
6304         case SPOOLSS_JOB_CONTROL_PAUSE:
6305                 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6306                         errcode = WERR_OK;
6307                 }
6308                 break;
6309         case SPOOLSS_JOB_CONTROL_RESTART:
6310         case SPOOLSS_JOB_CONTROL_RESUME:
6311                 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6312                         errcode = WERR_OK;
6313                 }
6314                 break;
6315         case 0:
6316                 errcode = WERR_OK;
6317                 break;
6318         default:
6319                 return WERR_UNKNOWN_LEVEL;
6320         }
6321
6322         if (!W_ERROR_IS_OK(errcode)) {
6323                 return errcode;
6324         }
6325
6326         if (r->in.ctr == NULL) {
6327                 return errcode;
6328         }
6329
6330         switch (r->in.ctr->level) {
6331         case 1:
6332                 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6333                                            r->in.job_id,
6334                                            r->in.ctr->info.info1);
6335                 break;
6336         case 2:
6337         case 3:
6338         case 4:
6339         default:
6340                 return WERR_UNKNOWN_LEVEL;
6341         }
6342
6343         return errcode;
6344 }
6345
6346 /****************************************************************************
6347  Enumerates all printer drivers by level and architecture.
6348 ****************************************************************************/
6349
6350 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6351                                                        struct auth_serversupplied_info *server_info,
6352                                                        const char *servername,
6353                                                        const char *architecture,
6354                                                        uint32_t level,
6355                                                        union spoolss_DriverInfo **info_p,
6356                                                        uint32_t *count_p)
6357 {
6358         int i;
6359         uint32_t version;
6360         struct spoolss_DriverInfo8 *driver;
6361         union spoolss_DriverInfo *info = NULL;
6362         uint32_t count = 0;
6363         WERROR result = WERR_OK;
6364         uint32_t num_drivers;
6365         const char **drivers;
6366
6367         *count_p = 0;
6368         *info_p = NULL;
6369
6370         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6371                 result = winreg_get_driver_list(mem_ctx, server_info,
6372                                                 architecture, version,
6373                                                 &num_drivers, &drivers);
6374                 if (!W_ERROR_IS_OK(result)) {
6375                         goto out;
6376                 }
6377                 DEBUG(4, ("we have:[%d] drivers in environment"
6378                           " [%s] and version [%d]\n",
6379                           num_drivers, architecture, version));
6380
6381                 if (num_drivers != 0) {
6382                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6383                                                     union spoolss_DriverInfo,
6384                                                     count + num_drivers);
6385                         if (!info) {
6386                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6387                                         "failed to enlarge driver info buffer!\n"));
6388                                 result = WERR_NOMEM;
6389                                 goto out;
6390                         }
6391                 }
6392
6393                 for (i = 0; i < num_drivers; i++) {
6394                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6395
6396                         result = winreg_get_driver(mem_ctx, server_info,
6397                                                    architecture, drivers[i],
6398                                                    version, &driver);
6399                         if (!W_ERROR_IS_OK(result)) {
6400                                 goto out;
6401                         }
6402
6403                         switch (level) {
6404                         case 1:
6405                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
6406                                                                    driver, servername);
6407                                 break;
6408                         case 2:
6409                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
6410                                                                    driver, servername);
6411                                 break;
6412                         case 3:
6413                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
6414                                                                    driver, servername);
6415                                 break;
6416                         case 4:
6417                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
6418                                                                    driver, servername);
6419                                 break;
6420                         case 5:
6421                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
6422                                                                    driver, servername);
6423                                 break;
6424                         case 6:
6425                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
6426                                                                    driver, servername);
6427                                 break;
6428                         case 8:
6429                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
6430                                                                    driver, servername);
6431                                 break;
6432                         default:
6433                                 result = WERR_UNKNOWN_LEVEL;
6434                                 break;
6435                         }
6436
6437                         TALLOC_FREE(driver);
6438
6439                         if (!W_ERROR_IS_OK(result)) {
6440                                 goto out;
6441                         }
6442                 }
6443
6444                 count += num_drivers;
6445                 TALLOC_FREE(drivers);
6446         }
6447
6448  out:
6449         TALLOC_FREE(drivers);
6450
6451         if (!W_ERROR_IS_OK(result)) {
6452                 TALLOC_FREE(info);
6453                 return result;
6454         }
6455
6456         *info_p = info;
6457         *count_p = count;
6458
6459         return WERR_OK;
6460 }
6461
6462 /****************************************************************************
6463  Enumerates all printer drivers by level.
6464 ****************************************************************************/
6465
6466 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6467                                        struct auth_serversupplied_info *server_info,
6468                                        const char *servername,
6469                                        const char *architecture,
6470                                        uint32_t level,
6471                                        union spoolss_DriverInfo **info_p,
6472                                        uint32_t *count_p)
6473 {
6474         uint32_t a,i;
6475         WERROR result = WERR_OK;
6476
6477         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6478
6479                 for (a=0; archi_table[a].long_archi != NULL; a++) {
6480
6481                         union spoolss_DriverInfo *info = NULL;
6482                         uint32_t count = 0;
6483
6484                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
6485                                                                           server_info,
6486                                                                           servername,
6487                                                                           archi_table[a].long_archi,
6488                                                                           level,
6489                                                                           &info,
6490                                                                           &count);
6491                         if (!W_ERROR_IS_OK(result)) {
6492                                 continue;
6493                         }
6494
6495                         for (i=0; i < count; i++) {
6496                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6497                                              info[i], info_p, count_p);
6498                         }
6499                 }
6500
6501                 return result;
6502         }
6503
6504         return enumprinterdrivers_level_by_architecture(mem_ctx,
6505                                                         server_info,
6506                                                         servername,
6507                                                         architecture,
6508                                                         level,
6509                                                         info_p,
6510                                                         count_p);
6511 }
6512
6513 /****************************************************************
6514  _spoolss_EnumPrinterDrivers
6515 ****************************************************************/
6516
6517 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6518                                    struct spoolss_EnumPrinterDrivers *r)
6519 {
6520         const char *cservername;
6521         WERROR result;
6522
6523         /* that's an [in out] buffer */
6524
6525         if (!r->in.buffer && (r->in.offered != 0)) {
6526                 return WERR_INVALID_PARAM;
6527         }
6528
6529         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6530
6531         *r->out.needed = 0;
6532         *r->out.count = 0;
6533         *r->out.info = NULL;
6534
6535         cservername = canon_servername(r->in.server);
6536
6537         if (!is_myname_or_ipaddr(cservername)) {
6538                 return WERR_UNKNOWN_PRINTER_DRIVER;
6539         }
6540
6541         result = enumprinterdrivers_level(p->mem_ctx,
6542                                           p->server_info,
6543                                           cservername,
6544                                           r->in.environment,
6545                                           r->in.level,
6546                                           r->out.info,
6547                                           r->out.count);
6548         if (!W_ERROR_IS_OK(result)) {
6549                 return result;
6550         }
6551
6552         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6553                                                      spoolss_EnumPrinterDrivers, 
6554                                                      *r->out.info, r->in.level,
6555                                                      *r->out.count);
6556         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6557         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6558
6559         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6560 }
6561
6562 /****************************************************************
6563  _spoolss_EnumForms
6564 ****************************************************************/
6565
6566 WERROR _spoolss_EnumForms(pipes_struct *p,
6567                           struct spoolss_EnumForms *r)
6568 {
6569         WERROR result;
6570
6571         *r->out.count = 0;
6572         *r->out.needed = 0;
6573         *r->out.info = NULL;
6574
6575         /* that's an [in out] buffer */
6576
6577         if (!r->in.buffer && (r->in.offered != 0) ) {
6578                 return WERR_INVALID_PARAM;
6579         }
6580
6581         DEBUG(4,("_spoolss_EnumForms\n"));
6582         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6583         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6584
6585         switch (r->in.level) {
6586         case 1:
6587                 result = winreg_printer_enumforms1(p->mem_ctx,
6588                                                    p->server_info,
6589                                                    r->out.count,
6590                                                    r->out.info);
6591                 break;
6592         default:
6593                 result = WERR_UNKNOWN_LEVEL;
6594                 break;
6595         }
6596
6597         if (!W_ERROR_IS_OK(result)) {
6598                 return result;
6599         }
6600
6601         if (*r->out.count == 0) {
6602                 return WERR_NO_MORE_ITEMS;
6603         }
6604
6605         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6606                                                      spoolss_EnumForms, 
6607                                                      *r->out.info, r->in.level,
6608                                                      *r->out.count);
6609         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6610         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6611
6612         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6613 }
6614
6615 /****************************************************************
6616  _spoolss_GetForm
6617 ****************************************************************/
6618
6619 WERROR _spoolss_GetForm(pipes_struct *p,
6620                         struct spoolss_GetForm *r)
6621 {
6622         WERROR result;
6623
6624         /* that's an [in out] buffer */
6625
6626         if (!r->in.buffer && (r->in.offered != 0)) {
6627                 return WERR_INVALID_PARAM;
6628         }
6629
6630         DEBUG(4,("_spoolss_GetForm\n"));
6631         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6632         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
6633
6634         switch (r->in.level) {
6635         case 1:
6636                 result = winreg_printer_getform1(p->mem_ctx,
6637                                                  p->server_info,
6638                                                  r->in.form_name,
6639                                                  &r->out.info->info1);
6640                 break;
6641         default:
6642                 result = WERR_UNKNOWN_LEVEL;
6643                 break;
6644         }
6645
6646         if (!W_ERROR_IS_OK(result)) {
6647                 TALLOC_FREE(r->out.info);
6648                 return result;
6649         }
6650
6651         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
6652                                                r->out.info, r->in.level);
6653         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6654
6655         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6656 }
6657
6658 /****************************************************************************
6659 ****************************************************************************/
6660
6661 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6662                           struct spoolss_PortInfo1 *r,
6663                           const char *name)
6664 {
6665         r->port_name = talloc_strdup(mem_ctx, name);
6666         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6667
6668         return WERR_OK;
6669 }
6670
6671 /****************************************************************************
6672  TODO: This probably needs distinguish between TCP/IP and Local ports
6673  somehow.
6674 ****************************************************************************/
6675
6676 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6677                           struct spoolss_PortInfo2 *r,
6678                           const char *name)
6679 {
6680         r->port_name = talloc_strdup(mem_ctx, name);
6681         W_ERROR_HAVE_NO_MEMORY(r->port_name);
6682
6683         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6684         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6685
6686         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6687         W_ERROR_HAVE_NO_MEMORY(r->description);
6688
6689         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6690         r->reserved = 0;
6691
6692         return WERR_OK;
6693 }
6694
6695
6696 /****************************************************************************
6697  wrapper around the enumer ports command
6698 ****************************************************************************/
6699
6700 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6701 {
6702         char *cmd = lp_enumports_cmd();
6703         char **qlines = NULL;
6704         char *command = NULL;
6705         int numlines;
6706         int ret;
6707         int fd;
6708
6709         *count = 0;
6710         *lines = NULL;
6711
6712         /* if no hook then just fill in the default port */
6713
6714         if ( !*cmd ) {
6715                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6716                         return WERR_NOMEM;
6717                 }
6718                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6719                         TALLOC_FREE(qlines);
6720                         return WERR_NOMEM;
6721                 }
6722                 qlines[1] = NULL;
6723                 numlines = 1;
6724         }
6725         else {
6726                 /* we have a valid enumport command */
6727
6728                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6729                 if (!command) {
6730                         return WERR_NOMEM;
6731                 }
6732
6733                 DEBUG(10,("Running [%s]\n", command));
6734                 ret = smbrun(command, &fd);
6735                 DEBUG(10,("Returned [%d]\n", ret));
6736                 TALLOC_FREE(command);
6737                 if (ret != 0) {
6738                         if (fd != -1) {
6739                                 close(fd);
6740                         }
6741                         return WERR_ACCESS_DENIED;
6742                 }
6743
6744                 numlines = 0;
6745                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6746                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6747                 close(fd);
6748         }
6749
6750         *count = numlines;
6751         *lines = qlines;
6752
6753         return WERR_OK;
6754 }
6755
6756 /****************************************************************************
6757  enumports level 1.
6758 ****************************************************************************/
6759
6760 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6761                                 union spoolss_PortInfo **info_p,
6762                                 uint32_t *count)
6763 {
6764         union spoolss_PortInfo *info = NULL;
6765         int i=0;
6766         WERROR result = WERR_OK;
6767         char **qlines = NULL;
6768         int numlines = 0;
6769
6770         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6771         if (!W_ERROR_IS_OK(result)) {
6772                 goto out;
6773         }
6774
6775         if (numlines) {
6776                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6777                 if (!info) {
6778                         DEBUG(10,("Returning WERR_NOMEM\n"));
6779                         result = WERR_NOMEM;
6780                         goto out;
6781                 }
6782
6783                 for (i=0; i<numlines; i++) {
6784                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6785                         result = fill_port_1(info, &info[i].info1, qlines[i]);
6786                         if (!W_ERROR_IS_OK(result)) {
6787                                 goto out;
6788                         }
6789                 }
6790         }
6791         TALLOC_FREE(qlines);
6792
6793 out:
6794         if (!W_ERROR_IS_OK(result)) {
6795                 TALLOC_FREE(info);
6796                 TALLOC_FREE(qlines);
6797                 *count = 0;
6798                 *info_p = NULL;
6799                 return result;
6800         }
6801
6802         *info_p = info;
6803         *count = numlines;
6804
6805         return WERR_OK;
6806 }
6807
6808 /****************************************************************************
6809  enumports level 2.
6810 ****************************************************************************/
6811
6812 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6813                                 union spoolss_PortInfo **info_p,
6814                                 uint32_t *count)
6815 {
6816         union spoolss_PortInfo *info = NULL;
6817         int i=0;
6818         WERROR result = WERR_OK;
6819         char **qlines = NULL;
6820         int numlines = 0;
6821
6822         result = enumports_hook(talloc_tos(), &numlines, &qlines );
6823         if (!W_ERROR_IS_OK(result)) {
6824                 goto out;
6825         }
6826
6827         if (numlines) {
6828                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6829                 if (!info) {
6830                         DEBUG(10,("Returning WERR_NOMEM\n"));
6831                         result = WERR_NOMEM;
6832                         goto out;
6833                 }
6834
6835                 for (i=0; i<numlines; i++) {
6836                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6837                         result = fill_port_2(info, &info[i].info2, qlines[i]);
6838                         if (!W_ERROR_IS_OK(result)) {
6839                                 goto out;
6840                         }
6841                 }
6842         }
6843         TALLOC_FREE(qlines);
6844
6845 out:
6846         if (!W_ERROR_IS_OK(result)) {
6847                 TALLOC_FREE(info);
6848                 TALLOC_FREE(qlines);
6849                 *count = 0;
6850                 *info_p = NULL;
6851                 return result;
6852         }
6853
6854         *info_p = info;
6855         *count = numlines;
6856
6857         return WERR_OK;
6858 }
6859
6860 /****************************************************************
6861  _spoolss_EnumPorts
6862 ****************************************************************/
6863
6864 WERROR _spoolss_EnumPorts(pipes_struct *p,
6865                           struct spoolss_EnumPorts *r)
6866 {
6867         WERROR result;
6868
6869         /* that's an [in out] buffer */
6870
6871         if (!r->in.buffer && (r->in.offered != 0)) {
6872                 return WERR_INVALID_PARAM;
6873         }
6874
6875         DEBUG(4,("_spoolss_EnumPorts\n"));
6876
6877         *r->out.count = 0;
6878         *r->out.needed = 0;
6879         *r->out.info = NULL;
6880
6881         switch (r->in.level) {
6882         case 1:
6883                 result = enumports_level_1(p->mem_ctx, r->out.info,
6884                                            r->out.count);
6885                 break;
6886         case 2:
6887                 result = enumports_level_2(p->mem_ctx, r->out.info,
6888                                            r->out.count);
6889                 break;
6890         default:
6891                 return WERR_UNKNOWN_LEVEL;
6892         }
6893
6894         if (!W_ERROR_IS_OK(result)) {
6895                 return result;
6896         }
6897
6898         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6899                                                      spoolss_EnumPorts, 
6900                                                      *r->out.info, r->in.level,
6901                                                      *r->out.count);
6902         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6903         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6904
6905         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6906 }
6907
6908 /****************************************************************************
6909 ****************************************************************************/
6910
6911 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
6912                                            const char *server,
6913                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
6914                                            struct spoolss_DeviceMode *devmode,
6915                                            struct security_descriptor *secdesc,
6916                                            struct spoolss_UserLevelCtr *user_ctr,
6917                                            struct policy_handle *handle)
6918 {
6919         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
6920         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
6921         int     snum;
6922         WERROR err = WERR_OK;
6923
6924         /* samba does not have a concept of local, non-shared printers yet, so
6925          * make sure we always setup sharename - gd */
6926         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
6927             (info2->printername != NULL && info2->printername[0] != '\0')) {
6928                 DEBUG(5, ("spoolss_addprinterex_level_2: "
6929                         "no sharename has been set, setting printername %s as sharename\n",
6930                         info2->printername));
6931                 info2->sharename = info2->printername;
6932         }
6933
6934         /* check to see if the printer already exists */
6935         if ((snum = print_queue_snum(info2->sharename)) != -1) {
6936                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6937                         info2->sharename));
6938                 return WERR_PRINTER_ALREADY_EXISTS;
6939         }
6940
6941         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
6942                 if ((snum = print_queue_snum(info2->printername)) != -1) {
6943                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
6944                                 info2->printername));
6945                         return WERR_PRINTER_ALREADY_EXISTS;
6946                 }
6947         }
6948
6949         /* validate printer info struct */
6950         if (!info2->printername || strlen(info2->printername) == 0) {
6951                 return WERR_INVALID_PRINTER_NAME;
6952         }
6953         if (!info2->portname || strlen(info2->portname) == 0) {
6954                 return WERR_UNKNOWN_PORT;
6955         }
6956         if (!info2->drivername || strlen(info2->drivername) == 0) {
6957                 return WERR_UNKNOWN_PRINTER_DRIVER;
6958         }
6959         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
6960                 return WERR_UNKNOWN_PRINTPROCESSOR;
6961         }
6962
6963         /* FIXME!!!  smbd should check to see if the driver is installed before
6964            trying to add a printer like this  --jerry */
6965
6966         if (*lp_addprinter_cmd() ) {
6967                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6968                                        info2) ) {
6969                         return WERR_ACCESS_DENIED;
6970                 }
6971         } else {
6972                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
6973                         "smb.conf parameter \"addprinter command\" is defined. This"
6974                         "parameter must exist for this call to succeed\n",
6975                         info2->sharename ));
6976         }
6977
6978         if ((snum = print_queue_snum(info2->sharename)) == -1) {
6979                 return WERR_ACCESS_DENIED;
6980         }
6981
6982         /* you must be a printer admin to add a new printer */
6983         if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
6984                 return WERR_ACCESS_DENIED;
6985         }
6986
6987         /*
6988          * Do sanity check on the requested changes for Samba.
6989          */
6990
6991         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
6992                 return WERR_INVALID_PARAM;
6993         }
6994
6995         if (devmode == NULL) {
6996                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
6997         }
6998
6999         err = winreg_update_printer(p->mem_ctx,
7000                                     p->server_info,
7001                                     info2->sharename,
7002                                     info2_mask,
7003                                     info2,
7004                                     devmode,
7005                                     secdesc);
7006         if (!W_ERROR_IS_OK(err)) {
7007                 return err;
7008         }
7009
7010         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7011                 /* Handle open failed - remove addition. */
7012                 ZERO_STRUCTP(handle);
7013                 return WERR_ACCESS_DENIED;
7014         }
7015
7016         return WERR_OK;
7017 }
7018
7019 /****************************************************************
7020  _spoolss_AddPrinterEx
7021 ****************************************************************/
7022
7023 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7024                              struct spoolss_AddPrinterEx *r)
7025 {
7026         switch (r->in.info_ctr->level) {
7027         case 1:
7028                 /* we don't handle yet */
7029                 /* but I know what to do ... */
7030                 return WERR_UNKNOWN_LEVEL;
7031         case 2:
7032                 return spoolss_addprinterex_level_2(p, r->in.server,
7033                                                     r->in.info_ctr,
7034                                                     r->in.devmode_ctr->devmode,
7035                                                     r->in.secdesc_ctr->sd,
7036                                                     r->in.userlevel_ctr,
7037                                                     r->out.handle);
7038         default:
7039                 return WERR_UNKNOWN_LEVEL;
7040         }
7041 }
7042
7043 /****************************************************************
7044  _spoolss_AddPrinter
7045 ****************************************************************/
7046
7047 WERROR _spoolss_AddPrinter(pipes_struct *p,
7048                            struct spoolss_AddPrinter *r)
7049 {
7050         struct spoolss_AddPrinterEx a;
7051         struct spoolss_UserLevelCtr userlevel_ctr;
7052
7053         ZERO_STRUCT(userlevel_ctr);
7054
7055         userlevel_ctr.level = 1;
7056
7057         a.in.server             = r->in.server;
7058         a.in.info_ctr           = r->in.info_ctr;
7059         a.in.devmode_ctr        = r->in.devmode_ctr;
7060         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7061         a.in.userlevel_ctr      = &userlevel_ctr;
7062         a.out.handle            = r->out.handle;
7063
7064         return _spoolss_AddPrinterEx(p, &a);
7065 }
7066
7067 /****************************************************************
7068  _spoolss_AddPrinterDriverEx
7069 ****************************************************************/
7070
7071 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7072                                    struct spoolss_AddPrinterDriverEx *r)
7073 {
7074         WERROR err = WERR_OK;
7075         const char *driver_name = NULL;
7076         uint32_t version;
7077         const char *fn;
7078
7079         switch (p->opnum) {
7080                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7081                         fn = "_spoolss_AddPrinterDriver";
7082                         break;
7083                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7084                         fn = "_spoolss_AddPrinterDriverEx";
7085                         break;
7086                 default:
7087                         return WERR_INVALID_PARAM;
7088         }
7089
7090         /*
7091          * we only support the semantics of AddPrinterDriver()
7092          * i.e. only copy files that are newer than existing ones
7093          */
7094
7095         if (r->in.flags == 0) {
7096                 return WERR_INVALID_PARAM;
7097         }
7098
7099         if (r->in.flags != APD_COPY_NEW_FILES) {
7100                 return WERR_ACCESS_DENIED;
7101         }
7102
7103         /* FIXME */
7104         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7105                 /* Clever hack from Martin Zielinski <mz@seh.de>
7106                  * to allow downgrade from level 8 (Vista).
7107                  */
7108                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7109                         r->in.info_ctr->level));
7110                 return WERR_UNKNOWN_LEVEL;
7111         }
7112
7113         DEBUG(5,("Cleaning driver's information\n"));
7114         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7115         if (!W_ERROR_IS_OK(err))
7116                 goto done;
7117
7118         DEBUG(5,("Moving driver to final destination\n"));
7119         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7120                                                               &err)) ) {
7121                 goto done;
7122         }
7123
7124         err = winreg_add_driver(p->mem_ctx, p->server_info,
7125                                 r->in.info_ctr, &driver_name, &version);
7126         if (!W_ERROR_IS_OK(err)) {
7127                 goto done;
7128         }
7129
7130         /*
7131          * I think this is where he DrvUpgradePrinter() hook would be
7132          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7133          * server.  Right now, we just need to send ourselves a message
7134          * to update each printer bound to this driver.   --jerry
7135          */
7136
7137         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7138                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7139                         fn, driver_name));
7140         }
7141
7142 done:
7143         return err;
7144 }
7145
7146 /****************************************************************
7147  _spoolss_AddPrinterDriver
7148 ****************************************************************/
7149
7150 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7151                                  struct spoolss_AddPrinterDriver *r)
7152 {
7153         struct spoolss_AddPrinterDriverEx a;
7154
7155         switch (r->in.info_ctr->level) {
7156         case 2:
7157         case 3:
7158         case 4:
7159         case 5:
7160                 break;
7161         default:
7162                 return WERR_UNKNOWN_LEVEL;
7163         }
7164
7165         a.in.servername         = r->in.servername;
7166         a.in.info_ctr           = r->in.info_ctr;
7167         a.in.flags              = APD_COPY_NEW_FILES;
7168
7169         return _spoolss_AddPrinterDriverEx(p, &a);
7170 }
7171
7172 /****************************************************************************
7173 ****************************************************************************/
7174
7175 struct _spoolss_paths {
7176         int type;
7177         const char *share;
7178         const char *dir;
7179 };
7180
7181 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7182
7183 static const struct _spoolss_paths spoolss_paths[]= {
7184         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7185         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7186 };
7187
7188 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7189                                           const char *servername,
7190                                           const char *environment,
7191                                           int component,
7192                                           char **path)
7193 {
7194         const char *pservername = NULL;
7195         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7196         const char *short_archi;
7197
7198         *path = NULL;
7199
7200         /* environment may be empty */
7201         if (environment && strlen(environment)) {
7202                 long_archi = environment;
7203         }
7204
7205         /* servername may be empty */
7206         if (servername && strlen(servername)) {
7207                 pservername = canon_servername(servername);
7208
7209                 if (!is_myname_or_ipaddr(pservername)) {
7210                         return WERR_INVALID_PARAM;
7211                 }
7212         }
7213
7214         if (!(short_archi = get_short_archi(long_archi))) {
7215                 return WERR_INVALID_ENVIRONMENT;
7216         }
7217
7218         switch (component) {
7219         case SPOOLSS_PRTPROCS_PATH:
7220         case SPOOLSS_DRIVER_PATH:
7221                 if (pservername) {
7222                         *path = talloc_asprintf(mem_ctx,
7223                                         "\\\\%s\\%s\\%s",
7224                                         pservername,
7225                                         spoolss_paths[component].share,
7226                                         short_archi);
7227                 } else {
7228                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7229                                         SPOOLSS_DEFAULT_SERVER_PATH,
7230                                         spoolss_paths[component].dir,
7231                                         short_archi);
7232                 }
7233                 break;
7234         default:
7235                 return WERR_INVALID_PARAM;
7236         }
7237
7238         if (!*path) {
7239                 return WERR_NOMEM;
7240         }
7241
7242         return WERR_OK;
7243 }
7244
7245 /****************************************************************************
7246 ****************************************************************************/
7247
7248 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7249                                           const char *servername,
7250                                           const char *environment,
7251                                           struct spoolss_DriverDirectoryInfo1 *r)
7252 {
7253         WERROR werr;
7254         char *path = NULL;
7255
7256         werr = compose_spoolss_server_path(mem_ctx,
7257                                            servername,
7258                                            environment,
7259                                            SPOOLSS_DRIVER_PATH,
7260                                            &path);
7261         if (!W_ERROR_IS_OK(werr)) {
7262                 return werr;
7263         }
7264
7265         DEBUG(4,("printer driver directory: [%s]\n", path));
7266
7267         r->directory_name = path;
7268
7269         return WERR_OK;
7270 }
7271
7272 /****************************************************************
7273  _spoolss_GetPrinterDriverDirectory
7274 ****************************************************************/
7275
7276 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7277                                           struct spoolss_GetPrinterDriverDirectory *r)
7278 {
7279         WERROR werror;
7280
7281         /* that's an [in out] buffer */
7282
7283         if (!r->in.buffer && (r->in.offered != 0)) {
7284                 return WERR_INVALID_PARAM;
7285         }
7286
7287         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7288                 r->in.level));
7289
7290         *r->out.needed = 0;
7291
7292         /* r->in.level is ignored */
7293
7294         werror = getprinterdriverdir_level_1(p->mem_ctx,
7295                                              r->in.server,
7296                                              r->in.environment,
7297                                              &r->out.info->info1);
7298         if (!W_ERROR_IS_OK(werror)) {
7299                 TALLOC_FREE(r->out.info);
7300                 return werror;
7301         }
7302
7303         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
7304                                                r->out.info, r->in.level);
7305         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7306
7307         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7308 }
7309
7310 /****************************************************************
7311  _spoolss_EnumPrinterData
7312 ****************************************************************/
7313
7314 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7315                                 struct spoolss_EnumPrinterData *r)
7316 {
7317         WERROR result;
7318         struct spoolss_EnumPrinterDataEx r2;
7319         uint32_t count;
7320         struct spoolss_PrinterEnumValues *info, *val = NULL;
7321         uint32_t needed;
7322
7323         r2.in.handle    = r->in.handle;
7324         r2.in.key_name  = "PrinterDriverData";
7325         r2.in.offered   = 0;
7326         r2.out.count    = &count;
7327         r2.out.info     = &info;
7328         r2.out.needed   = &needed;
7329
7330         result = _spoolss_EnumPrinterDataEx(p, &r2);
7331         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7332                 r2.in.offered = needed;
7333                 result = _spoolss_EnumPrinterDataEx(p, &r2);
7334         }
7335         if (!W_ERROR_IS_OK(result)) {
7336                 return result;
7337         }
7338
7339         /*
7340          * The NT machine wants to know the biggest size of value and data
7341          *
7342          * cf: MSDN EnumPrinterData remark section
7343          */
7344
7345         if (!r->in.value_offered && !r->in.data_offered) {
7346                 uint32_t biggest_valuesize = 0;
7347                 uint32_t biggest_datasize = 0;
7348                 int i, name_length;
7349
7350                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7351
7352                 for (i=0; i<count; i++) {
7353
7354                         name_length = strlen(info[i].value_name);
7355                         if (strlen(info[i].value_name) > biggest_valuesize) {
7356                                 biggest_valuesize = name_length;
7357                         }
7358
7359                         if (info[i].data_length > biggest_datasize) {
7360                                 biggest_datasize = info[i].data_length;
7361                         }
7362
7363                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7364                                 biggest_datasize));
7365                 }
7366
7367                 /* the value is an UNICODE string but real_value_size is the length
7368                    in bytes including the trailing 0 */
7369
7370                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7371                 *r->out.data_needed  = biggest_datasize;
7372
7373                 DEBUG(6,("final values: [%d], [%d]\n",
7374                         *r->out.value_needed, *r->out.data_needed));
7375
7376                 return WERR_OK;
7377         }
7378
7379         if (r->in.enum_index < count) {
7380                 val = &info[r->in.enum_index];
7381         }
7382
7383         if (val == NULL) {
7384                 /* out_value should default to "" or else NT4 has
7385                    problems unmarshalling the response */
7386
7387                 if (r->in.value_offered) {
7388                         *r->out.value_needed = 1;
7389                         r->out.value_name = talloc_strdup(r, "");
7390                         if (!r->out.value_name) {
7391                                 return WERR_NOMEM;
7392                         }
7393                 } else {
7394                         r->out.value_name = NULL;
7395                         *r->out.value_needed = 0;
7396                 }
7397
7398                 /* the data is counted in bytes */
7399
7400                 *r->out.data_needed = r->in.data_offered;
7401
7402                 result = WERR_NO_MORE_ITEMS;
7403         } else {
7404                 /*
7405                  * the value is:
7406                  * - counted in bytes in the request
7407                  * - counted in UNICODE chars in the max reply
7408                  * - counted in bytes in the real size
7409                  *
7410                  * take a pause *before* coding not *during* coding
7411                  */
7412
7413                 /* name */
7414                 if (r->in.value_offered) {
7415                         r->out.value_name = talloc_strdup(r, val->value_name);
7416                         if (!r->out.value_name) {
7417                                 return WERR_NOMEM;
7418                         }
7419                         *r->out.value_needed = val->value_name_len;
7420                 } else {
7421                         r->out.value_name = NULL;
7422                         *r->out.value_needed = 0;
7423                 }
7424
7425                 /* type */
7426
7427                 *r->out.type = val->type;
7428
7429                 /* data - counted in bytes */
7430
7431                 /*
7432                  * See the section "Dynamically Typed Query Parameters"
7433                  * in MS-RPRN.
7434                  */
7435
7436                 if (r->out.data && val->data && val->data->data &&
7437                                 val->data_length && r->in.data_offered) {
7438                         memcpy(r->out.data, val->data->data,
7439                                 MIN(val->data_length,r->in.data_offered));
7440                 }
7441
7442                 *r->out.data_needed = val->data_length;
7443
7444                 result = WERR_OK;
7445         }
7446
7447         return result;
7448 }
7449
7450 /****************************************************************
7451  _spoolss_SetPrinterData
7452 ****************************************************************/
7453
7454 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7455                                struct spoolss_SetPrinterData *r)
7456 {
7457         struct spoolss_SetPrinterDataEx r2;
7458
7459         r2.in.handle            = r->in.handle;
7460         r2.in.key_name          = "PrinterDriverData";
7461         r2.in.value_name        = r->in.value_name;
7462         r2.in.type              = r->in.type;
7463         r2.in.data              = r->in.data;
7464         r2.in.offered           = r->in.offered;
7465
7466         return _spoolss_SetPrinterDataEx(p, &r2);
7467 }
7468
7469 /****************************************************************
7470  _spoolss_ResetPrinter
7471 ****************************************************************/
7472
7473 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7474                              struct spoolss_ResetPrinter *r)
7475 {
7476         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
7477         int             snum;
7478
7479         DEBUG(5,("_spoolss_ResetPrinter\n"));
7480
7481         /*
7482          * All we do is to check to see if the handle and queue is valid.
7483          * This call really doesn't mean anything to us because we only
7484          * support RAW printing.   --jerry
7485          */
7486
7487         if (!Printer) {
7488                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7489                         OUR_HANDLE(r->in.handle)));
7490                 return WERR_BADFID;
7491         }
7492
7493         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7494                 return WERR_BADFID;
7495
7496
7497         /* blindly return success */
7498         return WERR_OK;
7499 }
7500
7501 /****************************************************************
7502  _spoolss_DeletePrinterData
7503 ****************************************************************/
7504
7505 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7506                                   struct spoolss_DeletePrinterData *r)
7507 {
7508         struct spoolss_DeletePrinterDataEx r2;
7509
7510         r2.in.handle            = r->in.handle;
7511         r2.in.key_name          = "PrinterDriverData";
7512         r2.in.value_name        = r->in.value_name;
7513
7514         return _spoolss_DeletePrinterDataEx(p, &r2);
7515 }
7516
7517 /****************************************************************
7518  _spoolss_AddForm
7519 ****************************************************************/
7520
7521 WERROR _spoolss_AddForm(pipes_struct *p,
7522                         struct spoolss_AddForm *r)
7523 {
7524         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7525         int snum = -1;
7526         WERROR status = WERR_OK;
7527         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7528
7529         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7530
7531         DEBUG(5,("_spoolss_AddForm\n"));
7532
7533         if (!Printer) {
7534                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7535                         OUR_HANDLE(r->in.handle)));
7536                 return WERR_BADFID;
7537         }
7538
7539         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7540            and not a printer admin, then fail */
7541
7542         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7543              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7544              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7545                                           p->server_info->info3->base.domain.string,
7546                                           NULL,
7547                                           p->server_info->ptok,
7548                                           lp_printer_admin(snum))) {
7549                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7550                 return WERR_ACCESS_DENIED;
7551         }
7552
7553         switch (form->flags) {
7554         case SPOOLSS_FORM_USER:
7555         case SPOOLSS_FORM_BUILTIN:
7556         case SPOOLSS_FORM_PRINTER:
7557                 break;
7558         default:
7559                 return WERR_INVALID_PARAM;
7560         }
7561
7562         status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7563         if (!W_ERROR_IS_OK(status)) {
7564                 return status;
7565         }
7566
7567         /*
7568          * ChangeID must always be set if this is a printer
7569          */
7570         if (Printer->printer_type == SPLHND_PRINTER) {
7571                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7572                         return WERR_BADFID;
7573                 }
7574
7575                 status = winreg_printer_update_changeid(p->mem_ctx,
7576                                                         p->server_info,
7577                                                         lp_const_servicename(snum));
7578                 if (!W_ERROR_IS_OK(status)) {
7579                         return status;
7580                 }
7581         }
7582
7583         return status;
7584 }
7585
7586 /****************************************************************
7587  _spoolss_DeleteForm
7588 ****************************************************************/
7589
7590 WERROR _spoolss_DeleteForm(pipes_struct *p,
7591                            struct spoolss_DeleteForm *r)
7592 {
7593         const char *form_name = r->in.form_name;
7594         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7595         int snum = -1;
7596         WERROR status = WERR_OK;
7597         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7598
7599         DEBUG(5,("_spoolss_DeleteForm\n"));
7600
7601         if (!Printer) {
7602                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7603                         OUR_HANDLE(r->in.handle)));
7604                 return WERR_BADFID;
7605         }
7606
7607         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7608              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7609              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7610                                           p->server_info->info3->base.domain.string,
7611                                           NULL,
7612                                           p->server_info->ptok,
7613                                           lp_printer_admin(snum))) {
7614                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7615                 return WERR_ACCESS_DENIED;
7616         }
7617
7618         status = winreg_printer_deleteform1(p->mem_ctx,
7619                                             p->server_info,
7620                                             form_name);
7621         if (!W_ERROR_IS_OK(status)) {
7622                 return status;
7623         }
7624
7625         /*
7626          * ChangeID must always be set if this is a printer
7627          */
7628         if (Printer->printer_type == SPLHND_PRINTER) {
7629                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7630                         return WERR_BADFID;
7631                 }
7632
7633                 status = winreg_printer_update_changeid(p->mem_ctx,
7634                                                         p->server_info,
7635                                                         lp_const_servicename(snum));
7636                 if (!W_ERROR_IS_OK(status)) {
7637                         return status;
7638                 }
7639         }
7640
7641         return status;
7642 }
7643
7644 /****************************************************************
7645  _spoolss_SetForm
7646 ****************************************************************/
7647
7648 WERROR _spoolss_SetForm(pipes_struct *p,
7649                         struct spoolss_SetForm *r)
7650 {
7651         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7652         const char *form_name = r->in.form_name;
7653         int snum = -1;
7654         WERROR status = WERR_OK;
7655         SE_PRIV se_printop = SE_PRINT_OPERATOR;
7656
7657         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7658
7659         DEBUG(5,("_spoolss_SetForm\n"));
7660
7661         if (!Printer) {
7662                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7663                         OUR_HANDLE(r->in.handle)));
7664                 return WERR_BADFID;
7665         }
7666
7667         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7668            and not a printer admin, then fail */
7669
7670         if ((p->server_info->utok.uid != sec_initial_uid()) &&
7671              !user_has_privileges(p->server_info->ptok, &se_printop) &&
7672              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7673                                           p->server_info->info3->base.domain.string,
7674                                           NULL,
7675                                           p->server_info->ptok,
7676                                           lp_printer_admin(snum))) {
7677                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7678                 return WERR_ACCESS_DENIED;
7679         }
7680
7681         status = winreg_printer_setform1(p->mem_ctx,
7682                                          p->server_info,
7683                                          form_name,
7684                                          form);
7685         if (!W_ERROR_IS_OK(status)) {
7686                 return status;
7687         }
7688
7689         /*
7690          * ChangeID must always be set if this is a printer
7691          */
7692         if (Printer->printer_type == SPLHND_PRINTER) {
7693                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7694                         return WERR_BADFID;
7695                 }
7696
7697                 status = winreg_printer_update_changeid(p->mem_ctx,
7698                                                         p->server_info,
7699                                                         lp_const_servicename(snum));
7700                 if (!W_ERROR_IS_OK(status)) {
7701                         return status;
7702                 }
7703         }
7704
7705         return status;
7706 }
7707
7708 /****************************************************************************
7709  fill_print_processor1
7710 ****************************************************************************/
7711
7712 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7713                                     struct spoolss_PrintProcessorInfo1 *r,
7714                                     const char *print_processor_name)
7715 {
7716         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7717         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7718
7719         return WERR_OK;
7720 }
7721
7722 /****************************************************************************
7723  enumprintprocessors level 1.
7724 ****************************************************************************/
7725
7726 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7727                                           union spoolss_PrintProcessorInfo **info_p,
7728                                           uint32_t *count)
7729 {
7730         union spoolss_PrintProcessorInfo *info;
7731         WERROR result;
7732
7733         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7734         W_ERROR_HAVE_NO_MEMORY(info);
7735
7736         *count = 1;
7737
7738         result = fill_print_processor1(info, &info[0].info1, "winprint");
7739         if (!W_ERROR_IS_OK(result)) {
7740                 goto out;
7741         }
7742
7743  out:
7744         if (!W_ERROR_IS_OK(result)) {
7745                 TALLOC_FREE(info);
7746                 *count = 0;
7747                 return result;
7748         }
7749
7750         *info_p = info;
7751
7752         return WERR_OK;
7753 }
7754
7755 /****************************************************************
7756  _spoolss_EnumPrintProcessors
7757 ****************************************************************/
7758
7759 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7760                                     struct spoolss_EnumPrintProcessors *r)
7761 {
7762         WERROR result;
7763
7764         /* that's an [in out] buffer */
7765
7766         if (!r->in.buffer && (r->in.offered != 0)) {
7767                 return WERR_INVALID_PARAM;
7768         }
7769
7770         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7771
7772         /*
7773          * Enumerate the print processors ...
7774          *
7775          * Just reply with "winprint", to keep NT happy
7776          * and I can use my nice printer checker.
7777          */
7778
7779         *r->out.count = 0;
7780         *r->out.needed = 0;
7781         *r->out.info = NULL;
7782
7783         switch (r->in.level) {
7784         case 1:
7785                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7786                                                      r->out.count);
7787                 break;
7788         default:
7789                 return WERR_UNKNOWN_LEVEL;
7790         }
7791
7792         if (!W_ERROR_IS_OK(result)) {
7793                 return result;
7794         }
7795
7796         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7797                                                      spoolss_EnumPrintProcessors,
7798                                                      *r->out.info, r->in.level,
7799                                                      *r->out.count);
7800         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7801         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7802
7803         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7804 }
7805
7806 /****************************************************************************
7807  fill_printprocdatatype1
7808 ****************************************************************************/
7809
7810 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
7811                                       struct spoolss_PrintProcDataTypesInfo1 *r,
7812                                       const char *name_array)
7813 {
7814         r->name_array = talloc_strdup(mem_ctx, name_array);
7815         W_ERROR_HAVE_NO_MEMORY(r->name_array);
7816
7817         return WERR_OK;
7818 }
7819
7820 /****************************************************************************
7821  enumprintprocdatatypes level 1.
7822 ****************************************************************************/
7823
7824 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
7825                                              union spoolss_PrintProcDataTypesInfo **info_p,
7826                                              uint32_t *count)
7827 {
7828         WERROR result;
7829         union spoolss_PrintProcDataTypesInfo *info;
7830
7831         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
7832         W_ERROR_HAVE_NO_MEMORY(info);
7833
7834         *count = 1;
7835
7836         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
7837         if (!W_ERROR_IS_OK(result)) {
7838                 goto out;
7839         }
7840
7841  out:
7842         if (!W_ERROR_IS_OK(result)) {
7843                 TALLOC_FREE(info);
7844                 *count = 0;
7845                 return result;
7846         }
7847
7848         *info_p = info;
7849
7850         return WERR_OK;
7851 }
7852
7853 /****************************************************************
7854  _spoolss_EnumPrintProcDataTypes
7855 ****************************************************************/
7856
7857 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
7858                                        struct spoolss_EnumPrintProcDataTypes *r)
7859 {
7860         WERROR result;
7861
7862         /* that's an [in out] buffer */
7863
7864         if (!r->in.buffer && (r->in.offered != 0)) {
7865                 return WERR_INVALID_PARAM;
7866         }
7867
7868         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
7869
7870         *r->out.count = 0;
7871         *r->out.needed = 0;
7872         *r->out.info = NULL;
7873
7874         switch (r->in.level) {
7875         case 1:
7876                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
7877                                                         r->out.count);
7878                 break;
7879         default:
7880                 return WERR_UNKNOWN_LEVEL;
7881         }
7882
7883         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7884                                                      spoolss_EnumPrintProcDataTypes, 
7885                                                      *r->out.info, r->in.level,
7886                                                      *r->out.count);
7887         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7888         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7889
7890         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7891 }
7892
7893 /****************************************************************************
7894  fill_monitor_1
7895 ****************************************************************************/
7896
7897 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
7898                              struct spoolss_MonitorInfo1 *r,
7899                              const char *monitor_name)
7900 {
7901         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
7902         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7903
7904         return WERR_OK;
7905 }
7906
7907 /****************************************************************************
7908  fill_monitor_2
7909 ****************************************************************************/
7910
7911 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
7912                              struct spoolss_MonitorInfo2 *r,
7913                              const char *monitor_name,
7914                              const char *environment,
7915                              const char *dll_name)
7916 {
7917         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
7918         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7919         r->environment                  = talloc_strdup(mem_ctx, environment);
7920         W_ERROR_HAVE_NO_MEMORY(r->environment);
7921         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
7922         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
7923
7924         return WERR_OK;
7925 }
7926
7927 /****************************************************************************
7928  enumprintmonitors level 1.
7929 ****************************************************************************/
7930
7931 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
7932                                         union spoolss_MonitorInfo **info_p,
7933                                         uint32_t *count)
7934 {
7935         union spoolss_MonitorInfo *info;
7936         WERROR result = WERR_OK;
7937
7938         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7939         W_ERROR_HAVE_NO_MEMORY(info);
7940
7941         *count = 2;
7942
7943         result = fill_monitor_1(info, &info[0].info1,
7944                                 SPL_LOCAL_PORT);
7945         if (!W_ERROR_IS_OK(result)) {
7946                 goto out;
7947         }
7948
7949         result = fill_monitor_1(info, &info[1].info1,
7950                                 SPL_TCPIP_PORT);
7951         if (!W_ERROR_IS_OK(result)) {
7952                 goto out;
7953         }
7954
7955 out:
7956         if (!W_ERROR_IS_OK(result)) {
7957                 TALLOC_FREE(info);
7958                 *count = 0;
7959                 return result;
7960         }
7961
7962         *info_p = info;
7963
7964         return WERR_OK;
7965 }
7966
7967 /****************************************************************************
7968  enumprintmonitors level 2.
7969 ****************************************************************************/
7970
7971 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
7972                                         union spoolss_MonitorInfo **info_p,
7973                                         uint32_t *count)
7974 {
7975         union spoolss_MonitorInfo *info;
7976         WERROR result = WERR_OK;
7977
7978         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
7979         W_ERROR_HAVE_NO_MEMORY(info);
7980
7981         *count = 2;
7982
7983         result = fill_monitor_2(info, &info[0].info2,
7984                                 SPL_LOCAL_PORT,
7985                                 "Windows NT X86", /* FIXME */
7986                                 "localmon.dll");
7987         if (!W_ERROR_IS_OK(result)) {
7988                 goto out;
7989         }
7990
7991         result = fill_monitor_2(info, &info[1].info2,
7992                                 SPL_TCPIP_PORT,
7993                                 "Windows NT X86", /* FIXME */
7994                                 "tcpmon.dll");
7995         if (!W_ERROR_IS_OK(result)) {
7996                 goto out;
7997         }
7998
7999 out:
8000         if (!W_ERROR_IS_OK(result)) {
8001                 TALLOC_FREE(info);
8002                 *count = 0;
8003                 return result;
8004         }
8005
8006         *info_p = info;
8007
8008         return WERR_OK;
8009 }
8010
8011 /****************************************************************
8012  _spoolss_EnumMonitors
8013 ****************************************************************/
8014
8015 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8016                              struct spoolss_EnumMonitors *r)
8017 {
8018         WERROR result;
8019
8020         /* that's an [in out] buffer */
8021
8022         if (!r->in.buffer && (r->in.offered != 0)) {
8023                 return WERR_INVALID_PARAM;
8024         }
8025
8026         DEBUG(5,("_spoolss_EnumMonitors\n"));
8027
8028         /*
8029          * Enumerate the print monitors ...
8030          *
8031          * Just reply with "Local Port", to keep NT happy
8032          * and I can use my nice printer checker.
8033          */
8034
8035         *r->out.count = 0;
8036         *r->out.needed = 0;
8037         *r->out.info = NULL;
8038
8039         switch (r->in.level) {
8040         case 1:
8041                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8042                                                    r->out.count);
8043                 break;
8044         case 2:
8045                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8046                                                    r->out.count);
8047                 break;
8048         default:
8049                 return WERR_UNKNOWN_LEVEL;
8050         }
8051
8052         if (!W_ERROR_IS_OK(result)) {
8053                 return result;
8054         }
8055
8056         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8057                                                      spoolss_EnumMonitors, 
8058                                                      *r->out.info, r->in.level,
8059                                                      *r->out.count);
8060         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8061         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8062
8063         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8064 }
8065
8066 /****************************************************************************
8067 ****************************************************************************/
8068
8069 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8070                              const print_queue_struct *queue,
8071                              int count, int snum,
8072                              struct spoolss_PrinterInfo2 *pinfo2,
8073                              uint32_t jobid,
8074                              struct spoolss_JobInfo1 *r)
8075 {
8076         int i = 0;
8077         bool found = false;
8078
8079         for (i=0; i<count; i++) {
8080                 if (queue[i].job == (int)jobid) {
8081                         found = true;
8082                         break;
8083                 }
8084         }
8085
8086         if (found == false) {
8087                 /* NT treats not found as bad param... yet another bad choice */
8088                 return WERR_INVALID_PARAM;
8089         }
8090
8091         return fill_job_info1(mem_ctx,
8092                               r,
8093                               &queue[i],
8094                               i,
8095                               snum,
8096                               pinfo2);
8097 }
8098
8099 /****************************************************************************
8100 ****************************************************************************/
8101
8102 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8103                              const print_queue_struct *queue,
8104                              int count, int snum,
8105                              struct spoolss_PrinterInfo2 *pinfo2,
8106                              uint32_t jobid,
8107                              struct spoolss_JobInfo2 *r)
8108 {
8109         int i = 0;
8110         bool found = false;
8111         struct spoolss_DeviceMode *devmode;
8112         WERROR result;
8113
8114         for (i=0; i<count; i++) {
8115                 if (queue[i].job == (int)jobid) {
8116                         found = true;
8117                         break;
8118                 }
8119         }
8120
8121         if (found == false) {
8122                 /* NT treats not found as bad param... yet another bad
8123                    choice */
8124                 return WERR_INVALID_PARAM;
8125         }
8126
8127         /*
8128          * if the print job does not have a DEVMODE associated with it,
8129          * just use the one for the printer. A NULL devicemode is not
8130          *  a failure condition
8131          */
8132
8133         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8134         if (!devmode) {
8135                 result = spoolss_create_default_devmode(mem_ctx,
8136                                                 pinfo2->printername,
8137                                                 &devmode);
8138                 if (!W_ERROR_IS_OK(result)) {
8139                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8140                         return result;
8141                 }
8142         }
8143
8144         return fill_job_info2(mem_ctx,
8145                               r,
8146                               &queue[i],
8147                               i,
8148                               snum,
8149                               pinfo2,
8150                               devmode);
8151 }
8152
8153 /****************************************************************
8154  _spoolss_GetJob
8155 ****************************************************************/
8156
8157 WERROR _spoolss_GetJob(pipes_struct *p,
8158                        struct spoolss_GetJob *r)
8159 {
8160         WERROR result = WERR_OK;
8161         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8162         int snum;
8163         int count;
8164         print_queue_struct      *queue = NULL;
8165         print_status_struct prt_status;
8166
8167         /* that's an [in out] buffer */
8168
8169         if (!r->in.buffer && (r->in.offered != 0)) {
8170                 return WERR_INVALID_PARAM;
8171         }
8172
8173         DEBUG(5,("_spoolss_GetJob\n"));
8174
8175         *r->out.needed = 0;
8176
8177         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8178                 return WERR_BADFID;
8179         }
8180
8181         result = winreg_get_printer(talloc_tos(), p->server_info, NULL,
8182                                     lp_servicename(snum), &pinfo2);
8183         if (!W_ERROR_IS_OK(result)) {
8184                 return result;
8185         }
8186
8187         count = print_queue_status(snum, &queue, &prt_status);
8188
8189         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8190                      count, prt_status.status, prt_status.message));
8191
8192         switch (r->in.level) {
8193         case 1:
8194                 result = getjob_level_1(p->mem_ctx,
8195                                         queue, count, snum, pinfo2,
8196                                         r->in.job_id, &r->out.info->info1);
8197                 break;
8198         case 2:
8199                 result = getjob_level_2(p->mem_ctx,
8200                                         queue, count, snum, pinfo2,
8201                                         r->in.job_id, &r->out.info->info2);
8202                 break;
8203         default:
8204                 result = WERR_UNKNOWN_LEVEL;
8205                 break;
8206         }
8207
8208         SAFE_FREE(queue);
8209         TALLOC_FREE(pinfo2);
8210
8211         if (!W_ERROR_IS_OK(result)) {
8212                 TALLOC_FREE(r->out.info);
8213                 return result;
8214         }
8215
8216         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8217                                                                                    r->in.level);
8218         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8219
8220         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8221 }
8222
8223 /****************************************************************
8224  _spoolss_GetPrinterDataEx
8225 ****************************************************************/
8226
8227 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8228                                  struct spoolss_GetPrinterDataEx *r)
8229 {
8230
8231         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8232         const char *printer;
8233         int                     snum = 0;
8234         WERROR result = WERR_OK;
8235         DATA_BLOB blob;
8236         enum winreg_Type val_type;
8237         uint8_t *val_data;
8238         uint32_t val_size;
8239
8240
8241         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8242
8243         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8244                 r->in.key_name, r->in.value_name));
8245
8246         /* in case of problem, return some default values */
8247
8248         *r->out.needed  = 0;
8249         *r->out.type    = REG_NONE;
8250
8251         if (!Printer) {
8252                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8253                         OUR_HANDLE(r->in.handle)));
8254                 result = WERR_BADFID;
8255                 goto done;
8256         }
8257
8258         /* Is the handle to a printer or to the server? */
8259
8260         if (Printer->printer_type == SPLHND_SERVER) {
8261
8262                 union spoolss_PrinterData data;
8263
8264                 result = getprinterdata_printer_server(p->mem_ctx,
8265                                                        r->in.value_name,
8266                                                        r->out.type,
8267                                                        &data);
8268                 if (!W_ERROR_IS_OK(result)) {
8269                         return result;
8270                 }
8271
8272                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8273                                                   *r->out.type, &data);
8274                 if (!W_ERROR_IS_OK(result)) {
8275                         return result;
8276                 }
8277
8278                 *r->out.needed = blob.length;
8279
8280                 if (r->in.offered >= *r->out.needed) {
8281                         memcpy(r->out.data, blob.data, blob.length);
8282                 }
8283
8284                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8285         }
8286
8287         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8288                 return WERR_BADFID;
8289         }
8290         printer = lp_const_servicename(snum);
8291
8292         /* check to see if the keyname is valid */
8293         if (!strlen(r->in.key_name)) {
8294                 return WERR_INVALID_PARAM;
8295         }
8296
8297         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8298         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8299             strequal(r->in.value_name, "ChangeId")) {
8300                 *r->out.type = REG_DWORD;
8301                 *r->out.needed = 4;
8302                 if (r->in.offered >= *r->out.needed) {
8303                         uint32_t changeid = 0;
8304
8305                         result = winreg_printer_get_changeid(p->mem_ctx,
8306                                                              p->server_info,
8307                                                              printer,
8308                                                              &changeid);
8309                         if (!W_ERROR_IS_OK(result)) {
8310                                 return result;
8311                         }
8312
8313                         SIVAL(r->out.data, 0, changeid);
8314                         result = WERR_OK;
8315                 }
8316                 goto done;
8317         }
8318
8319         result = winreg_get_printer_dataex(p->mem_ctx,
8320                                            p->server_info,
8321                                            printer,
8322                                            r->in.key_name,
8323                                            r->in.value_name,
8324                                            &val_type,
8325                                            &val_data,
8326                                            &val_size);
8327         if (!W_ERROR_IS_OK(result)) {
8328                 return result;
8329         }
8330
8331         *r->out.needed = val_size;
8332         *r->out.type = val_type;
8333
8334         if (r->in.offered >= *r->out.needed) {
8335                 memcpy(r->out.data, val_data, val_size);
8336         }
8337
8338  done:
8339         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8340         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8341
8342         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8343 }
8344
8345 /****************************************************************
8346  _spoolss_SetPrinterDataEx
8347 ****************************************************************/
8348
8349 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8350                                  struct spoolss_SetPrinterDataEx *r)
8351 {
8352         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8353         int                     snum = 0;
8354         WERROR                  result = WERR_OK;
8355         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8356         char                    *oid_string;
8357
8358         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8359
8360         /* From MSDN documentation of SetPrinterDataEx: pass request to
8361            SetPrinterData if key is "PrinterDriverData" */
8362
8363         if (!Printer) {
8364                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8365                         OUR_HANDLE(r->in.handle)));
8366                 return WERR_BADFID;
8367         }
8368
8369         if (Printer->printer_type == SPLHND_SERVER) {
8370                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8371                         "Not implemented for server handles yet\n"));
8372                 return WERR_INVALID_PARAM;
8373         }
8374
8375         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8376                 return WERR_BADFID;
8377         }
8378
8379         /*
8380          * Access check : NT returns "access denied" if you make a
8381          * SetPrinterData call without the necessary privildge.
8382          * we were originally returning OK if nothing changed
8383          * which made Win2k issue **a lot** of SetPrinterData
8384          * when connecting to a printer  --jerry
8385          */
8386
8387         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8388                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8389                         "change denied by handle access permissions\n"));
8390                 return WERR_ACCESS_DENIED;
8391         }
8392
8393         result = winreg_get_printer(Printer, p->server_info,
8394                                     Printer->servername,
8395                                     lp_servicename(snum),
8396                                     &pinfo2);
8397         if (!W_ERROR_IS_OK(result)) {
8398                 return result;
8399         }
8400
8401         /* check for OID in valuename */
8402
8403         oid_string = strchr(r->in.value_name, ',');
8404         if (oid_string) {
8405                 *oid_string = '\0';
8406                 oid_string++;
8407         }
8408
8409         /* save the registry data */
8410
8411         result = winreg_set_printer_dataex(p->mem_ctx,
8412                                            p->server_info,
8413                                            pinfo2->sharename,
8414                                            r->in.key_name,
8415                                            r->in.value_name,
8416                                            r->in.type,
8417                                            r->in.data,
8418                                            r->in.offered);
8419
8420         if (W_ERROR_IS_OK(result)) {
8421                 /* save the OID if one was specified */
8422                 if (oid_string) {
8423                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8424                                 r->in.key_name, SPOOL_OID_KEY);
8425                         if (!str) {
8426                                 result = WERR_NOMEM;
8427                                 goto done;
8428                         }
8429
8430                         /*
8431                          * I'm not checking the status here on purpose.  Don't know
8432                          * if this is right, but I'm returning the status from the
8433                          * previous set_printer_dataex() call.  I have no idea if
8434                          * this is right.    --jerry
8435                          */
8436                         winreg_set_printer_dataex(p->mem_ctx,
8437                                                   p->server_info,
8438                                                   pinfo2->sharename,
8439                                                   str,
8440                                                   r->in.value_name,
8441                                                   REG_SZ,
8442                                                   (uint8_t *) oid_string,
8443                                                   strlen(oid_string) + 1);
8444                 }
8445
8446                 result = winreg_printer_update_changeid(p->mem_ctx,
8447                                                         p->server_info,
8448                                                         lp_const_servicename(snum));
8449
8450         }
8451
8452 done:
8453         talloc_free(pinfo2);
8454         return result;
8455 }
8456
8457 /****************************************************************
8458  _spoolss_DeletePrinterDataEx
8459 ****************************************************************/
8460
8461 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8462                                     struct spoolss_DeletePrinterDataEx *r)
8463 {
8464         const char *printer;
8465         int             snum=0;
8466         WERROR          status = WERR_OK;
8467         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8468
8469         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8470
8471         if (!Printer) {
8472                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8473                         "Invalid handle (%s:%u:%u).\n",
8474                         OUR_HANDLE(r->in.handle)));
8475                 return WERR_BADFID;
8476         }
8477
8478         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8479                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8480                         "printer properties change denied by handle\n"));
8481                 return WERR_ACCESS_DENIED;
8482         }
8483
8484         if (!r->in.value_name || !r->in.key_name) {
8485                 return WERR_NOMEM;
8486         }
8487
8488         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8489                 return WERR_BADFID;
8490         }
8491         printer = lp_const_servicename(snum);
8492
8493         status = winreg_delete_printer_dataex(p->mem_ctx,
8494                                               p->server_info,
8495                                               printer,
8496                                               r->in.key_name,
8497                                               r->in.value_name);
8498         if (W_ERROR_IS_OK(status)) {
8499                 status = winreg_printer_update_changeid(p->mem_ctx,
8500                                                         p->server_info,
8501                                                         printer);
8502         }
8503
8504         return status;
8505 }
8506
8507 /****************************************************************
8508  _spoolss_EnumPrinterKey
8509 ****************************************************************/
8510
8511 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8512                                struct spoolss_EnumPrinterKey *r)
8513 {
8514         uint32_t        num_keys;
8515         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8516         int             snum = 0;
8517         WERROR          result = WERR_BADFILE;
8518         const char **array = NULL;
8519         DATA_BLOB blob;
8520
8521         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8522
8523         if (!Printer) {
8524                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8525                         OUR_HANDLE(r->in.handle)));
8526                 return WERR_BADFID;
8527         }
8528
8529         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8530                 return WERR_BADFID;
8531         }
8532
8533         result = winreg_enum_printer_key(p->mem_ctx,
8534                                          p->server_info,
8535                                          lp_const_servicename(snum),
8536                                          r->in.key_name,
8537                                          &num_keys,
8538                                          &array);
8539         if (!W_ERROR_IS_OK(result)) {
8540                 goto done;
8541         }
8542
8543         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8544                 result = WERR_NOMEM;
8545                 goto done;
8546         }
8547
8548         *r->out._ndr_size = r->in.offered / 2;
8549         *r->out.needed = blob.length;
8550
8551         if (r->in.offered < *r->out.needed) {
8552                 result = WERR_MORE_DATA;
8553         } else {
8554                 result = WERR_OK;
8555                 r->out.key_buffer->string_array = array;
8556         }
8557
8558  done:
8559         if (!W_ERROR_IS_OK(result)) {
8560                 TALLOC_FREE(array);
8561                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8562                         *r->out.needed = 0;
8563                 }
8564         }
8565
8566         return result;
8567 }
8568
8569 /****************************************************************
8570  _spoolss_DeletePrinterKey
8571 ****************************************************************/
8572
8573 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8574                                  struct spoolss_DeletePrinterKey *r)
8575 {
8576         Printer_entry           *Printer = find_printer_index_by_hnd(p, r->in.handle);
8577         int                     snum=0;
8578         WERROR                  status;
8579         const char *printer;
8580
8581         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8582
8583         if (!Printer) {
8584                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8585                         OUR_HANDLE(r->in.handle)));
8586                 return WERR_BADFID;
8587         }
8588
8589         /* if keyname == NULL, return error */
8590         if ( !r->in.key_name )
8591                 return WERR_INVALID_PARAM;
8592
8593         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8594                 return WERR_BADFID;
8595         }
8596
8597         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8598                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8599                         "printer properties change denied by handle\n"));
8600                 return WERR_ACCESS_DENIED;
8601         }
8602
8603         printer = lp_const_servicename(snum);
8604
8605         /* delete the key and all subkeys */
8606         status = winreg_delete_printer_key(p->mem_ctx,
8607                                            p->server_info,
8608                                            printer,
8609                                            r->in.key_name);
8610         if (W_ERROR_IS_OK(status)) {
8611                 status = winreg_printer_update_changeid(p->mem_ctx,
8612                                                         p->server_info,
8613                                                         printer);
8614         }
8615
8616         return status;
8617 }
8618
8619 /****************************************************************
8620  _spoolss_EnumPrinterDataEx
8621 ****************************************************************/
8622
8623 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8624                                   struct spoolss_EnumPrinterDataEx *r)
8625 {
8626         uint32_t        count = 0;
8627         struct spoolss_PrinterEnumValues *info = NULL;
8628         Printer_entry   *Printer = find_printer_index_by_hnd(p, r->in.handle);
8629         int             snum;
8630         WERROR          result;
8631
8632         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8633
8634         *r->out.count = 0;
8635         *r->out.needed = 0;
8636         *r->out.info = NULL;
8637
8638         if (!Printer) {
8639                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8640                         OUR_HANDLE(r->in.handle)));
8641                 return WERR_BADFID;
8642         }
8643
8644         /*
8645          * first check for a keyname of NULL or "".  Win2k seems to send
8646          * this a lot and we should send back WERR_INVALID_PARAM
8647          * no need to spend time looking up the printer in this case.
8648          * --jerry
8649          */
8650
8651         if (!strlen(r->in.key_name)) {
8652                 result = WERR_INVALID_PARAM;
8653                 goto done;
8654         }
8655
8656         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8657                 return WERR_BADFID;
8658         }
8659
8660         /* now look for a match on the key name */
8661         result = winreg_enum_printer_dataex(p->mem_ctx,
8662                                             p->server_info,
8663                                             lp_const_servicename(snum),
8664                                             r->in.key_name,
8665                                             &count,
8666                                             &info);
8667         if (!W_ERROR_IS_OK(result)) {
8668                 goto done;
8669         }
8670
8671 #if 0 /* FIXME - gd */
8672         /* housekeeping information in the reply */
8673
8674         /* Fix from Martin Zielinski <mz@seh.de> - ensure
8675          * the hand marshalled container size is a multiple
8676          * of 4 bytes for RPC alignment.
8677          */
8678
8679         if (needed % 4) {
8680                 needed += 4-(needed % 4);
8681         }
8682 #endif
8683         *r->out.count   = count;
8684         *r->out.info    = info;
8685
8686  done:
8687         if (!W_ERROR_IS_OK(result)) {
8688                 return result;
8689         }
8690
8691         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8692                                                spoolss_EnumPrinterDataEx, 
8693                                                *r->out.info,
8694                                                *r->out.count);
8695         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8696         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8697
8698         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8699 }
8700
8701 /****************************************************************************
8702 ****************************************************************************/
8703
8704 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8705                                                  const char *servername,
8706                                                  const char *environment,
8707                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
8708 {
8709         WERROR werr;
8710         char *path = NULL;
8711
8712         werr = compose_spoolss_server_path(mem_ctx,
8713                                            servername,
8714                                            environment,
8715                                            SPOOLSS_PRTPROCS_PATH,
8716                                            &path);
8717         if (!W_ERROR_IS_OK(werr)) {
8718                 return werr;
8719         }
8720
8721         DEBUG(4,("print processor directory: [%s]\n", path));
8722
8723         r->directory_name = path;
8724
8725         return WERR_OK;
8726 }
8727
8728 /****************************************************************
8729  _spoolss_GetPrintProcessorDirectory
8730 ****************************************************************/
8731
8732 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8733                                            struct spoolss_GetPrintProcessorDirectory *r)
8734 {
8735         WERROR result;
8736
8737         /* that's an [in out] buffer */
8738
8739         if (!r->in.buffer && (r->in.offered != 0)) {
8740                 return WERR_INVALID_PARAM;
8741         }
8742
8743         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8744                 r->in.level));
8745
8746         *r->out.needed = 0;
8747
8748         /* r->in.level is ignored */
8749
8750         /* We always should reply with a local print processor directory so that
8751          * users are not forced to have a [prnproc$] share on the Samba spoolss
8752          * server - Guenther */
8753
8754         result = getprintprocessordirectory_level_1(p->mem_ctx,
8755                                                     NULL, /* r->in.server */
8756                                                     r->in.environment,
8757                                                     &r->out.info->info1);
8758         if (!W_ERROR_IS_OK(result)) {
8759                 TALLOC_FREE(r->out.info);
8760                 return result;
8761         }
8762
8763         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8764                                                                                    r->out.info, r->in.level);
8765         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8766
8767         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8768 }
8769
8770 /*******************************************************************
8771  ********************************************************************/
8772
8773 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8774                                const char *dllname)
8775 {
8776         enum ndr_err_code ndr_err;
8777         struct spoolss_MonitorUi ui;
8778
8779         ui.dll_name = dllname;
8780
8781         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8782                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8783         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8784                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8785         }
8786         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8787 }
8788
8789 /*******************************************************************
8790  Streams the monitor UI DLL name in UNICODE
8791 *******************************************************************/
8792
8793 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8794                                NT_USER_TOKEN *token, DATA_BLOB *in,
8795                                DATA_BLOB *out, uint32_t *needed)
8796 {
8797         const char *dllname = "tcpmonui.dll";
8798
8799         *needed = (strlen(dllname)+1) * 2;
8800
8801         if (out->length < *needed) {
8802                 return WERR_INSUFFICIENT_BUFFER;
8803         }
8804
8805         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8806                 return WERR_NOMEM;
8807         }
8808
8809         return WERR_OK;
8810 }
8811
8812 /*******************************************************************
8813  ********************************************************************/
8814
8815 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
8816                              struct spoolss_PortData1 *port1,
8817                              const DATA_BLOB *buf)
8818 {
8819         enum ndr_err_code ndr_err;
8820         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
8821                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
8822         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8823                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
8824         }
8825         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8826 }
8827
8828 /*******************************************************************
8829  ********************************************************************/
8830
8831 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
8832                              struct spoolss_PortData2 *port2,
8833                              const DATA_BLOB *buf)
8834 {
8835         enum ndr_err_code ndr_err;
8836         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
8837                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
8838         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8839                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
8840         }
8841         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8842 }
8843
8844 /*******************************************************************
8845  Create a new TCP/IP port
8846 *******************************************************************/
8847
8848 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
8849                              NT_USER_TOKEN *token, DATA_BLOB *in,
8850                              DATA_BLOB *out, uint32_t *needed)
8851 {
8852         struct spoolss_PortData1 port1;
8853         struct spoolss_PortData2 port2;
8854         char *device_uri = NULL;
8855         uint32_t version;
8856
8857         const char *portname;
8858         const char *hostaddress;
8859         const char *queue;
8860         uint32_t port_number;
8861         uint32_t protocol;
8862
8863         /* peek for spoolss_PortData version */
8864
8865         if (!in || (in->length < (128 + 4))) {
8866                 return WERR_GENERAL_FAILURE;
8867         }
8868
8869         version = IVAL(in->data, 128);
8870
8871         switch (version) {
8872                 case 1:
8873                         ZERO_STRUCT(port1);
8874
8875                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
8876                                 return WERR_NOMEM;
8877                         }
8878
8879                         portname        = port1.portname;
8880                         hostaddress     = port1.hostaddress;
8881                         queue           = port1.queue;
8882                         protocol        = port1.protocol;
8883                         port_number     = port1.port_number;
8884
8885                         break;
8886                 case 2:
8887                         ZERO_STRUCT(port2);
8888
8889                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
8890                                 return WERR_NOMEM;
8891                         }
8892
8893                         portname        = port2.portname;
8894                         hostaddress     = port2.hostaddress;
8895                         queue           = port2.queue;
8896                         protocol        = port2.protocol;
8897                         port_number     = port2.port_number;
8898
8899                         break;
8900                 default:
8901                         DEBUG(1,("xcvtcp_addport: "
8902                                 "unknown version of port_data: %d\n", version));
8903                         return WERR_UNKNOWN_PORT;
8904         }
8905
8906         /* create the device URI and call the add_port_hook() */
8907
8908         switch (protocol) {
8909         case PROTOCOL_RAWTCP_TYPE:
8910                 device_uri = talloc_asprintf(mem_ctx,
8911                                 "socket://%s:%d/", hostaddress,
8912                                 port_number);
8913                 break;
8914
8915         case PROTOCOL_LPR_TYPE:
8916                 device_uri = talloc_asprintf(mem_ctx,
8917                         "lpr://%s/%s", hostaddress, queue );
8918                 break;
8919
8920         default:
8921                 return WERR_UNKNOWN_PORT;
8922         }
8923
8924         if (!device_uri) {
8925                 return WERR_NOMEM;
8926         }
8927
8928         return add_port_hook(mem_ctx, token, portname, device_uri);
8929 }
8930
8931 /*******************************************************************
8932 *******************************************************************/
8933
8934 struct xcv_api_table xcvtcp_cmds[] = {
8935         { "MonitorUI",  xcvtcp_monitorui },
8936         { "AddPort",    xcvtcp_addport},
8937         { NULL,         NULL }
8938 };
8939
8940 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
8941                                      NT_USER_TOKEN *token, const char *command,
8942                                      DATA_BLOB *inbuf,
8943                                      DATA_BLOB *outbuf,
8944                                      uint32_t *needed )
8945 {
8946         int i;
8947
8948         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
8949
8950         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
8951                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
8952                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
8953         }
8954
8955         return WERR_BADFUNC;
8956 }
8957
8958 /*******************************************************************
8959 *******************************************************************/
8960 #if 0   /* don't support management using the "Local Port" monitor */
8961
8962 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
8963                                  NT_USER_TOKEN *token, DATA_BLOB *in,
8964                                  DATA_BLOB *out, uint32_t *needed)
8965 {
8966         const char *dllname = "localui.dll";
8967
8968         *needed = (strlen(dllname)+1) * 2;
8969
8970         if (out->length < *needed) {
8971                 return WERR_INSUFFICIENT_BUFFER;
8972         }
8973
8974         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8975                 return WERR_NOMEM;
8976         }
8977
8978         return WERR_OK;
8979 }
8980
8981 /*******************************************************************
8982 *******************************************************************/
8983
8984 struct xcv_api_table xcvlocal_cmds[] = {
8985         { "MonitorUI",  xcvlocal_monitorui },
8986         { NULL,         NULL }
8987 };
8988 #else
8989 struct xcv_api_table xcvlocal_cmds[] = {
8990         { NULL,         NULL }
8991 };
8992 #endif
8993
8994
8995
8996 /*******************************************************************
8997 *******************************************************************/
8998
8999 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9000                                        NT_USER_TOKEN *token, const char *command,
9001                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9002                                        uint32_t *needed)
9003 {
9004         int i;
9005
9006         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9007
9008         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9009                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9010                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9011         }
9012         return WERR_BADFUNC;
9013 }
9014
9015 /****************************************************************
9016  _spoolss_XcvData
9017 ****************************************************************/
9018
9019 WERROR _spoolss_XcvData(pipes_struct *p,
9020                         struct spoolss_XcvData *r)
9021 {
9022         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9023         DATA_BLOB out_data = data_blob_null;
9024         WERROR werror;
9025
9026         if (!Printer) {
9027                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9028                         OUR_HANDLE(r->in.handle)));
9029                 return WERR_BADFID;
9030         }
9031
9032         /* Has to be a handle to the TCP/IP port monitor */
9033
9034         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9035                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9036                 return WERR_BADFID;
9037         }
9038
9039         /* requires administrative access to the server */
9040
9041         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9042                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9043                 return WERR_ACCESS_DENIED;
9044         }
9045
9046         /* Allocate the outgoing buffer */
9047
9048         if (r->in.out_data_size) {
9049                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9050                 if (out_data.data == NULL) {
9051                         return WERR_NOMEM;
9052                 }
9053         }
9054
9055         switch ( Printer->printer_type ) {
9056         case SPLHND_PORTMON_TCP:
9057                 werror = process_xcvtcp_command(p->mem_ctx,
9058                                                 p->server_info->ptok,
9059                                                 r->in.function_name,
9060                                                 &r->in.in_data, &out_data,
9061                                                 r->out.needed);
9062                 break;
9063         case SPLHND_PORTMON_LOCAL:
9064                 werror = process_xcvlocal_command(p->mem_ctx,
9065                                                   p->server_info->ptok,
9066                                                   r->in.function_name,
9067                                                   &r->in.in_data, &out_data,
9068                                                   r->out.needed);
9069                 break;
9070         default:
9071                 werror = WERR_INVALID_PRINT_MONITOR;
9072         }
9073
9074         if (!W_ERROR_IS_OK(werror)) {
9075                 return werror;
9076         }
9077
9078         *r->out.status_code = 0;
9079
9080         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9081                 memcpy(r->out.out_data, out_data.data,
9082                         MIN(r->in.out_data_size, out_data.length));
9083         }
9084
9085         return WERR_OK;
9086 }
9087
9088 /****************************************************************
9089  _spoolss_AddPrintProcessor
9090 ****************************************************************/
9091
9092 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9093                                   struct spoolss_AddPrintProcessor *r)
9094 {
9095         /* for now, just indicate success and ignore the add.  We'll
9096            automatically set the winprint processor for printer
9097            entries later.  Used to debug the LexMark Optra S 1855 PCL
9098            driver --jerry */
9099
9100         return WERR_OK;
9101 }
9102
9103 /****************************************************************
9104  _spoolss_AddPort
9105 ****************************************************************/
9106
9107 WERROR _spoolss_AddPort(pipes_struct *p,
9108                         struct spoolss_AddPort *r)
9109 {
9110         /* do what w2k3 does */
9111
9112         return WERR_NOT_SUPPORTED;
9113 }
9114
9115 /****************************************************************
9116  _spoolss_GetPrinterDriver
9117 ****************************************************************/
9118
9119 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9120                                  struct spoolss_GetPrinterDriver *r)
9121 {
9122         p->rng_fault_state = true;
9123         return WERR_NOT_SUPPORTED;
9124 }
9125
9126 /****************************************************************
9127  _spoolss_ReadPrinter
9128 ****************************************************************/
9129
9130 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9131                             struct spoolss_ReadPrinter *r)
9132 {
9133         p->rng_fault_state = true;
9134         return WERR_NOT_SUPPORTED;
9135 }
9136
9137 /****************************************************************
9138  _spoolss_WaitForPrinterChange
9139 ****************************************************************/
9140
9141 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9142                                      struct spoolss_WaitForPrinterChange *r)
9143 {
9144         p->rng_fault_state = true;
9145         return WERR_NOT_SUPPORTED;
9146 }
9147
9148 /****************************************************************
9149  _spoolss_ConfigurePort
9150 ****************************************************************/
9151
9152 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9153                               struct spoolss_ConfigurePort *r)
9154 {
9155         p->rng_fault_state = true;
9156         return WERR_NOT_SUPPORTED;
9157 }
9158
9159 /****************************************************************
9160  _spoolss_DeletePort
9161 ****************************************************************/
9162
9163 WERROR _spoolss_DeletePort(pipes_struct *p,
9164                            struct spoolss_DeletePort *r)
9165 {
9166         p->rng_fault_state = true;
9167         return WERR_NOT_SUPPORTED;
9168 }
9169
9170 /****************************************************************
9171  _spoolss_CreatePrinterIC
9172 ****************************************************************/
9173
9174 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9175                                 struct spoolss_CreatePrinterIC *r)
9176 {
9177         p->rng_fault_state = true;
9178         return WERR_NOT_SUPPORTED;
9179 }
9180
9181 /****************************************************************
9182  _spoolss_PlayGDIScriptOnPrinterIC
9183 ****************************************************************/
9184
9185 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9186                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9187 {
9188         p->rng_fault_state = true;
9189         return WERR_NOT_SUPPORTED;
9190 }
9191
9192 /****************************************************************
9193  _spoolss_DeletePrinterIC
9194 ****************************************************************/
9195
9196 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9197                                 struct spoolss_DeletePrinterIC *r)
9198 {
9199         p->rng_fault_state = true;
9200         return WERR_NOT_SUPPORTED;
9201 }
9202
9203 /****************************************************************
9204  _spoolss_AddPrinterConnection
9205 ****************************************************************/
9206
9207 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9208                                      struct spoolss_AddPrinterConnection *r)
9209 {
9210         p->rng_fault_state = true;
9211         return WERR_NOT_SUPPORTED;
9212 }
9213
9214 /****************************************************************
9215  _spoolss_DeletePrinterConnection
9216 ****************************************************************/
9217
9218 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9219                                         struct spoolss_DeletePrinterConnection *r)
9220 {
9221         p->rng_fault_state = true;
9222         return WERR_NOT_SUPPORTED;
9223 }
9224
9225 /****************************************************************
9226  _spoolss_PrinterMessageBox
9227 ****************************************************************/
9228
9229 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9230                                   struct spoolss_PrinterMessageBox *r)
9231 {
9232         p->rng_fault_state = true;
9233         return WERR_NOT_SUPPORTED;
9234 }
9235
9236 /****************************************************************
9237  _spoolss_AddMonitor
9238 ****************************************************************/
9239
9240 WERROR _spoolss_AddMonitor(pipes_struct *p,
9241                            struct spoolss_AddMonitor *r)
9242 {
9243         p->rng_fault_state = true;
9244         return WERR_NOT_SUPPORTED;
9245 }
9246
9247 /****************************************************************
9248  _spoolss_DeleteMonitor
9249 ****************************************************************/
9250
9251 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9252                               struct spoolss_DeleteMonitor *r)
9253 {
9254         p->rng_fault_state = true;
9255         return WERR_NOT_SUPPORTED;
9256 }
9257
9258 /****************************************************************
9259  _spoolss_DeletePrintProcessor
9260 ****************************************************************/
9261
9262 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9263                                      struct spoolss_DeletePrintProcessor *r)
9264 {
9265         p->rng_fault_state = true;
9266         return WERR_NOT_SUPPORTED;
9267 }
9268
9269 /****************************************************************
9270  _spoolss_AddPrintProvidor
9271 ****************************************************************/
9272
9273 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9274                                  struct spoolss_AddPrintProvidor *r)
9275 {
9276         p->rng_fault_state = true;
9277         return WERR_NOT_SUPPORTED;
9278 }
9279
9280 /****************************************************************
9281  _spoolss_DeletePrintProvidor
9282 ****************************************************************/
9283
9284 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9285                                     struct spoolss_DeletePrintProvidor *r)
9286 {
9287         p->rng_fault_state = true;
9288         return WERR_NOT_SUPPORTED;
9289 }
9290
9291 /****************************************************************
9292  _spoolss_FindFirstPrinterChangeNotification
9293 ****************************************************************/
9294
9295 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9296                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
9297 {
9298         p->rng_fault_state = true;
9299         return WERR_NOT_SUPPORTED;
9300 }
9301
9302 /****************************************************************
9303  _spoolss_FindNextPrinterChangeNotification
9304 ****************************************************************/
9305
9306 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9307                                                   struct spoolss_FindNextPrinterChangeNotification *r)
9308 {
9309         p->rng_fault_state = true;
9310         return WERR_NOT_SUPPORTED;
9311 }
9312
9313 /****************************************************************
9314  _spoolss_RouterFindFirstPrinterChangeNotificationOld
9315 ****************************************************************/
9316
9317 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9318                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9319 {
9320         p->rng_fault_state = true;
9321         return WERR_NOT_SUPPORTED;
9322 }
9323
9324 /****************************************************************
9325  _spoolss_ReplyOpenPrinter
9326 ****************************************************************/
9327
9328 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9329                                  struct spoolss_ReplyOpenPrinter *r)
9330 {
9331         p->rng_fault_state = true;
9332         return WERR_NOT_SUPPORTED;
9333 }
9334
9335 /****************************************************************
9336  _spoolss_RouterReplyPrinter
9337 ****************************************************************/
9338
9339 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9340                                    struct spoolss_RouterReplyPrinter *r)
9341 {
9342         p->rng_fault_state = true;
9343         return WERR_NOT_SUPPORTED;
9344 }
9345
9346 /****************************************************************
9347  _spoolss_ReplyClosePrinter
9348 ****************************************************************/
9349
9350 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9351                                   struct spoolss_ReplyClosePrinter *r)
9352 {
9353         p->rng_fault_state = true;
9354         return WERR_NOT_SUPPORTED;
9355 }
9356
9357 /****************************************************************
9358  _spoolss_AddPortEx
9359 ****************************************************************/
9360
9361 WERROR _spoolss_AddPortEx(pipes_struct *p,
9362                           struct spoolss_AddPortEx *r)
9363 {
9364         p->rng_fault_state = true;
9365         return WERR_NOT_SUPPORTED;
9366 }
9367
9368 /****************************************************************
9369  _spoolss_RouterFindFirstPrinterChangeNotification
9370 ****************************************************************/
9371
9372 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9373                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9374 {
9375         p->rng_fault_state = true;
9376         return WERR_NOT_SUPPORTED;
9377 }
9378
9379 /****************************************************************
9380  _spoolss_SpoolerInit
9381 ****************************************************************/
9382
9383 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9384                             struct spoolss_SpoolerInit *r)
9385 {
9386         p->rng_fault_state = true;
9387         return WERR_NOT_SUPPORTED;
9388 }
9389
9390 /****************************************************************
9391  _spoolss_ResetPrinterEx
9392 ****************************************************************/
9393
9394 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9395                                struct spoolss_ResetPrinterEx *r)
9396 {
9397         p->rng_fault_state = true;
9398         return WERR_NOT_SUPPORTED;
9399 }
9400
9401 /****************************************************************
9402  _spoolss_RouterReplyPrinterEx
9403 ****************************************************************/
9404
9405 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9406                                      struct spoolss_RouterReplyPrinterEx *r)
9407 {
9408         p->rng_fault_state = true;
9409         return WERR_NOT_SUPPORTED;
9410 }
9411
9412 /****************************************************************
9413  _spoolss_44
9414 ****************************************************************/
9415
9416 WERROR _spoolss_44(pipes_struct *p,
9417                    struct spoolss_44 *r)
9418 {
9419         p->rng_fault_state = true;
9420         return WERR_NOT_SUPPORTED;
9421 }
9422
9423 /****************************************************************
9424  _spoolss_47
9425 ****************************************************************/
9426
9427 WERROR _spoolss_47(pipes_struct *p,
9428                    struct spoolss_47 *r)
9429 {
9430         p->rng_fault_state = true;
9431         return WERR_NOT_SUPPORTED;
9432 }
9433
9434 /****************************************************************
9435  _spoolss_4a
9436 ****************************************************************/
9437
9438 WERROR _spoolss_4a(pipes_struct *p,
9439                    struct spoolss_4a *r)
9440 {
9441         p->rng_fault_state = true;
9442         return WERR_NOT_SUPPORTED;
9443 }
9444
9445 /****************************************************************
9446  _spoolss_4b
9447 ****************************************************************/
9448
9449 WERROR _spoolss_4b(pipes_struct *p,
9450                    struct spoolss_4b *r)
9451 {
9452         p->rng_fault_state = true;
9453         return WERR_NOT_SUPPORTED;
9454 }
9455
9456 /****************************************************************
9457  _spoolss_4c
9458 ****************************************************************/
9459
9460 WERROR _spoolss_4c(pipes_struct *p,
9461                    struct spoolss_4c *r)
9462 {
9463         p->rng_fault_state = true;
9464         return WERR_NOT_SUPPORTED;
9465 }
9466
9467 /****************************************************************
9468  _spoolss_53
9469 ****************************************************************/
9470
9471 WERROR _spoolss_53(pipes_struct *p,
9472                    struct spoolss_53 *r)
9473 {
9474         p->rng_fault_state = true;
9475         return WERR_NOT_SUPPORTED;
9476 }
9477
9478 /****************************************************************
9479  _spoolss_55
9480 ****************************************************************/
9481
9482 WERROR _spoolss_55(pipes_struct *p,
9483                    struct spoolss_55 *r)
9484 {
9485         p->rng_fault_state = true;
9486         return WERR_NOT_SUPPORTED;
9487 }
9488
9489 /****************************************************************
9490  _spoolss_56
9491 ****************************************************************/
9492
9493 WERROR _spoolss_56(pipes_struct *p,
9494                    struct spoolss_56 *r)
9495 {
9496         p->rng_fault_state = true;
9497         return WERR_NOT_SUPPORTED;
9498 }
9499
9500 /****************************************************************
9501  _spoolss_57
9502 ****************************************************************/
9503
9504 WERROR _spoolss_57(pipes_struct *p,
9505                    struct spoolss_57 *r)
9506 {
9507         p->rng_fault_state = true;
9508         return WERR_NOT_SUPPORTED;
9509 }
9510
9511 /****************************************************************
9512  _spoolss_5a
9513 ****************************************************************/
9514
9515 WERROR _spoolss_5a(pipes_struct *p,
9516                    struct spoolss_5a *r)
9517 {
9518         p->rng_fault_state = true;
9519         return WERR_NOT_SUPPORTED;
9520 }
9521
9522 /****************************************************************
9523  _spoolss_5b
9524 ****************************************************************/
9525
9526 WERROR _spoolss_5b(pipes_struct *p,
9527                    struct spoolss_5b *r)
9528 {
9529         p->rng_fault_state = true;
9530         return WERR_NOT_SUPPORTED;
9531 }
9532
9533 /****************************************************************
9534  _spoolss_5c
9535 ****************************************************************/
9536
9537 WERROR _spoolss_5c(pipes_struct *p,
9538                    struct spoolss_5c *r)
9539 {
9540         p->rng_fault_state = true;
9541         return WERR_NOT_SUPPORTED;
9542 }
9543
9544 /****************************************************************
9545  _spoolss_5d
9546 ****************************************************************/
9547
9548 WERROR _spoolss_5d(pipes_struct *p,
9549                    struct spoolss_5d *r)
9550 {
9551         p->rng_fault_state = true;
9552         return WERR_NOT_SUPPORTED;
9553 }
9554
9555 /****************************************************************
9556  _spoolss_5e
9557 ****************************************************************/
9558
9559 WERROR _spoolss_5e(pipes_struct *p,
9560                    struct spoolss_5e *r)
9561 {
9562         p->rng_fault_state = true;
9563         return WERR_NOT_SUPPORTED;
9564 }
9565
9566 /****************************************************************
9567  _spoolss_5f
9568 ****************************************************************/
9569
9570 WERROR _spoolss_5f(pipes_struct *p,
9571                    struct spoolss_5f *r)
9572 {
9573         p->rng_fault_state = true;
9574         return WERR_NOT_SUPPORTED;
9575 }
9576
9577 /****************************************************************
9578  _spoolss_60
9579 ****************************************************************/
9580
9581 WERROR _spoolss_60(pipes_struct *p,
9582                    struct spoolss_60 *r)
9583 {
9584         p->rng_fault_state = true;
9585         return WERR_NOT_SUPPORTED;
9586 }
9587
9588 /****************************************************************
9589  _spoolss_61
9590 ****************************************************************/
9591
9592 WERROR _spoolss_61(pipes_struct *p,
9593                    struct spoolss_61 *r)
9594 {
9595         p->rng_fault_state = true;
9596         return WERR_NOT_SUPPORTED;
9597 }
9598
9599 /****************************************************************
9600  _spoolss_62
9601 ****************************************************************/
9602
9603 WERROR _spoolss_62(pipes_struct *p,
9604                    struct spoolss_62 *r)
9605 {
9606         p->rng_fault_state = true;
9607         return WERR_NOT_SUPPORTED;
9608 }
9609
9610 /****************************************************************
9611  _spoolss_63
9612 ****************************************************************/
9613
9614 WERROR _spoolss_63(pipes_struct *p,
9615                    struct spoolss_63 *r)
9616 {
9617         p->rng_fault_state = true;
9618         return WERR_NOT_SUPPORTED;
9619 }
9620
9621 /****************************************************************
9622  _spoolss_64
9623 ****************************************************************/
9624
9625 WERROR _spoolss_64(pipes_struct *p,
9626                    struct spoolss_64 *r)
9627 {
9628         p->rng_fault_state = true;
9629         return WERR_NOT_SUPPORTED;
9630 }
9631
9632 /****************************************************************
9633  _spoolss_65
9634 ****************************************************************/
9635
9636 WERROR _spoolss_65(pipes_struct *p,
9637                    struct spoolss_65 *r)
9638 {
9639         p->rng_fault_state = true;
9640         return WERR_NOT_SUPPORTED;
9641 }
9642
9643 /****************************************************************
9644  _spoolss_GetCorePrinterDrivers
9645 ****************************************************************/
9646
9647 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9648                                       struct spoolss_GetCorePrinterDrivers *r)
9649 {
9650         p->rng_fault_state = true;
9651         return WERR_NOT_SUPPORTED;
9652 }
9653
9654 /****************************************************************
9655  _spoolss_67
9656 ****************************************************************/
9657
9658 WERROR _spoolss_67(pipes_struct *p,
9659                    struct spoolss_67 *r)
9660 {
9661         p->rng_fault_state = true;
9662         return WERR_NOT_SUPPORTED;
9663 }
9664
9665 /****************************************************************
9666  _spoolss_GetPrinterDriverPackagePath
9667 ****************************************************************/
9668
9669 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9670                                             struct spoolss_GetPrinterDriverPackagePath *r)
9671 {
9672         p->rng_fault_state = true;
9673         return WERR_NOT_SUPPORTED;
9674 }
9675
9676 /****************************************************************
9677  _spoolss_69
9678 ****************************************************************/
9679
9680 WERROR _spoolss_69(pipes_struct *p,
9681                    struct spoolss_69 *r)
9682 {
9683         p->rng_fault_state = true;
9684         return WERR_NOT_SUPPORTED;
9685 }
9686
9687 /****************************************************************
9688  _spoolss_6a
9689 ****************************************************************/
9690
9691 WERROR _spoolss_6a(pipes_struct *p,
9692                    struct spoolss_6a *r)
9693 {
9694         p->rng_fault_state = true;
9695         return WERR_NOT_SUPPORTED;
9696 }
9697
9698 /****************************************************************
9699  _spoolss_6b
9700 ****************************************************************/
9701
9702 WERROR _spoolss_6b(pipes_struct *p,
9703                    struct spoolss_6b *r)
9704 {
9705         p->rng_fault_state = true;
9706         return WERR_NOT_SUPPORTED;
9707 }
9708
9709 /****************************************************************
9710  _spoolss_6c
9711 ****************************************************************/
9712
9713 WERROR _spoolss_6c(pipes_struct *p,
9714                    struct spoolss_6c *r)
9715 {
9716         p->rng_fault_state = true;
9717         return WERR_NOT_SUPPORTED;
9718 }
9719
9720 /****************************************************************
9721  _spoolss_6d
9722 ****************************************************************/
9723
9724 WERROR _spoolss_6d(pipes_struct *p,
9725                    struct spoolss_6d *r)
9726 {
9727         p->rng_fault_state = true;
9728         return WERR_NOT_SUPPORTED;
9729 }