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