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