s3-spoolss: use struct spoolss_NotifyInfo instead of SPOOL_NOTIFY_INFO.
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *
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 extern userdom_struct current_user_info;
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
34
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
38
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41
42 struct table_node {
43         const char    *long_archi;
44         const char    *short_archi;
45         int     version;
46 };
47
48 static Printer_entry *printers_list;
49
50 typedef struct _counter_printer_0 {
51         struct _counter_printer_0 *next;
52         struct _counter_printer_0 *prev;
53
54         int snum;
55         uint32 counter;
56 } counter_printer_0;
57
58 static counter_printer_0 *counter_list;
59
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
62
63
64 /* in printing/nt_printing.c */
65
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
67
68 /* API table for Xcv Monitor functions */
69
70 struct xcv_api_table {
71         const char *name;
72         WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
73 };
74
75 /********************************************************************
76  * Canonicalize servername.
77  ********************************************************************/
78
79 static const char *canon_servername(const char *servername)
80 {
81         const char *pservername = servername;
82         while (*pservername == '\\') {
83                 pservername++;
84         }
85         return pservername;
86 }
87
88 /* translate between internal status numbers and NT status numbers */
89 static int nt_printj_status(int v)
90 {
91         switch (v) {
92         case LPQ_QUEUED:
93                 return 0;
94         case LPQ_PAUSED:
95                 return JOB_STATUS_PAUSED;
96         case LPQ_SPOOLING:
97                 return JOB_STATUS_SPOOLING;
98         case LPQ_PRINTING:
99                 return JOB_STATUS_PRINTING;
100         case LPQ_ERROR:
101                 return JOB_STATUS_ERROR;
102         case LPQ_DELETING:
103                 return JOB_STATUS_DELETING;
104         case LPQ_OFFLINE:
105                 return JOB_STATUS_OFFLINE;
106         case LPQ_PAPEROUT:
107                 return JOB_STATUS_PAPEROUT;
108         case LPQ_PRINTED:
109                 return JOB_STATUS_PRINTED;
110         case LPQ_DELETED:
111                 return JOB_STATUS_DELETED;
112         case LPQ_BLOCKED:
113                 return JOB_STATUS_BLOCKED;
114         case LPQ_USER_INTERVENTION:
115                 return JOB_STATUS_USER_INTERVENTION;
116         }
117         return 0;
118 }
119
120 static int nt_printq_status(int v)
121 {
122         switch (v) {
123         case LPQ_PAUSED:
124                 return PRINTER_STATUS_PAUSED;
125         case LPQ_QUEUED:
126         case LPQ_SPOOLING:
127         case LPQ_PRINTING:
128                 return 0;
129         }
130         return 0;
131 }
132
133 /****************************************************************************
134  Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
135 ****************************************************************************/
136
137 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
138 {
139         if (*pp == NULL)
140                 return;
141
142         SAFE_FREE((*pp)->ctr.type);
143         SAFE_FREE(*pp);
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         free_spool_notify_option(&Printer->notify.option);
219         Printer->notify.option=NULL;
220         Printer->notify.client_connected=False;
221
222         free_nt_devicemode( &Printer->nt_devmode );
223         free_a_printer( &Printer->printer_info, 2 );
224
225         /* Remove from the internal list. */
226         DLIST_REMOVE(printers_list, Printer);
227         return 0;
228 }
229
230 /****************************************************************************
231  Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
233
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
235 {
236         SPOOL_NOTIFY_OPTION *new_sp = NULL;
237
238         if (!sp)
239                 return NULL;
240
241         new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
242         if (!new_sp)
243                 return NULL;
244
245         *new_sp = *sp;
246
247         if (sp->ctr.count) {
248                 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
249
250                 if (!new_sp->ctr.type) {
251                         SAFE_FREE(new_sp);
252                         return NULL;
253                 }
254         }
255
256         return new_sp;
257 }
258
259 /****************************************************************************
260   find printer index by handle
261 ****************************************************************************/
262
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
264 {
265         Printer_entry *find_printer = NULL;
266
267         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
268                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
269                 return NULL;
270         }
271
272         return find_printer;
273 }
274
275 /****************************************************************************
276  Close printer index by handle.
277 ****************************************************************************/
278
279 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
280 {
281         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
282
283         if (!Printer) {
284                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
285                 return False;
286         }
287
288         close_policy_hnd(p, hnd);
289
290         return True;
291 }
292
293 /****************************************************************************
294  Delete a printer given a handle.
295 ****************************************************************************/
296
297 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
298 {
299         char *cmd = lp_deleteprinter_cmd();
300         char *command = NULL;
301         int ret;
302         SE_PRIV se_printop = SE_PRINT_OPERATOR;
303         bool is_print_op = False;
304
305         /* can't fail if we don't try */
306
307         if ( !*cmd )
308                 return WERR_OK;
309
310         command = talloc_asprintf(ctx,
311                         "%s \"%s\"",
312                         cmd, sharename);
313         if (!command) {
314                 return WERR_NOMEM;
315         }
316         if ( token )
317                 is_print_op = user_has_privileges( token, &se_printop );
318
319         DEBUG(10,("Running [%s]\n", command));
320
321         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
322
323         if ( is_print_op )
324                 become_root();
325
326         if ( (ret = smbrun(command, NULL)) == 0 ) {
327                 /* Tell everyone we updated smb.conf. */
328                 message_send_all(smbd_messaging_context(),
329                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
330         }
331
332         if ( is_print_op )
333                 unbecome_root();
334
335         /********** END SePrintOperatorPrivlege BLOCK **********/
336
337         DEBUGADD(10,("returned [%d]\n", ret));
338
339         TALLOC_FREE(command);
340
341         if (ret != 0)
342                 return WERR_BADFID; /* What to return here? */
343
344         /* go ahead and re-read the services immediately */
345         reload_services( False );
346
347         if ( lp_servicenumber( sharename )  < 0 )
348                 return WERR_ACCESS_DENIED;
349
350         return WERR_OK;
351 }
352
353 /****************************************************************************
354  Delete a printer given a handle.
355 ****************************************************************************/
356
357 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
358 {
359         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
360
361         if (!Printer) {
362                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
363                 return WERR_BADFID;
364         }
365
366         /*
367          * It turns out that Windows allows delete printer on a handle
368          * opened by an admin user, then used on a pipe handle created
369          * by an anonymous user..... but they're working on security.... riiight !
370          * JRA.
371          */
372
373         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
374                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
375                 return WERR_ACCESS_DENIED;
376         }
377
378         /* this does not need a become root since the access check has been
379            done on the handle already */
380
381         if (del_a_printer( Printer->sharename ) != 0) {
382                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
383                 return WERR_BADFID;
384         }
385
386         return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
387                                    Printer->sharename );
388 }
389
390 /****************************************************************************
391  Return the snum of a printer corresponding to an handle.
392 ****************************************************************************/
393
394 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
395                              struct share_params **params)
396 {
397         Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
398
399         if (!Printer) {
400                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
401                 return False;
402         }
403
404         switch (Printer->printer_type) {
405                 case SPLHND_PRINTER:
406                         DEBUG(4,("short name:%s\n", Printer->sharename));
407                         *number = print_queue_snum(Printer->sharename);
408                         return (*number != -1);
409                 case SPLHND_SERVER:
410                         return False;
411                 default:
412                         return False;
413         }
414 }
415
416 /****************************************************************************
417  Set printer handle type.
418  Check if it's \\server or \\server\printer
419 ****************************************************************************/
420
421 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
422 {
423         DEBUG(3,("Setting printer type=%s\n", handlename));
424
425         if ( strlen(handlename) < 3 ) {
426                 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
427                 return False;
428         }
429
430         /* it's a print server */
431         if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
432                 DEBUGADD(4,("Printer is a print server\n"));
433                 Printer->printer_type = SPLHND_SERVER;
434         }
435         /* it's a printer (set_printer_hnd_name() will handle port monitors */
436         else {
437                 DEBUGADD(4,("Printer is a printer\n"));
438                 Printer->printer_type = SPLHND_PRINTER;
439         }
440
441         return True;
442 }
443
444 /****************************************************************************
445  Set printer handle name..  Accept names like \\server, \\server\printer,
446  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
447  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
448  XcvDataPort() interface.
449 ****************************************************************************/
450
451 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
452 {
453         int snum;
454         int n_services=lp_numservices();
455         char *aprinter, *printername;
456         const char *servername;
457         fstring sname;
458         bool found=False;
459         NT_PRINTER_INFO_LEVEL *printer = NULL;
460         WERROR result;
461
462         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
463
464         aprinter = handlename;
465         if ( *handlename == '\\' ) {
466                 servername = canon_servername(handlename);
467                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
468                         *aprinter = '\0';
469                         aprinter++;
470                 }
471         } else {
472                 servername = "";
473         }
474
475         /* save the servername to fill in replies on this handle */
476
477         if ( !is_myname_or_ipaddr( servername ) )
478                 return False;
479
480         fstrcpy( Printer->servername, servername );
481
482         if ( Printer->printer_type == SPLHND_SERVER )
483                 return True;
484
485         if ( Printer->printer_type != SPLHND_PRINTER )
486                 return False;
487
488         DEBUGADD(5, ("searching for [%s]\n", aprinter ));
489
490         /* check for the Port Monitor Interface */
491
492         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
493                 Printer->printer_type = SPLHND_PORTMON_TCP;
494                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
495                 found = True;
496         }
497         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
498                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
499                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
500                 found = True;
501         }
502
503         /* Search all sharenames first as this is easier than pulling
504            the printer_info_2 off of disk. Don't use find_service() since
505            that calls out to map_username() */
506
507         /* do another loop to look for printernames */
508
509         for (snum=0; !found && snum<n_services; snum++) {
510
511                 /* no point going on if this is not a printer */
512
513                 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
514                         continue;
515
516                 fstrcpy(sname, lp_servicename(snum));
517                 if ( strequal( aprinter, sname ) ) {
518                         found = True;
519                         break;
520                 }
521
522                 /* no point looking up the printer object if
523                    we aren't allowing printername != sharename */
524
525                 if ( lp_force_printername(snum) )
526                         continue;
527
528                 fstrcpy(sname, lp_servicename(snum));
529
530                 printer = NULL;
531
532                 /* This call doesn't fill in the location or comment from
533                  * a CUPS server for efficiency with large numbers of printers.
534                  * JRA.
535                  */
536
537                 result = get_a_printer_search( NULL, &printer, 2, sname );
538                 if ( !W_ERROR_IS_OK(result) ) {
539                         DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
540                                 sname, win_errstr(result)));
541                         continue;
542                 }
543
544                 /* printername is always returned as \\server\printername */
545                 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
546                         DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
547                                 printer->info_2->printername));
548                         free_a_printer( &printer, 2);
549                         continue;
550                 }
551
552                 printername++;
553
554                 if ( strequal(printername, aprinter) ) {
555                         free_a_printer( &printer, 2);
556                         found = True;
557                         break;
558                 }
559
560                 DEBUGADD(10, ("printername: %s\n", printername));
561
562                 free_a_printer( &printer, 2);
563         }
564
565         free_a_printer( &printer, 2);
566
567         if ( !found ) {
568                 DEBUGADD(4,("Printer not found\n"));
569                 return False;
570         }
571
572         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
573
574         fstrcpy(Printer->sharename, sname);
575
576         return True;
577 }
578
579 /****************************************************************************
580  Find first available printer slot. creates a printer handle for you.
581  ****************************************************************************/
582
583 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
584 {
585         Printer_entry *new_printer;
586
587         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
588
589         new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
590         if (new_printer == NULL) {
591                 return false;
592         }
593         talloc_set_destructor(new_printer, printer_entry_destructor);
594
595         if (!create_policy_hnd(p, hnd, new_printer)) {
596                 TALLOC_FREE(new_printer);
597                 return False;
598         }
599
600         /* Add to the internal list. */
601         DLIST_ADD(printers_list, new_printer);
602
603         new_printer->notify.option=NULL;
604
605         if (!set_printer_hnd_printertype(new_printer, name)) {
606                 close_printer_handle(p, hnd);
607                 return False;
608         }
609
610         if (!set_printer_hnd_name(new_printer, name)) {
611                 close_printer_handle(p, hnd);
612                 return False;
613         }
614
615         new_printer->access_granted = access_granted;
616
617         DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
618
619         return True;
620 }
621
622 /***************************************************************************
623  check to see if the client motify handle is monitoring the notification
624  given by (notify_type, notify_field).
625  **************************************************************************/
626
627 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
628                                       uint16 notify_field)
629 {
630         return True;
631 }
632
633 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
634                                 uint16 notify_field)
635 {
636         SPOOL_NOTIFY_OPTION *option = p->notify.option;
637         uint32 i, j;
638
639         /*
640          * Flags should always be zero when the change notify
641          * is registered by the client's spooler.  A user Win32 app
642          * might use the flags though instead of the NOTIFY_OPTION_INFO
643          * --jerry
644          */
645
646         if (!option) {
647                 return False;
648         }
649
650         if (p->notify.flags)
651                 return is_monitoring_event_flags(
652                         p->notify.flags, notify_type, notify_field);
653
654         for (i = 0; i < option->count; i++) {
655
656                 /* Check match for notify_type */
657
658                 if (option->ctr.type[i].type != notify_type)
659                         continue;
660
661                 /* Check match for field */
662
663                 for (j = 0; j < option->ctr.type[i].count; j++) {
664                         if (option->ctr.type[i].fields[j] == notify_field) {
665                                 return True;
666                         }
667                 }
668         }
669
670         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
671                    p->servername, p->sharename, notify_type, notify_field));
672
673         return False;
674 }
675
676 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
677         _data->data.integer[0] = _integer; \
678         _data->data.integer[1] = 0;
679
680
681 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
682         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
683         if (!_data->data.string.string) {\
684                 _data->data.string.size = 0; \
685         } \
686         _data->data.string.size = strlen_m_term(_p) * 2;
687
688 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
689         _data->data.devmode.devmode = _devmode;
690
691 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
692         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
693         if (!_data->data.sd.sd) { \
694                 _data->data.sd.sd_size = 0; \
695         } \
696         _data->data.sd.sd_size = _size;
697
698 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
699                                    struct tm *t,
700                                    const char **pp,
701                                    uint32_t *plen)
702 {
703         struct spoolss_Time st;
704         uint32_t len = 16;
705         char *p;
706
707         if (!init_systemtime(&st, t)) {
708                 return;
709         }
710
711         p = talloc_array(mem_ctx, char, len);
712         if (!p) {
713                 return;
714         }
715
716         /*
717          * Systemtime must be linearized as a set of UINT16's.
718          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
719          */
720
721         SSVAL(p, 0, st.year);
722         SSVAL(p, 2, st.month);
723         SSVAL(p, 4, st.day_of_week);
724         SSVAL(p, 6, st.day);
725         SSVAL(p, 8, st.hour);
726         SSVAL(p, 10, st.minute);
727         SSVAL(p, 12, st.second);
728         SSVAL(p, 14, st.millisecond);
729
730         *pp = p;
731         *plen = len;
732 }
733
734 /* Convert a notification message to a struct spoolss_Notify */
735
736 static void notify_one_value(struct spoolss_notify_msg *msg,
737                              struct spoolss_Notify *data,
738                              TALLOC_CTX *mem_ctx)
739 {
740         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
741 }
742
743 static void notify_string(struct spoolss_notify_msg *msg,
744                           struct spoolss_Notify *data,
745                           TALLOC_CTX *mem_ctx)
746 {
747         /* The length of the message includes the trailing \0 */
748
749         data->data.string.size = msg->len * 2;
750         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
751         if (!data->data.string.string) {
752                 data->data.string.size = 0;
753                 return;
754         }
755 }
756
757 static void notify_system_time(struct spoolss_notify_msg *msg,
758                                struct spoolss_Notify *data,
759                                TALLOC_CTX *mem_ctx)
760 {
761         data->data.string.string = NULL;
762         data->data.string.size = 0;
763
764         if (msg->len != sizeof(time_t)) {
765                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
766                           msg->len));
767                 return;
768         }
769
770         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
771                                &data->data.string.string,
772                                &data->data.string.size);
773 }
774
775 struct notify2_message_table {
776         const char *name;
777         void (*fn)(struct spoolss_notify_msg *msg,
778                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
779 };
780
781 static struct notify2_message_table printer_notify_table[] = {
782         /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
783         /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
784         /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
785         /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
786         /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
787         /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
788         /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
789         /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
790         /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
791         /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
792         /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
793         /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
794         /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
795         /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
796         /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
797         /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
798         /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
799         /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
800         /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
801 };
802
803 static struct notify2_message_table job_notify_table[] = {
804         /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
805         /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
806         /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
807         /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
808         /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
809         /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
810         /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
811         /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
812         /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
813         /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
814         /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
815         /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
816         /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
817         /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
818         /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
819         /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
820         /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
821         /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
822         /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
823         /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
824         /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
825         /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
826         /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
827         /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
828 };
829
830
831 /***********************************************************************
832  Allocate talloc context for container object
833  **********************************************************************/
834
835 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 {
837         if ( !ctr )
838                 return;
839
840         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
841
842         return;
843 }
844
845 /***********************************************************************
846  release all allocated memory and zero out structure
847  **********************************************************************/
848
849 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
850 {
851         if ( !ctr )
852                 return;
853
854         if ( ctr->ctx )
855                 talloc_destroy(ctr->ctx);
856
857         ZERO_STRUCTP(ctr);
858
859         return;
860 }
861
862 /***********************************************************************
863  **********************************************************************/
864
865 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
866 {
867         if ( !ctr )
868                 return NULL;
869
870         return ctr->ctx;
871 }
872
873 /***********************************************************************
874  **********************************************************************/
875
876 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
877 {
878         if ( !ctr || !ctr->msg_groups )
879                 return NULL;
880
881         if ( idx >= ctr->num_groups )
882                 return NULL;
883
884         return &ctr->msg_groups[idx];
885
886 }
887
888 /***********************************************************************
889  How many groups of change messages do we have ?
890  **********************************************************************/
891
892 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
893 {
894         if ( !ctr )
895                 return 0;
896
897         return ctr->num_groups;
898 }
899
900 /***********************************************************************
901  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
902  **********************************************************************/
903
904 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
905 {
906         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
907         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
908         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
909         int                             i, new_slot;
910
911         if ( !ctr || !msg )
912                 return 0;
913
914         /* loop over all groups looking for a matching printer name */
915
916         for ( i=0; i<ctr->num_groups; i++ ) {
917                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
918                         break;
919         }
920
921         /* add a new group? */
922
923         if ( i == ctr->num_groups ) {
924                 ctr->num_groups++;
925
926                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
927                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
928                         return 0;
929                 }
930                 ctr->msg_groups = groups;
931
932                 /* clear the new entry and set the printer name */
933
934                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
935                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
936         }
937
938         /* add the change messages; 'i' is the correct index now regardless */
939
940         msg_grp = &ctr->msg_groups[i];
941
942         msg_grp->num_msgs++;
943
944         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
945                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
946                 return 0;
947         }
948         msg_grp->msgs = msg_list;
949
950         new_slot = msg_grp->num_msgs-1;
951         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
952
953         /* need to allocate own copy of data */
954
955         if ( msg->len != 0 )
956                 msg_grp->msgs[new_slot].notify.data = (char *)
957                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
958
959         return ctr->num_groups;
960 }
961
962 /***********************************************************************
963  Send a change notication message on all handles which have a call
964  back registered
965  **********************************************************************/
966
967 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
968 {
969         Printer_entry            *p;
970         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
971         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
972         SPOOLSS_NOTIFY_MSG       *messages;
973         int                      sending_msg_count;
974
975         if ( !msg_group ) {
976                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
977                 return;
978         }
979
980         messages = msg_group->msgs;
981
982         if ( !messages ) {
983                 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
984                 return;
985         }
986
987         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
988
989         /* loop over all printers */
990
991         for (p = printers_list; p; p = p->next) {
992                 struct spoolss_Notify *notifies;
993                 uint32_t count = 0;
994                 uint32_t id;
995                 int     i;
996
997                 /* Is there notification on this handle? */
998
999                 if ( !p->notify.client_connected )
1000                         continue;
1001
1002                 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1003
1004                 /* For this printer?  Print servers always receive
1005                    notifications. */
1006
1007                 if ( ( p->printer_type == SPLHND_PRINTER )  &&
1008                     ( !strequal(msg_group->printername, p->sharename) ) )
1009                         continue;
1010
1011                 DEBUG(10,("Our printer\n"));
1012
1013                 /* allocate the max entries possible */
1014
1015                 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1016                 if (!notifies) {
1017                         return;
1018                 }
1019
1020                 /* build the array of change notifications */
1021
1022                 sending_msg_count = 0;
1023
1024                 for ( i=0; i<msg_group->num_msgs; i++ ) {
1025                         SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
1026
1027                         /* Are we monitoring this event? */
1028
1029                         if (!is_monitoring_event(p, msg->type, msg->field))
1030                                 continue;
1031
1032                         sending_msg_count++;
1033
1034
1035                         DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1036                                 msg->type, msg->field, p->sharename));
1037
1038                         /*
1039                          * if the is a printer notification handle and not a job notification
1040                          * type, then set the id to 0.  Other wise just use what was specified
1041                          * in the message.
1042                          *
1043                          * When registering change notification on a print server handle
1044                          * we always need to send back the id (snum) matching the printer
1045                          * for which the change took place.  For change notify registered
1046                          * on a printer handle, this does not matter and the id should be 0.
1047                          *
1048                          * --jerry
1049                          */
1050
1051                         if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1052                                 id = 0;
1053                         else
1054                                 id = msg->id;
1055
1056
1057                         /* Convert unix jobid to smb jobid */
1058
1059                         if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1060                                 id = sysjob_to_jobid(msg->id);
1061
1062                                 if (id == -1) {
1063                                         DEBUG(3, ("no such unix jobid %d\n", msg->id));
1064                                         goto done;
1065                                 }
1066                         }
1067
1068                         construct_info_data( &notifies[count], msg->type, msg->field, id );
1069
1070                         switch(msg->type) {
1071                         case PRINTER_NOTIFY_TYPE:
1072                                 if ( printer_notify_table[msg->field].fn )
1073                                         printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1074                                 break;
1075
1076                         case JOB_NOTIFY_TYPE:
1077                                 if ( job_notify_table[msg->field].fn )
1078                                         job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1079                                 break;
1080
1081                         default:
1082                                 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1083                                 goto done;
1084                         }
1085
1086                         count++;
1087                 }
1088
1089                 if ( sending_msg_count ) {
1090                         rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1091                                         data_len, data, p->notify.change, 0 );
1092                 }
1093         }
1094
1095 done:
1096         DEBUG(8,("send_notify2_changes: Exit...\n"));
1097         return;
1098 }
1099
1100 /***********************************************************************
1101  **********************************************************************/
1102
1103 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1104 {
1105
1106         uint32 tv_sec, tv_usec;
1107         size_t offset = 0;
1108
1109         /* Unpack message */
1110
1111         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1112                              msg->printer);
1113
1114         offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1115                                 &tv_sec, &tv_usec,
1116                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1117
1118         if (msg->len == 0)
1119                 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1120                            &msg->notify.value[0], &msg->notify.value[1]);
1121         else
1122                 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1123                            &msg->len, &msg->notify.data);
1124
1125         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1126                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1127
1128         tv->tv_sec = tv_sec;
1129         tv->tv_usec = tv_usec;
1130
1131         if (msg->len == 0)
1132                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1133                           msg->notify.value[1]));
1134         else
1135                 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1136
1137         return True;
1138 }
1139
1140 /********************************************************************
1141  Receive a notify2 message list
1142  ********************************************************************/
1143
1144 static void receive_notify2_message_list(struct messaging_context *msg,
1145                                          void *private_data,
1146                                          uint32_t msg_type,
1147                                          struct server_id server_id,
1148                                          DATA_BLOB *data)
1149 {
1150         size_t                  msg_count, i;
1151         char                    *buf = (char *)data->data;
1152         char                    *msg_ptr;
1153         size_t                  msg_len;
1154         SPOOLSS_NOTIFY_MSG      notify;
1155         SPOOLSS_NOTIFY_MSG_CTR  messages;
1156         int                     num_groups;
1157
1158         if (data->length < 4) {
1159                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1160                 return;
1161         }
1162
1163         msg_count = IVAL(buf, 0);
1164         msg_ptr = buf + 4;
1165
1166         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1167
1168         if (msg_count == 0) {
1169                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1170                 return;
1171         }
1172
1173         /* initialize the container */
1174
1175         ZERO_STRUCT( messages );
1176         notify_msg_ctr_init( &messages );
1177
1178         /*
1179          * build message groups for each printer identified
1180          * in a change_notify msg.  Remember that a PCN message
1181          * includes the handle returned for the srv_spoolss_replyopenprinter()
1182          * call.  Therefore messages are grouped according to printer handle.
1183          */
1184
1185         for ( i=0; i<msg_count; i++ ) {
1186                 struct timeval msg_tv;
1187
1188                 if (msg_ptr + 4 - buf > data->length) {
1189                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1190                         return;
1191                 }
1192
1193                 msg_len = IVAL(msg_ptr,0);
1194                 msg_ptr += 4;
1195
1196                 if (msg_ptr + msg_len - buf > data->length) {
1197                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1198                         return;
1199                 }
1200
1201                 /* unpack messages */
1202
1203                 ZERO_STRUCT( notify );
1204                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1205                 msg_ptr += msg_len;
1206
1207                 /* add to correct list in container */
1208
1209                 notify_msg_ctr_addmsg( &messages, &notify );
1210
1211                 /* free memory that might have been allocated by notify2_unpack_msg() */
1212
1213                 if ( notify.len != 0 )
1214                         SAFE_FREE( notify.notify.data );
1215         }
1216
1217         /* process each group of messages */
1218
1219         num_groups = notify_msg_ctr_numgroups( &messages );
1220         for ( i=0; i<num_groups; i++ )
1221                 send_notify2_changes( &messages, i );
1222
1223
1224         /* cleanup */
1225
1226         DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1227
1228         notify_msg_ctr_destroy( &messages );
1229
1230         return;
1231 }
1232
1233 /********************************************************************
1234  Send a message to ourself about new driver being installed
1235  so we can upgrade the information for each printer bound to this
1236  driver
1237  ********************************************************************/
1238
1239 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1240 {
1241         int len = strlen(drivername);
1242
1243         if (!len)
1244                 return False;
1245
1246         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1247                 drivername));
1248
1249         messaging_send_buf(smbd_messaging_context(), procid_self(),
1250                            MSG_PRINTER_DRVUPGRADE,
1251                            (uint8 *)drivername, len+1);
1252
1253         return True;
1254 }
1255
1256 /**********************************************************************
1257  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1258  over all printers, upgrading ones as necessary
1259  **********************************************************************/
1260
1261 void do_drv_upgrade_printer(struct messaging_context *msg,
1262                             void *private_data,
1263                             uint32_t msg_type,
1264                             struct server_id server_id,
1265                             DATA_BLOB *data)
1266 {
1267         fstring drivername;
1268         int snum;
1269         int n_services = lp_numservices();
1270         size_t len;
1271
1272         len = MIN(data->length,sizeof(drivername)-1);
1273         strncpy(drivername, (const char *)data->data, len);
1274
1275         DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1276
1277         /* Iterate the printer list */
1278
1279         for (snum=0; snum<n_services; snum++)
1280         {
1281                 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1282                 {
1283                         WERROR result;
1284                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1285
1286                         result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1287                         if (!W_ERROR_IS_OK(result))
1288                                 continue;
1289
1290                         if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1291                         {
1292                                 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1293
1294                                 /* all we care about currently is the change_id */
1295
1296                                 result = mod_a_printer(printer, 2);
1297                                 if (!W_ERROR_IS_OK(result)) {
1298                                         DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1299                                                 win_errstr(result)));
1300                                 }
1301                         }
1302
1303                         free_a_printer(&printer, 2);
1304                 }
1305         }
1306
1307         /* all done */
1308 }
1309
1310 /********************************************************************
1311  Update the cache for all printq's with a registered client
1312  connection
1313  ********************************************************************/
1314
1315 void update_monitored_printq_cache( void )
1316 {
1317         Printer_entry *printer = printers_list;
1318         int snum;
1319
1320         /* loop through all printers and update the cache where
1321            client_connected == True */
1322         while ( printer )
1323         {
1324                 if ( (printer->printer_type == SPLHND_PRINTER)
1325                         && printer->notify.client_connected )
1326                 {
1327                         snum = print_queue_snum(printer->sharename);
1328                         print_queue_status( snum, NULL, NULL );
1329                 }
1330
1331                 printer = printer->next;
1332         }
1333
1334         return;
1335 }
1336 /********************************************************************
1337  Send a message to ourself about new driver being installed
1338  so we can upgrade the information for each printer bound to this
1339  driver
1340  ********************************************************************/
1341
1342 static bool srv_spoolss_reset_printerdata(char* drivername)
1343 {
1344         int len = strlen(drivername);
1345
1346         if (!len)
1347                 return False;
1348
1349         DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1350                 drivername));
1351
1352         messaging_send_buf(smbd_messaging_context(), procid_self(),
1353                            MSG_PRINTERDATA_INIT_RESET,
1354                            (uint8 *)drivername, len+1);
1355
1356         return True;
1357 }
1358
1359 /**********************************************************************
1360  callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1361  over all printers, resetting printer data as neessary
1362  **********************************************************************/
1363
1364 void reset_all_printerdata(struct messaging_context *msg,
1365                            void *private_data,
1366                            uint32_t msg_type,
1367                            struct server_id server_id,
1368                            DATA_BLOB *data)
1369 {
1370         fstring drivername;
1371         int snum;
1372         int n_services = lp_numservices();
1373         size_t len;
1374
1375         len = MIN( data->length, sizeof(drivername)-1 );
1376         strncpy( drivername, (const char *)data->data, len );
1377
1378         DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1379
1380         /* Iterate the printer list */
1381
1382         for ( snum=0; snum<n_services; snum++ )
1383         {
1384                 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1385                 {
1386                         WERROR result;
1387                         NT_PRINTER_INFO_LEVEL *printer = NULL;
1388
1389                         result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1390                         if ( !W_ERROR_IS_OK(result) )
1391                                 continue;
1392
1393                         /*
1394                          * if the printer is bound to the driver,
1395                          * then reset to the new driver initdata
1396                          */
1397
1398                         if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1399                         {
1400                                 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1401
1402                                 if ( !set_driver_init(printer, 2) ) {
1403                                         DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1404                                                 printer->info_2->printername, printer->info_2->drivername));
1405                                 }
1406
1407                                 result = mod_a_printer( printer, 2 );
1408                                 if ( !W_ERROR_IS_OK(result) ) {
1409                                         DEBUG(3,("reset_all_printerdata: mod_a_printer() failed!  (%s)\n",
1410                                                 get_dos_error_msg(result)));
1411                                 }
1412                         }
1413
1414                         free_a_printer( &printer, 2 );
1415                 }
1416         }
1417
1418         /* all done */
1419
1420         return;
1421 }
1422
1423 /****************************************************************
1424  _spoolss_OpenPrinter
1425 ****************************************************************/
1426
1427 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1428                             struct spoolss_OpenPrinter *r)
1429 {
1430         struct spoolss_OpenPrinterEx e;
1431         WERROR werr;
1432
1433         ZERO_STRUCT(e.in.userlevel);
1434
1435         e.in.printername        = r->in.printername;
1436         e.in.datatype           = r->in.datatype;
1437         e.in.devmode_ctr        = r->in.devmode_ctr;
1438         e.in.access_mask        = r->in.access_mask;
1439         e.in.level              = 0;
1440
1441         e.out.handle            = r->out.handle;
1442
1443         werr = _spoolss_OpenPrinterEx(p, &e);
1444
1445         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1446                 /* OpenPrinterEx returns this for a bad
1447                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1448                  * instead.
1449                  */
1450                 werr = WERR_INVALID_PRINTER_NAME;
1451         }
1452
1453         return werr;
1454 }
1455
1456 /********************************************************************
1457  FIXME: temporary convert_devicemode_new function
1458  ********************************************************************/
1459
1460 static bool convert_devicemode_new(const char *printername,
1461                                    struct spoolss_DeviceMode *devmode,
1462                                    NT_DEVICEMODE **pp_nt_devmode)
1463 {
1464         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1465
1466         /*
1467          * Ensure nt_devmode is a valid pointer
1468          * as we will be overwriting it.
1469          */
1470
1471         if (nt_devmode == NULL) {
1472                 DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
1473                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1474                         return false;
1475         }
1476
1477         rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1478         rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1479
1480         nt_devmode->specversion         = devmode->specversion;
1481         nt_devmode->driverversion       = devmode->driverversion;
1482         nt_devmode->size                = devmode->size;
1483         nt_devmode->fields              = devmode->fields;
1484         nt_devmode->orientation         = devmode->orientation;
1485         nt_devmode->papersize           = devmode->papersize;
1486         nt_devmode->paperlength         = devmode->paperlength;
1487         nt_devmode->paperwidth          = devmode->paperwidth;
1488         nt_devmode->scale               = devmode->scale;
1489         nt_devmode->copies              = devmode->copies;
1490         nt_devmode->defaultsource       = devmode->defaultsource;
1491         nt_devmode->printquality        = devmode->printquality;
1492         nt_devmode->color               = devmode->color;
1493         nt_devmode->duplex              = devmode->duplex;
1494         nt_devmode->yresolution         = devmode->yresolution;
1495         nt_devmode->ttoption            = devmode->ttoption;
1496         nt_devmode->collate             = devmode->collate;
1497
1498         nt_devmode->logpixels           = devmode->logpixels;
1499         nt_devmode->bitsperpel          = devmode->bitsperpel;
1500         nt_devmode->pelswidth           = devmode->pelswidth;
1501         nt_devmode->pelsheight          = devmode->pelsheight;
1502         nt_devmode->displayflags        = devmode->displayflags;
1503         nt_devmode->displayfrequency    = devmode->displayfrequency;
1504         nt_devmode->icmmethod           = devmode->icmmethod;
1505         nt_devmode->icmintent           = devmode->icmintent;
1506         nt_devmode->mediatype           = devmode->mediatype;
1507         nt_devmode->dithertype          = devmode->dithertype;
1508         nt_devmode->reserved1           = devmode->reserved1;
1509         nt_devmode->reserved2           = devmode->reserved2;
1510         nt_devmode->panningwidth        = devmode->panningwidth;
1511         nt_devmode->panningheight       = devmode->panningheight;
1512
1513         /*
1514          * Only change private and driverextra if the incoming devmode
1515          * has a new one. JRA.
1516          */
1517
1518         if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1519                 SAFE_FREE(nt_devmode->nt_dev_private);
1520                 nt_devmode->driverextra = devmode->__driverextra_length;
1521                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1522                         return false;
1523                 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1524         }
1525
1526         *pp_nt_devmode = nt_devmode;
1527
1528         return true;
1529 }
1530
1531 /****************************************************************
1532  _spoolss_OpenPrinterEx
1533 ****************************************************************/
1534
1535 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1536                               struct spoolss_OpenPrinterEx *r)
1537 {
1538         POLICY_HND              *handle = r->out.handle;
1539         char *name = CONST_DISCARD(char *, r->in.printername);
1540         int snum;
1541         Printer_entry *Printer=NULL;
1542
1543         if (!name) {
1544                 return WERR_INVALID_PARAM;
1545         }
1546
1547         /* some sanity check because you can open a printer or a print server */
1548         /* aka: \\server\printer or \\server */
1549
1550         DEBUGADD(3,("checking name: %s\n",name));
1551
1552         if (!open_printer_hnd(p, handle, name, 0)) {
1553                 ZERO_STRUCTP(r->out.handle);
1554                 return WERR_INVALID_PARAM;
1555         }
1556
1557         Printer=find_printer_index_by_hnd(p, handle);
1558         if ( !Printer ) {
1559                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1560                         "handle we created for printer %s\n", name ));
1561                 close_printer_handle(p,handle);
1562                 ZERO_STRUCTP(r->out.handle);
1563                 return WERR_INVALID_PARAM;
1564         }
1565
1566         /*
1567          * First case: the user is opening the print server:
1568          *
1569          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1570          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571          *
1572          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1573          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1574          * or if the user is listed in the smb.conf printer admin parameter.
1575          *
1576          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1577          * client view printer folder, but does not show the MSAPW.
1578          *
1579          * Note: this test needs code to check access rights here too. Jeremy
1580          * could you look at this?
1581          *
1582          * Second case: the user is opening a printer:
1583          * NT doesn't let us connect to a printer if the connecting user
1584          * doesn't have print permission.
1585          *
1586          * Third case: user is opening a Port Monitor
1587          * access checks same as opening a handle to the print server.
1588          */
1589
1590         switch (Printer->printer_type )
1591         {
1592         case SPLHND_SERVER:
1593         case SPLHND_PORTMON_TCP:
1594         case SPLHND_PORTMON_LOCAL:
1595                 /* Printserver handles use global struct... */
1596
1597                 snum = -1;
1598
1599                 /* Map standard access rights to object specific access rights */
1600
1601                 se_map_standard(&r->in.access_mask,
1602                                 &printserver_std_mapping);
1603
1604                 /* Deny any object specific bits that don't apply to print
1605                    servers (i.e printer and job specific bits) */
1606
1607                 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1608
1609                 if (r->in.access_mask &
1610                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1611                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1612                         close_printer_handle(p, handle);
1613                         ZERO_STRUCTP(r->out.handle);
1614                         return WERR_ACCESS_DENIED;
1615                 }
1616
1617                 /* Allow admin access */
1618
1619                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1620                 {
1621                         SE_PRIV se_printop = SE_PRINT_OPERATOR;
1622
1623                         if (!lp_ms_add_printer_wizard()) {
1624                                 close_printer_handle(p, handle);
1625                                 ZERO_STRUCTP(r->out.handle);
1626                                 return WERR_ACCESS_DENIED;
1627                         }
1628
1629                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1630                            and not a printer admin, then fail */
1631
1632                         if ((p->server_info->utok.uid != 0) &&
1633                             !user_has_privileges(p->server_info->ptok,
1634                                                  &se_printop ) &&
1635                             !token_contains_name_in_list(
1636                                     uidtoname(p->server_info->utok.uid),
1637                                     NULL, NULL,
1638                                     p->server_info->ptok,
1639                                     lp_printer_admin(snum))) {
1640                                 close_printer_handle(p, handle);
1641                                 ZERO_STRUCTP(r->out.handle);
1642                                 return WERR_ACCESS_DENIED;
1643                         }
1644
1645                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1646                 }
1647                 else
1648                 {
1649                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1650                 }
1651
1652                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1653                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1654
1655                 /* We fall through to return WERR_OK */
1656                 break;
1657
1658         case SPLHND_PRINTER:
1659                 /* NT doesn't let us connect to a printer if the connecting user
1660                    doesn't have print permission.  */
1661
1662                 if (!get_printer_snum(p, handle, &snum, NULL)) {
1663                         close_printer_handle(p, handle);
1664                         ZERO_STRUCTP(r->out.handle);
1665                         return WERR_BADFID;
1666                 }
1667
1668                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1669
1670                 /* map an empty access mask to the minimum access mask */
1671                 if (r->in.access_mask == 0x0)
1672                         r->in.access_mask = PRINTER_ACCESS_USE;
1673
1674                 /*
1675                  * If we are not serving the printer driver for this printer,
1676                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1677                  * will keep NT clients happy  --jerry
1678                  */
1679
1680                 if (lp_use_client_driver(snum)
1681                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1682                 {
1683                         r->in.access_mask = PRINTER_ACCESS_USE;
1684                 }
1685
1686                 /* check smb.conf parameters and the the sec_desc */
1687
1688                 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1689                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1690                         ZERO_STRUCTP(r->out.handle);
1691                         return WERR_ACCESS_DENIED;
1692                 }
1693
1694                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1695                                    p->server_info->ptok, snum) ||
1696                     !print_access_check(p->server_info, snum,
1697                                         r->in.access_mask)) {
1698                         DEBUG(3, ("access DENIED for printer open\n"));
1699                         close_printer_handle(p, handle);
1700                         ZERO_STRUCTP(r->out.handle);
1701                         return WERR_ACCESS_DENIED;
1702                 }
1703
1704                 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1705                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1706                         close_printer_handle(p, handle);
1707                         ZERO_STRUCTP(r->out.handle);
1708                         return WERR_ACCESS_DENIED;
1709                 }
1710
1711                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1712                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1713                 else
1714                         r->in.access_mask = PRINTER_ACCESS_USE;
1715
1716                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1717                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1718
1719                 break;
1720
1721         default:
1722                 /* sanity check to prevent programmer error */
1723                 ZERO_STRUCTP(r->out.handle);
1724                 return WERR_BADFID;
1725         }
1726
1727         Printer->access_granted = r->in.access_mask;
1728
1729         /*
1730          * If the client sent a devmode in the OpenPrinter() call, then
1731          * save it here in case we get a job submission on this handle
1732          */
1733
1734          if ( (Printer->printer_type != SPLHND_SERVER)
1735                 && r->in.devmode_ctr.devmode )
1736          {
1737                 convert_devicemode_new(Printer->sharename,
1738                                        r->in.devmode_ctr.devmode,
1739                                        &Printer->nt_devmode);
1740          }
1741
1742 #if 0   /* JERRY -- I'm doubtful this is really effective */
1743         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1744            optimization in Windows 2000 clients  --jerry */
1745
1746         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1747                 && (RA_WIN2K == get_remote_arch()) )
1748         {
1749                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1750                 sys_usleep( 500000 );
1751         }
1752 #endif
1753
1754         return WERR_OK;
1755 }
1756
1757 /****************************************************************************
1758 ****************************************************************************/
1759
1760 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1761                                               NT_PRINTER_INFO_LEVEL_2 *d)
1762 {
1763         DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1764
1765         if (!r || !d) {
1766                 return false;
1767         }
1768
1769         d->attributes           = r->attributes;
1770         d->priority             = r->priority;
1771         d->default_priority     = r->defaultpriority;
1772         d->starttime            = r->starttime;
1773         d->untiltime            = r->untiltime;
1774         d->status               = r->status;
1775         d->cjobs                = r->cjobs;
1776
1777         fstrcpy(d->servername,  r->servername);
1778         fstrcpy(d->printername, r->printername);
1779         fstrcpy(d->sharename,   r->sharename);
1780         fstrcpy(d->portname,    r->portname);
1781         fstrcpy(d->drivername,  r->drivername);
1782         slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1783         fstrcpy(d->location,    r->location);
1784         fstrcpy(d->sepfile,     r->sepfile);
1785         fstrcpy(d->printprocessor, r->printprocessor);
1786         fstrcpy(d->datatype,    r->datatype);
1787         fstrcpy(d->parameters,  r->parameters);
1788
1789         return true;
1790 }
1791
1792 /****************************************************************************
1793 ****************************************************************************/
1794
1795 static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
1796                                      NT_PRINTER_INFO_LEVEL *printer)
1797 {
1798         bool ret;
1799
1800         switch (info_ctr->level) {
1801         case 2:
1802                 /* allocate memory if needed.  Messy because
1803                    convert_printer_info is used to update an existing
1804                    printer or build a new one */
1805
1806                 if (!printer->info_2) {
1807                         printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1808                         if (!printer->info_2) {
1809                                 DEBUG(0,("convert_printer_info_new: "
1810                                         "talloc() failed!\n"));
1811                                 return false;
1812                         }
1813                 }
1814
1815                 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1816                                                         printer->info_2);
1817                 printer->info_2->setuptime = time(NULL);
1818                 return ret;
1819         }
1820
1821         return false;
1822 }
1823
1824 /*******************************************************************
1825 ********************************************************************/
1826
1827 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1828 {
1829         int i;
1830
1831         if (!sarray) {
1832                 *farray = NULL;
1833                 return true;
1834         }
1835
1836         *farray = SMB_MALLOC_ARRAY(fstring, 1);
1837         if (!*farray) {
1838                 return false;
1839         }
1840
1841         for (i=0; sarray[i] != NULL; i++) {
1842                 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1843                 if (!*farray) {
1844                         return false;
1845                 }
1846                 fstrcpy((*farray)[i], sarray[i]);
1847         }
1848
1849         fstrcpy((*farray)[i], "");
1850
1851         return true;
1852 }
1853
1854 /*******************************************************************
1855 ********************************************************************/
1856
1857 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1858                                             NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1859 {
1860         NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1861
1862         DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1863
1864         if (*p == NULL) {
1865                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1866                 if (*p == NULL) {
1867                         return false;
1868                 }
1869                 ZERO_STRUCTP(*p);
1870         }
1871
1872         d = *p;
1873
1874         d->cversion =                   r->version;
1875
1876         fstrcpy(d->name,                r->driver_name);
1877         fstrcpy(d->environment,         r->architecture);
1878         fstrcpy(d->driverpath,          r->driver_path);
1879         fstrcpy(d->datafile,            r->data_file);
1880         fstrcpy(d->configfile,          r->config_file);
1881         fstrcpy(d->helpfile,            r->help_file);
1882         fstrcpy(d->monitorname,         r->monitor_name);
1883         fstrcpy(d->defaultdatatype,     r->default_datatype);
1884
1885         DEBUGADD(8,( "version:         %d\n", d->cversion));
1886         DEBUGADD(8,( "name:            %s\n", d->name));
1887         DEBUGADD(8,( "environment:     %s\n", d->environment));
1888         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1889         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1890         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1891         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1892         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1893         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1894
1895         if (r->dependent_files) {
1896                 if (!string_array_to_fstring_array(r->dependent_files->string,
1897                                                    &d->dependentfiles)) {
1898                         SAFE_FREE(*p);
1899                         return false;
1900                 }
1901         }
1902
1903         return true;
1904 }
1905
1906 /*******************************************************************
1907 ********************************************************************/
1908
1909 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1910                                             NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1911 {
1912         NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1913
1914         DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1915
1916         if (*p == NULL) {
1917                 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1918                 if (*p == NULL) {
1919                         return false;
1920                 }
1921                 ZERO_STRUCTP(*p);
1922         }
1923
1924         d = *p;
1925
1926         d->version =                    r->version;
1927
1928         fstrcpy(d->name,                r->driver_name);
1929         fstrcpy(d->environment,         r->architecture);
1930         fstrcpy(d->driverpath,          r->driver_path);
1931         fstrcpy(d->datafile,            r->data_file);
1932         fstrcpy(d->configfile,          r->config_file);
1933         fstrcpy(d->helpfile,            r->help_file);
1934         fstrcpy(d->monitorname,         r->monitor_name);
1935         fstrcpy(d->defaultdatatype,     r->default_datatype);
1936
1937         DEBUGADD(8,( "version:         %d\n", d->version));
1938         DEBUGADD(8,( "name:            %s\n", d->name));
1939         DEBUGADD(8,( "environment:     %s\n", d->environment));
1940         DEBUGADD(8,( "driverpath:      %s\n", d->driverpath));
1941         DEBUGADD(8,( "datafile:        %s\n", d->datafile));
1942         DEBUGADD(8,( "configfile:      %s\n", d->configfile));
1943         DEBUGADD(8,( "helpfile:        %s\n", d->helpfile));
1944         DEBUGADD(8,( "monitorname:     %s\n", d->monitorname));
1945         DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1946
1947         if (r->dependent_files) {
1948                 if (!string_array_to_fstring_array(r->dependent_files->string,
1949                                                    &d->dependentfiles)) {
1950                         goto error;
1951                 }
1952         }
1953
1954         if (r->previous_names) {
1955                 if (!string_array_to_fstring_array(r->previous_names->string,
1956                                                    &d->previousnames)) {
1957                         goto error;
1958                 }
1959         }
1960
1961         return true;
1962
1963  error:
1964         SAFE_FREE(*p);
1965         return false;
1966 }
1967
1968 /********************************************************************
1969  ********************************************************************/
1970
1971 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1972                                         NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1973                                         uint32_t level)
1974 {
1975         switch (level) {
1976         case 3:
1977                 printer->info_3 = NULL;
1978                 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1979                         return false;
1980                 }
1981                 break;
1982         case 6:
1983                 printer->info_6 = NULL;
1984                 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
1985                         return false;
1986                 }
1987                 break;
1988         default:
1989                 return false;
1990         }
1991
1992         return true;
1993 }
1994
1995 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1996                                 NT_DEVICEMODE **pp_nt_devmode)
1997 {
1998         NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1999
2000         /*
2001          * Ensure nt_devmode is a valid pointer
2002          * as we will be overwriting it.
2003          */
2004
2005         if (nt_devmode == NULL) {
2006                 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
2007                 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
2008                         return False;
2009         }
2010
2011         rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
2012         rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
2013
2014         nt_devmode->specversion=devmode->specversion;
2015         nt_devmode->driverversion=devmode->driverversion;
2016         nt_devmode->size=devmode->size;
2017         nt_devmode->fields=devmode->fields;
2018         nt_devmode->orientation=devmode->orientation;
2019         nt_devmode->papersize=devmode->papersize;
2020         nt_devmode->paperlength=devmode->paperlength;
2021         nt_devmode->paperwidth=devmode->paperwidth;
2022         nt_devmode->scale=devmode->scale;
2023         nt_devmode->copies=devmode->copies;
2024         nt_devmode->defaultsource=devmode->defaultsource;
2025         nt_devmode->printquality=devmode->printquality;
2026         nt_devmode->color=devmode->color;
2027         nt_devmode->duplex=devmode->duplex;
2028         nt_devmode->yresolution=devmode->yresolution;
2029         nt_devmode->ttoption=devmode->ttoption;
2030         nt_devmode->collate=devmode->collate;
2031
2032         nt_devmode->logpixels=devmode->logpixels;
2033         nt_devmode->bitsperpel=devmode->bitsperpel;
2034         nt_devmode->pelswidth=devmode->pelswidth;
2035         nt_devmode->pelsheight=devmode->pelsheight;
2036         nt_devmode->displayflags=devmode->displayflags;
2037         nt_devmode->displayfrequency=devmode->displayfrequency;
2038         nt_devmode->icmmethod=devmode->icmmethod;
2039         nt_devmode->icmintent=devmode->icmintent;
2040         nt_devmode->mediatype=devmode->mediatype;
2041         nt_devmode->dithertype=devmode->dithertype;
2042         nt_devmode->reserved1=devmode->reserved1;
2043         nt_devmode->reserved2=devmode->reserved2;
2044         nt_devmode->panningwidth=devmode->panningwidth;
2045         nt_devmode->panningheight=devmode->panningheight;
2046
2047         /*
2048          * Only change private and driverextra if the incoming devmode
2049          * has a new one. JRA.
2050          */
2051
2052         if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
2053                 SAFE_FREE(nt_devmode->nt_dev_private);
2054                 nt_devmode->driverextra=devmode->driverextra;
2055                 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
2056                         return False;
2057                 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
2058         }
2059
2060         *pp_nt_devmode = nt_devmode;
2061
2062         return True;
2063 }
2064
2065 /********************************************************************
2066  * _spoolss_enddocprinter_internal.
2067  ********************************************************************/
2068
2069 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
2070 {
2071         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2072         int snum;
2073
2074         if (!Printer) {
2075                 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
2076                 return WERR_BADFID;
2077         }
2078
2079         if (!get_printer_snum(p, handle, &snum, NULL))
2080                 return WERR_BADFID;
2081
2082         Printer->document_started=False;
2083         print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
2084         /* error codes unhandled so far ... */
2085
2086         return WERR_OK;
2087 }
2088
2089 /****************************************************************
2090  _spoolss_ClosePrinter
2091 ****************************************************************/
2092
2093 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2094                              struct spoolss_ClosePrinter *r)
2095 {
2096         POLICY_HND *handle = r->in.handle;
2097
2098         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2099
2100         if (Printer && Printer->document_started)
2101                 _spoolss_enddocprinter_internal(p, handle);          /* print job was not closed */
2102
2103         if (!close_printer_handle(p, handle))
2104                 return WERR_BADFID;
2105
2106         /* clear the returned printer handle.  Observed behavior
2107            from Win2k server.  Don't think this really matters.
2108            Previous code just copied the value of the closed
2109            handle.    --jerry */
2110
2111         ZERO_STRUCTP(r->out.handle);
2112
2113         return WERR_OK;
2114 }
2115
2116 /****************************************************************
2117  _spoolss_DeletePrinter
2118 ****************************************************************/
2119
2120 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2121                               struct spoolss_DeletePrinter *r)
2122 {
2123         POLICY_HND *handle = r->in.handle;
2124         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2125         WERROR result;
2126
2127         if (Printer && Printer->document_started)
2128                 _spoolss_enddocprinter_internal(p, handle);  /* print job was not closed */
2129
2130         result = delete_printer_handle(p, handle);
2131
2132         update_c_setprinter(False);
2133
2134         return result;
2135 }
2136
2137 /*******************************************************************
2138  * static function to lookup the version id corresponding to an
2139  * long architecture string
2140  ******************************************************************/
2141
2142 static int get_version_id (char * arch)
2143 {
2144         int i;
2145         struct table_node archi_table[]= {
2146
2147                 {"Windows 4.0",          "WIN40",       0 },
2148                 {"Windows NT x86",       "W32X86",      2 },
2149                 {"Windows NT R4000",     "W32MIPS",     2 },
2150                 {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
2151                 {"Windows NT PowerPC",   "W32PPC",      2 },
2152                 {"Windows IA64",         "IA64",        3 },
2153                 {"Windows x64",          "x64",         3 },
2154                 {NULL,                   "",            -1 }
2155         };
2156
2157         for (i=0; archi_table[i].long_archi != NULL; i++)
2158         {
2159                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2160                         return (archi_table[i].version);
2161         }
2162
2163         return -1;
2164 }
2165
2166 /****************************************************************
2167  _spoolss_DeletePrinterDriver
2168 ****************************************************************/
2169
2170 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2171                                     struct spoolss_DeletePrinterDriver *r)
2172 {
2173         char *driver;
2174         char *arch;
2175         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2176         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2177         int                             version;
2178         WERROR                          status;
2179         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2180         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2181
2182         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2183            and not a printer admin, then fail */
2184
2185         if ( (p->server_info->utok.uid != 0)
2186                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2187                 && !token_contains_name_in_list(
2188                         uidtoname(p->server_info->utok.uid), NULL,
2189                         NULL, p->server_info->ptok,
2190                         lp_printer_admin(-1)) )
2191         {
2192                 return WERR_ACCESS_DENIED;
2193         }
2194
2195         driver = CONST_DISCARD(char *, r->in.driver);
2196         arch   = CONST_DISCARD(char *, r->in.architecture);
2197
2198         /* check that we have a valid driver name first */
2199
2200         if ((version=get_version_id(arch)) == -1)
2201                 return WERR_INVALID_ENVIRONMENT;
2202
2203         ZERO_STRUCT(info);
2204         ZERO_STRUCT(info_win2k);
2205
2206         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2207         {
2208                 /* try for Win2k driver if "Windows NT x86" */
2209
2210                 if ( version == 2 ) {
2211                         version = 3;
2212                         if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2213                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2214                                 goto done;
2215                         }
2216                 }
2217                 /* otherwise it was a failure */
2218                 else {
2219                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2220                         goto done;
2221                 }
2222
2223         }
2224
2225         if (printer_driver_in_use(info.info_3)) {
2226                 status = WERR_PRINTER_DRIVER_IN_USE;
2227                 goto done;
2228         }
2229
2230         if ( version == 2 )
2231         {
2232                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2233                 {
2234                         /* if we get to here, we now have 2 driver info structures to remove */
2235                         /* remove the Win2k driver first*/
2236
2237                         status_win2k = delete_printer_driver(
2238                                 p, info_win2k.info_3, 3, False );
2239                         free_a_printer_driver( info_win2k, 3 );
2240
2241                         /* this should not have failed---if it did, report to client */
2242                         if ( !W_ERROR_IS_OK(status_win2k) )
2243                         {
2244                                 status = status_win2k;
2245                                 goto done;
2246                         }
2247                 }
2248         }
2249
2250         status = delete_printer_driver(p, info.info_3, version, False);
2251
2252         /* if at least one of the deletes succeeded return OK */
2253
2254         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2255                 status = WERR_OK;
2256
2257 done:
2258         free_a_printer_driver( info, 3 );
2259
2260         return status;
2261 }
2262
2263 /****************************************************************
2264  _spoolss_DeletePrinterDriverEx
2265 ****************************************************************/
2266
2267 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2268                                       struct spoolss_DeletePrinterDriverEx *r)
2269 {
2270         char *driver;
2271         char *arch;
2272         NT_PRINTER_DRIVER_INFO_LEVEL    info;
2273         NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
2274         int                             version;
2275         uint32_t                        flags = r->in.delete_flags;
2276         bool                            delete_files;
2277         WERROR                          status;
2278         WERROR                          status_win2k = WERR_ACCESS_DENIED;
2279         SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
2280
2281         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2282            and not a printer admin, then fail */
2283
2284         if ( (p->server_info->utok.uid != 0)
2285                 && !user_has_privileges(p->server_info->ptok, &se_printop )
2286                 && !token_contains_name_in_list(
2287                         uidtoname(p->server_info->utok.uid), NULL, NULL,
2288                         p->server_info->ptok, lp_printer_admin(-1)) )
2289         {
2290                 return WERR_ACCESS_DENIED;
2291         }
2292
2293         driver = CONST_DISCARD(char *, r->in.driver);
2294         arch   = CONST_DISCARD(char *, r->in.architecture);
2295
2296         /* check that we have a valid driver name first */
2297         if ((version=get_version_id(arch)) == -1) {
2298                 /* this is what NT returns */
2299                 return WERR_INVALID_ENVIRONMENT;
2300         }
2301
2302         if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2303                 version = r->in.version;
2304
2305         ZERO_STRUCT(info);
2306         ZERO_STRUCT(info_win2k);
2307
2308         status = get_a_printer_driver(&info, 3, driver, arch, version);
2309
2310         if ( !W_ERROR_IS_OK(status) )
2311         {
2312                 /*
2313                  * if the client asked for a specific version,
2314                  * or this is something other than Windows NT x86,
2315                  * then we've failed
2316                  */
2317
2318                 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2319                         goto done;
2320
2321                 /* try for Win2k driver if "Windows NT x86" */
2322
2323                 version = 3;
2324                 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2325                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2326                         goto done;
2327                 }
2328         }
2329
2330         if ( printer_driver_in_use(info.info_3) ) {
2331                 status = WERR_PRINTER_DRIVER_IN_USE;
2332                 goto done;
2333         }
2334
2335         /*
2336          * we have a couple of cases to consider.
2337          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2338          *     then the delete should fail if **any** files overlap with
2339          *     other drivers
2340          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2341          *     non-overlapping files
2342          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2343          *     is set, the do not delete any files
2344          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2345          */
2346
2347         delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2348
2349         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2350
2351         if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2352                 /* no idea of the correct error here */
2353                 status = WERR_ACCESS_DENIED;
2354                 goto done;
2355         }
2356
2357
2358         /* also check for W32X86/3 if necessary; maybe we already have? */
2359
2360         if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2361                 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2362                 {
2363
2364                         if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2365                                 /* no idea of the correct error here */
2366                                 free_a_printer_driver( info_win2k, 3 );
2367                                 status = WERR_ACCESS_DENIED;
2368                                 goto done;
2369                         }
2370
2371                         /* if we get to here, we now have 2 driver info structures to remove */
2372                         /* remove the Win2k driver first*/
2373
2374                         status_win2k = delete_printer_driver(
2375                                 p, info_win2k.info_3, 3, delete_files);
2376                         free_a_printer_driver( info_win2k, 3 );
2377
2378                         /* this should not have failed---if it did, report to client */
2379
2380                         if ( !W_ERROR_IS_OK(status_win2k) )
2381                                 goto done;
2382                 }
2383         }
2384
2385         status = delete_printer_driver(p, info.info_3, version, delete_files);
2386
2387         if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2388                 status = WERR_OK;
2389 done:
2390         free_a_printer_driver( info, 3 );
2391
2392         return status;
2393 }
2394
2395
2396 /****************************************************************************
2397  Internal routine for retreiving printerdata
2398  ***************************************************************************/
2399
2400 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2401                                   const char *key, const char *value, uint32 *type, uint8 **data,
2402                                   uint32 *needed, uint32 in_size  )
2403 {
2404         REGISTRY_VALUE          *val;
2405         uint32                  size;
2406         int                     data_len;
2407
2408         if ( !(val = get_printer_data( printer->info_2, key, value)) )
2409                 return WERR_BADFILE;
2410
2411         *type = regval_type( val );
2412
2413         DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2414
2415         size = regval_size( val );
2416
2417         /* copy the min(in_size, len) */
2418
2419         if ( in_size ) {
2420                 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2421
2422                 /* special case for 0 length values */
2423                 if ( data_len ) {
2424                         if ( (*data  = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2425                                 return WERR_NOMEM;
2426                 }
2427                 else {
2428                         if ( (*data  = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2429                                 return WERR_NOMEM;
2430                 }
2431         }
2432         else
2433                 *data = NULL;
2434
2435         *needed = size;
2436
2437         DEBUG(5,("get_printer_dataex: copy done\n"));
2438
2439         return WERR_OK;
2440 }
2441
2442 /****************************************************************************
2443  Internal routine for removing printerdata
2444  ***************************************************************************/
2445
2446 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2447 {
2448         return delete_printer_data( printer->info_2, key, value );
2449 }
2450
2451 /****************************************************************************
2452  Internal routine for storing printerdata
2453  ***************************************************************************/
2454
2455 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2456                                   uint32 type, uint8 *data, int real_len  )
2457 {
2458         /* the registry objects enforce uniqueness based on value name */
2459
2460         return add_printer_data( printer->info_2, key, value, type, data, real_len );
2461 }
2462
2463 /********************************************************************
2464  GetPrinterData on a printer server Handle.
2465 ********************************************************************/
2466
2467 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2468 {
2469         int i;
2470
2471         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2472
2473         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2474                 *type = REG_DWORD;
2475                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2476                         return WERR_NOMEM;
2477                 SIVAL(*data, 0, 0x00);
2478                 *needed = 0x4;
2479                 return WERR_OK;
2480         }
2481
2482         if (!StrCaseCmp(value, "BeepEnabled")) {
2483                 *type = REG_DWORD;
2484                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2485                         return WERR_NOMEM;
2486                 SIVAL(*data, 0, 0x00);
2487                 *needed = 0x4;
2488                 return WERR_OK;
2489         }
2490
2491         if (!StrCaseCmp(value, "EventLog")) {
2492                 *type = REG_DWORD;
2493                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2494                         return WERR_NOMEM;
2495                 /* formally was 0x1b */
2496                 SIVAL(*data, 0, 0x0);
2497                 *needed = 0x4;
2498                 return WERR_OK;
2499         }
2500
2501         if (!StrCaseCmp(value, "NetPopup")) {
2502                 *type = REG_DWORD;
2503                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2504                         return WERR_NOMEM;
2505                 SIVAL(*data, 0, 0x00);
2506                 *needed = 0x4;
2507                 return WERR_OK;
2508         }
2509
2510         if (!StrCaseCmp(value, "MajorVersion")) {
2511                 *type = REG_DWORD;
2512                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2513                         return WERR_NOMEM;
2514
2515                 /* Windows NT 4.0 seems to not allow uploading of drivers
2516                    to a server that reports 0x3 as the MajorVersion.
2517                    need to investigate more how Win2k gets around this .
2518                    -- jerry */
2519
2520                 if ( RA_WINNT == get_remote_arch() )
2521                         SIVAL(*data, 0, 2);
2522                 else
2523                         SIVAL(*data, 0, 3);
2524
2525                 *needed = 0x4;
2526                 return WERR_OK;
2527         }
2528
2529         if (!StrCaseCmp(value, "MinorVersion")) {
2530                 *type = REG_DWORD;
2531                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2532                         return WERR_NOMEM;
2533                 SIVAL(*data, 0, 0);
2534                 *needed = 0x4;
2535                 return WERR_OK;
2536         }
2537
2538         /* REG_BINARY
2539          *  uint32 size          = 0x114
2540          *  uint32 major         = 5
2541          *  uint32 minor         = [0|1]
2542          *  uint32 build         = [2195|2600]
2543          *  extra unicode string = e.g. "Service Pack 3"
2544          */
2545         if (!StrCaseCmp(value, "OSVersion")) {
2546                 *type = REG_BINARY;
2547                 *needed = 0x114;
2548
2549                 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2550                         return WERR_NOMEM;
2551
2552                 SIVAL(*data, 0, *needed);       /* size */
2553                 SIVAL(*data, 4, 5);             /* Windows 2000 == 5.0 */
2554                 SIVAL(*data, 8, 0);
2555                 SIVAL(*data, 12, 2195);         /* build */
2556
2557                 /* leave extra string empty */
2558
2559                 return WERR_OK;
2560         }
2561
2562
2563         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2564                 const char *string="C:\\PRINTERS";
2565                 *type = REG_SZ;
2566                 *needed = 2*(strlen(string)+1);
2567                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2568                         return WERR_NOMEM;
2569                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2570
2571                 /* it's done by hand ready to go on the wire */
2572                 for (i=0; i<strlen(string); i++) {
2573                         (*data)[2*i]=string[i];
2574                         (*data)[2*i+1]='\0';
2575                 }
2576                 return WERR_OK;
2577         }
2578
2579         if (!StrCaseCmp(value, "Architecture")) {
2580                 const char *string="Windows NT x86";
2581                 *type = REG_SZ;
2582                 *needed = 2*(strlen(string)+1);
2583                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2584                         return WERR_NOMEM;
2585                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2586                 for (i=0; i<strlen(string); i++) {
2587                         (*data)[2*i]=string[i];
2588                         (*data)[2*i+1]='\0';
2589                 }
2590                 return WERR_OK;
2591         }
2592
2593         if (!StrCaseCmp(value, "DsPresent")) {
2594                 *type = REG_DWORD;
2595                 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2596                         return WERR_NOMEM;
2597
2598                 /* only show the publish check box if we are a
2599                    memeber of a AD domain */
2600
2601                 if ( lp_security() == SEC_ADS )
2602                         SIVAL(*data, 0, 0x01);
2603                 else
2604                         SIVAL(*data, 0, 0x00);
2605
2606                 *needed = 0x4;
2607                 return WERR_OK;
2608         }
2609
2610         if (!StrCaseCmp(value, "DNSMachineName")) {
2611                 const char *hostname = get_mydnsfullname();
2612
2613                 if (!hostname)
2614                         return WERR_BADFILE;
2615                 *type = REG_SZ;
2616                 *needed = 2*(strlen(hostname)+1);
2617                 if((*data  = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2618                         return WERR_NOMEM;
2619                 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2620                 for (i=0; i<strlen(hostname); i++) {
2621                         (*data)[2*i]=hostname[i];
2622                         (*data)[2*i+1]='\0';
2623                 }
2624                 return WERR_OK;
2625         }
2626
2627
2628         return WERR_BADFILE;
2629 }
2630
2631 /********************************************************************
2632  * spoolss_getprinterdata
2633  ********************************************************************/
2634
2635 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2636 {
2637         POLICY_HND      *handle = &q_u->handle;
2638         UNISTR2         *valuename = &q_u->valuename;
2639         uint32          in_size = q_u->size;
2640         uint32          *type = &r_u->type;
2641         uint32          *out_size = &r_u->size;
2642         uint8           **data = &r_u->data;
2643         uint32          *needed = &r_u->needed;
2644         WERROR          status;
2645         fstring         value;
2646         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
2647         NT_PRINTER_INFO_LEVEL   *printer = NULL;
2648         int             snum = 0;
2649
2650         /*
2651          * Reminder: when it's a string, the length is in BYTES
2652          * even if UNICODE is negociated.
2653          *
2654          * JFM, 4/19/1999
2655          */
2656
2657         *out_size = in_size;
2658
2659         /* in case of problem, return some default values */
2660
2661         *needed = 0;
2662         *type   = 0;
2663
2664         DEBUG(4,("_spoolss_getprinterdata\n"));
2665
2666         if ( !Printer ) {
2667                 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2668                 status = WERR_BADFID;
2669                 goto done;
2670         }
2671
2672         unistr2_to_ascii(value, valuename, sizeof(value));
2673
2674         if ( Printer->printer_type == SPLHND_SERVER )
2675                 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2676         else
2677         {
2678                 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2679                         status = WERR_BADFID;
2680                         goto done;
2681                 }
2682
2683                 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2684                 if ( !W_ERROR_IS_OK(status) )
2685                         goto done;
2686
2687                 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2688
2689                 if ( strequal(value, "ChangeId") ) {
2690                         *type = REG_DWORD;
2691                         *needed = sizeof(uint32);
2692                         if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2693                                 status = WERR_NOMEM;
2694                                 goto done;
2695                         }
2696                         SIVAL( *data, 0, printer->info_2->changeid );
2697                         status = WERR_OK;
2698                 }
2699                 else
2700                         status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2701         }
2702
2703         if (*needed > *out_size)
2704                 status = WERR_MORE_DATA;
2705
2706 done:
2707         if ( !W_ERROR_IS_OK(status) )
2708         {
2709                 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2710
2711                 /* reply this param doesn't exist */
2712
2713                 if ( *out_size ) {
2714                         if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2715                                 if ( printer )
2716                                         free_a_printer( &printer, 2 );
2717                                 return WERR_NOMEM;
2718                         }
2719                 } else {
2720                         *data = NULL;
2721                 }
2722         }
2723
2724         /* cleanup & exit */
2725
2726         if ( printer )
2727                 free_a_printer( &printer, 2 );
2728
2729         return status;
2730 }
2731
2732 /*********************************************************
2733  Connect to the client machine.
2734 **********************************************************/
2735
2736 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2737                         struct sockaddr_storage *client_ss, const char *remote_machine)
2738 {
2739         NTSTATUS ret;
2740         struct cli_state *the_cli;
2741         struct sockaddr_storage rm_addr;
2742
2743         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2744                 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2745                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2746                         return False;
2747                 }
2748
2749                 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2750                         DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2751                         return False;
2752                 }
2753         } else {
2754                 char addr[INET6_ADDRSTRLEN];
2755                 rm_addr = *client_ss;
2756                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2757                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2758                         addr));
2759         }
2760
2761         /* setup the connection */
2762
2763         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2764                 &rm_addr, 0, "IPC$", "IPC",
2765                 "", /* username */
2766                 "", /* domain */
2767                 "", /* password */
2768                 0, lp_client_signing(), NULL );
2769
2770         if ( !NT_STATUS_IS_OK( ret ) ) {
2771                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2772                         remote_machine ));
2773                 return False;
2774         }
2775
2776         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2777                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2778                 cli_shutdown(the_cli);
2779                 return False;
2780         }
2781
2782         /*
2783          * Ok - we have an anonymous connection to the IPC$ share.
2784          * Now start the NT Domain stuff :-).
2785          */
2786
2787         ret = cli_rpc_pipe_open_noauth(the_cli, &syntax_spoolss, pp_pipe);
2788         if (!NT_STATUS_IS_OK(ret)) {
2789                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2790                         remote_machine, nt_errstr(ret)));
2791                 cli_shutdown(the_cli);
2792                 return False;
2793         }
2794
2795         return True;
2796 }
2797
2798 /***************************************************************************
2799  Connect to the client.
2800 ****************************************************************************/
2801
2802 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2803                                         uint32 localprinter, uint32 type,
2804                                         POLICY_HND *handle, struct sockaddr_storage *client_ss)
2805 {
2806         WERROR result;
2807         NTSTATUS status;
2808
2809         /*
2810          * If it's the first connection, contact the client
2811          * and connect to the IPC$ share anonymously
2812          */
2813         if (smb_connections==0) {
2814                 fstring unix_printer;
2815
2816                 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2817
2818                 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2819                         return False;
2820
2821                 messaging_register(smbd_messaging_context(), NULL,
2822                                    MSG_PRINTER_NOTIFY2,
2823                                    receive_notify2_message_list);
2824                 /* Tell the connections db we're now interested in printer
2825                  * notify messages. */
2826                 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2827         }
2828
2829         /*
2830          * Tell the specific printing tdb we want messages for this printer
2831          * by registering our PID.
2832          */
2833
2834         if (!print_notify_register_pid(snum))
2835                 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2836
2837         smb_connections++;
2838
2839         status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2840                                                  printer,
2841                                                  localprinter,
2842                                                  type,
2843                                                  0,
2844                                                  NULL,
2845                                                  handle,
2846                                                  &result);
2847         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2848                 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2849                         win_errstr(result)));
2850
2851         return (W_ERROR_IS_OK(result));
2852 }
2853
2854 /********************************************************************
2855  * _spoolss_rffpcnex
2856  * ReplyFindFirstPrinterChangeNotifyEx
2857  *
2858  * before replying OK: status=0 a rpc call is made to the workstation
2859  * asking ReplyOpenPrinter
2860  *
2861  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2862  * called from api_spoolss_rffpcnex
2863  ********************************************************************/
2864
2865 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2866 {
2867         POLICY_HND *handle = &q_u->handle;
2868         uint32 flags = q_u->flags;
2869         uint32 options = q_u->options;
2870         UNISTR2 *localmachine = &q_u->localmachine;
2871         uint32 printerlocal = q_u->printerlocal;
2872         int snum = -1;
2873         SPOOL_NOTIFY_OPTION *option = q_u->option;
2874         struct sockaddr_storage client_ss;
2875
2876         /* store the notify value in the printer struct */
2877
2878         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2879
2880         if (!Printer) {
2881                 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2882                 return WERR_BADFID;
2883         }
2884
2885         Printer->notify.flags=flags;
2886         Printer->notify.options=options;
2887         Printer->notify.printerlocal=printerlocal;
2888
2889         if (Printer->notify.option)
2890                 free_spool_notify_option(&Printer->notify.option);
2891
2892         Printer->notify.option=dup_spool_notify_option(option);
2893
2894         unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2895                        sizeof(Printer->notify.localmachine));
2896
2897         /* Connect to the client machine and send a ReplyOpenPrinter */
2898
2899         if ( Printer->printer_type == SPLHND_SERVER)
2900                 snum = -1;
2901         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2902                         !get_printer_snum(p, handle, &snum, NULL) )
2903                 return WERR_BADFID;
2904
2905         if (!interpret_string_addr(&client_ss, p->client_address,
2906                                    AI_NUMERICHOST)) {
2907                 return WERR_SERVER_UNAVAILABLE;
2908         }
2909
2910         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2911                                         Printer->notify.printerlocal, 1,
2912                                         &Printer->notify.client_hnd, &client_ss))
2913                 return WERR_SERVER_UNAVAILABLE;
2914
2915         Printer->notify.client_connected=True;
2916
2917         return WERR_OK;
2918 }
2919
2920 /*******************************************************************
2921  * fill a notify_info_data with the servername
2922  ********************************************************************/
2923
2924 void spoolss_notify_server_name(int snum,
2925                                        struct spoolss_Notify *data,
2926                                        print_queue_struct *queue,
2927                                        NT_PRINTER_INFO_LEVEL *printer,
2928                                        TALLOC_CTX *mem_ctx)
2929 {
2930         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2931 }
2932
2933 /*******************************************************************
2934  * fill a notify_info_data with the printername (not including the servername).
2935  ********************************************************************/
2936
2937 void spoolss_notify_printer_name(int snum,
2938                                         struct spoolss_Notify *data,
2939                                         print_queue_struct *queue,
2940                                         NT_PRINTER_INFO_LEVEL *printer,
2941                                         TALLOC_CTX *mem_ctx)
2942 {
2943         /* the notify name should not contain the \\server\ part */
2944         char *p = strrchr(printer->info_2->printername, '\\');
2945
2946         if (!p) {
2947                 p = printer->info_2->printername;
2948         } else {
2949                 p++;
2950         }
2951
2952         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2953 }
2954
2955 /*******************************************************************
2956  * fill a notify_info_data with the servicename
2957  ********************************************************************/
2958
2959 void spoolss_notify_share_name(int snum,
2960                                       struct spoolss_Notify *data,
2961                                       print_queue_struct *queue,
2962                                       NT_PRINTER_INFO_LEVEL *printer,
2963                                       TALLOC_CTX *mem_ctx)
2964 {
2965         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2966 }
2967
2968 /*******************************************************************
2969  * fill a notify_info_data with the port name
2970  ********************************************************************/
2971
2972 void spoolss_notify_port_name(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->portname);
2979 }
2980
2981 /*******************************************************************
2982  * fill a notify_info_data with the printername
2983  * but it doesn't exist, have to see what to do
2984  ********************************************************************/
2985
2986 void spoolss_notify_driver_name(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->drivername);
2993 }
2994
2995 /*******************************************************************
2996  * fill a notify_info_data with the comment
2997  ********************************************************************/
2998
2999 void spoolss_notify_comment(int snum,
3000                                    struct spoolss_Notify *data,
3001                                    print_queue_struct *queue,
3002                                    NT_PRINTER_INFO_LEVEL *printer,
3003                                    TALLOC_CTX *mem_ctx)
3004 {
3005         char *p;
3006
3007         if (*printer->info_2->comment == '\0') {
3008                 p = lp_comment(snum);
3009         } else {
3010                 p = printer->info_2->comment;
3011         }
3012
3013         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
3014 }
3015
3016 /*******************************************************************
3017  * fill a notify_info_data with the comment
3018  * location = "Room 1, floor 2, building 3"
3019  ********************************************************************/
3020
3021 void spoolss_notify_location(int snum,
3022                                     struct spoolss_Notify *data,
3023                                     print_queue_struct *queue,
3024                                     NT_PRINTER_INFO_LEVEL *printer,
3025                                     TALLOC_CTX *mem_ctx)
3026 {
3027         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
3028 }
3029
3030 /*******************************************************************
3031  * fill a notify_info_data with the device mode
3032  * jfm:xxxx don't to it for know but that's a real problem !!!
3033  ********************************************************************/
3034
3035 static void spoolss_notify_devmode(int snum,
3036                                    struct spoolss_Notify *data,
3037                                    print_queue_struct *queue,
3038                                    NT_PRINTER_INFO_LEVEL *printer,
3039                                    TALLOC_CTX *mem_ctx)
3040 {
3041         /* for a dummy implementation we have to zero the fields */
3042         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
3043 }
3044
3045 /*******************************************************************
3046  * fill a notify_info_data with the separator file name
3047  ********************************************************************/
3048
3049 void spoolss_notify_sepfile(int snum,
3050                                    struct spoolss_Notify *data,
3051                                    print_queue_struct *queue,
3052                                    NT_PRINTER_INFO_LEVEL *printer,
3053                                    TALLOC_CTX *mem_ctx)
3054 {
3055         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
3056 }
3057
3058 /*******************************************************************
3059  * fill a notify_info_data with the print processor
3060  * jfm:xxxx return always winprint to indicate we don't do anything to it
3061  ********************************************************************/
3062
3063 void spoolss_notify_print_processor(int snum,
3064                                            struct spoolss_Notify *data,
3065                                            print_queue_struct *queue,
3066                                            NT_PRINTER_INFO_LEVEL *printer,
3067                                            TALLOC_CTX *mem_ctx)
3068 {
3069         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
3070 }
3071
3072 /*******************************************************************
3073  * fill a notify_info_data with the print processor options
3074  * jfm:xxxx send an empty string
3075  ********************************************************************/
3076
3077 void spoolss_notify_parameters(int snum,
3078                                       struct spoolss_Notify *data,
3079                                       print_queue_struct *queue,
3080                                       NT_PRINTER_INFO_LEVEL *printer,
3081                                       TALLOC_CTX *mem_ctx)
3082 {
3083         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
3084 }
3085
3086 /*******************************************************************
3087  * fill a notify_info_data with the data type
3088  * jfm:xxxx always send RAW as data type
3089  ********************************************************************/
3090
3091 void spoolss_notify_datatype(int snum,
3092                                     struct spoolss_Notify *data,
3093                                     print_queue_struct *queue,
3094                                     NT_PRINTER_INFO_LEVEL *printer,
3095                                     TALLOC_CTX *mem_ctx)
3096 {
3097         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
3098 }
3099
3100 /*******************************************************************
3101  * fill a notify_info_data with the security descriptor
3102  * jfm:xxxx send an null pointer to say no security desc
3103  * have to implement security before !
3104  ********************************************************************/
3105
3106 static void spoolss_notify_security_desc(int snum,
3107                                          struct spoolss_Notify *data,
3108                                          print_queue_struct *queue,
3109                                          NT_PRINTER_INFO_LEVEL *printer,
3110                                          TALLOC_CTX *mem_ctx)
3111 {
3112         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
3113                                           printer->info_2->secdesc_buf->sd_size,
3114                                           printer->info_2->secdesc_buf->sd);
3115 }
3116
3117 /*******************************************************************
3118  * fill a notify_info_data with the attributes
3119  * jfm:xxxx a samba printer is always shared
3120  ********************************************************************/
3121
3122 void spoolss_notify_attributes(int snum,
3123                                       struct spoolss_Notify *data,
3124                                       print_queue_struct *queue,
3125                                       NT_PRINTER_INFO_LEVEL *printer,
3126                                       TALLOC_CTX *mem_ctx)
3127 {
3128         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3129 }
3130
3131 /*******************************************************************
3132  * fill a notify_info_data with the priority
3133  ********************************************************************/
3134
3135 static void spoolss_notify_priority(int snum,
3136                                     struct spoolss_Notify *data,
3137                                     print_queue_struct *queue,
3138                                     NT_PRINTER_INFO_LEVEL *printer,
3139                                     TALLOC_CTX *mem_ctx)
3140 {
3141         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3142 }
3143
3144 /*******************************************************************
3145  * fill a notify_info_data with the default priority
3146  ********************************************************************/
3147
3148 static void spoolss_notify_default_priority(int snum,
3149                                             struct spoolss_Notify *data,
3150                                             print_queue_struct *queue,
3151                                             NT_PRINTER_INFO_LEVEL *printer,
3152                                             TALLOC_CTX *mem_ctx)
3153 {
3154         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3155 }
3156
3157 /*******************************************************************
3158  * fill a notify_info_data with the start time
3159  ********************************************************************/
3160
3161 static void spoolss_notify_start_time(int snum,
3162                                       struct spoolss_Notify *data,
3163                                       print_queue_struct *queue,
3164                                       NT_PRINTER_INFO_LEVEL *printer,
3165                                       TALLOC_CTX *mem_ctx)
3166 {
3167         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3168 }
3169
3170 /*******************************************************************
3171  * fill a notify_info_data with the until time
3172  ********************************************************************/
3173
3174 static void spoolss_notify_until_time(int snum,
3175                                       struct spoolss_Notify *data,
3176                                       print_queue_struct *queue,
3177                                       NT_PRINTER_INFO_LEVEL *printer,
3178                                       TALLOC_CTX *mem_ctx)
3179 {
3180         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3181 }
3182
3183 /*******************************************************************
3184  * fill a notify_info_data with the status
3185  ********************************************************************/
3186
3187 static void spoolss_notify_status(int snum,
3188                                   struct spoolss_Notify *data,
3189                                   print_queue_struct *queue,
3190                                   NT_PRINTER_INFO_LEVEL *printer,
3191                                   TALLOC_CTX *mem_ctx)
3192 {
3193         print_status_struct status;
3194
3195         print_queue_length(snum, &status);
3196         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3197 }
3198
3199 /*******************************************************************
3200  * fill a notify_info_data with the number of jobs queued
3201  ********************************************************************/
3202
3203 void spoolss_notify_cjobs(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, print_queue_length(snum, NULL));
3210 }
3211
3212 /*******************************************************************
3213  * fill a notify_info_data with the average ppm
3214  ********************************************************************/
3215
3216 static void spoolss_notify_average_ppm(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         /* always respond 8 pages per minutes */
3223         /* a little hard ! */
3224         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3225 }
3226
3227 /*******************************************************************
3228  * fill a notify_info_data with username
3229  ********************************************************************/
3230
3231 static void spoolss_notify_username(int snum,
3232                                     struct spoolss_Notify *data,
3233                                     print_queue_struct *queue,
3234                                     NT_PRINTER_INFO_LEVEL *printer,
3235                                     TALLOC_CTX *mem_ctx)
3236 {
3237         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3238 }
3239
3240 /*******************************************************************
3241  * fill a notify_info_data with job status
3242  ********************************************************************/
3243
3244 static void spoolss_notify_job_status(int snum,
3245                                       struct spoolss_Notify *data,
3246                                       print_queue_struct *queue,
3247                                       NT_PRINTER_INFO_LEVEL *printer,
3248                                       TALLOC_CTX *mem_ctx)
3249 {
3250         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3251 }
3252
3253 /*******************************************************************
3254  * fill a notify_info_data with job name
3255  ********************************************************************/
3256
3257 static void spoolss_notify_job_name(int snum,
3258                                     struct spoolss_Notify *data,
3259                                     print_queue_struct *queue,
3260                                     NT_PRINTER_INFO_LEVEL *printer,
3261                                     TALLOC_CTX *mem_ctx)
3262 {
3263         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3264 }
3265
3266 /*******************************************************************
3267  * fill a notify_info_data with job status
3268  ********************************************************************/
3269
3270 static void spoolss_notify_job_status_string(int snum,
3271                                              struct spoolss_Notify *data,
3272                                              print_queue_struct *queue,
3273                                              NT_PRINTER_INFO_LEVEL *printer,
3274                                              TALLOC_CTX *mem_ctx)
3275 {
3276         /*
3277          * Now we're returning job status codes we just return a "" here. JRA.
3278          */
3279
3280         const char *p = "";
3281
3282 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3283         p = "unknown";
3284
3285         switch (queue->status) {
3286         case LPQ_QUEUED:
3287                 p = "Queued";
3288                 break;
3289         case LPQ_PAUSED:
3290                 p = "";    /* NT provides the paused string */
3291                 break;
3292         case LPQ_SPOOLING:
3293                 p = "Spooling";
3294                 break;
3295         case LPQ_PRINTING:
3296                 p = "Printing";
3297                 break;
3298         }
3299 #endif /* NO LONGER NEEDED. */
3300
3301         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3302 }
3303
3304 /*******************************************************************
3305  * fill a notify_info_data with job time
3306  ********************************************************************/
3307
3308 static void spoolss_notify_job_time(int snum,
3309                                     struct spoolss_Notify *data,
3310                                     print_queue_struct *queue,
3311                                     NT_PRINTER_INFO_LEVEL *printer,
3312                                     TALLOC_CTX *mem_ctx)
3313 {
3314         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3315 }
3316
3317 /*******************************************************************
3318  * fill a notify_info_data with job size
3319  ********************************************************************/
3320
3321 static void spoolss_notify_job_size(int snum,
3322                                     struct spoolss_Notify *data,
3323                                     print_queue_struct *queue,
3324                                     NT_PRINTER_INFO_LEVEL *printer,
3325                                     TALLOC_CTX *mem_ctx)
3326 {
3327         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3328 }
3329
3330 /*******************************************************************
3331  * fill a notify_info_data with page info
3332  ********************************************************************/
3333 static void spoolss_notify_total_pages(int snum,
3334                                 struct spoolss_Notify *data,
3335                                 print_queue_struct *queue,
3336                                 NT_PRINTER_INFO_LEVEL *printer,
3337                                 TALLOC_CTX *mem_ctx)
3338 {
3339         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3340 }
3341
3342 /*******************************************************************
3343  * fill a notify_info_data with pages printed info.
3344  ********************************************************************/
3345 static void spoolss_notify_pages_printed(int snum,
3346                                 struct spoolss_Notify *data,
3347                                 print_queue_struct *queue,
3348                                 NT_PRINTER_INFO_LEVEL *printer,
3349                                 TALLOC_CTX *mem_ctx)
3350 {
3351         /* Add code when back-end tracks this */
3352         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3353 }
3354
3355 /*******************************************************************
3356  Fill a notify_info_data with job position.
3357  ********************************************************************/
3358
3359 static void spoolss_notify_job_position(int snum,
3360                                         struct spoolss_Notify *data,
3361                                         print_queue_struct *queue,
3362                                         NT_PRINTER_INFO_LEVEL *printer,
3363                                         TALLOC_CTX *mem_ctx)
3364 {
3365         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3366 }
3367
3368 /*******************************************************************
3369  Fill a notify_info_data with submitted time.
3370  ********************************************************************/
3371
3372 static void spoolss_notify_submitted_time(int snum,
3373                                           struct spoolss_Notify *data,
3374                                           print_queue_struct *queue,
3375                                           NT_PRINTER_INFO_LEVEL *printer,
3376                                           TALLOC_CTX *mem_ctx)
3377 {
3378         data->data.string.string = NULL;
3379         data->data.string.size = 0;
3380
3381         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3382                                &data->data.string.string,
3383                                &data->data.string.size);
3384
3385 }
3386
3387 struct s_notify_info_data_table
3388 {
3389         enum spoolss_NotifyType type;
3390         enum spoolss_Field field;
3391         const char *name;
3392         enum spoolss_NotifyTable variable_type;
3393         void (*fn) (int snum, struct spoolss_Notify *data,
3394                     print_queue_struct *queue,
3395                     NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3396 };
3397
3398 /* A table describing the various print notification constants and
3399    whether the notification data is a pointer to a variable sized
3400    buffer, a one value uint32 or a two value uint32. */
3401
3402 static const struct s_notify_info_data_table notify_info_data_table[] =
3403 {
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME,         "PRINTER_NOTIFY_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME,        "PRINTER_NOTIFY_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME,          "PRINTER_NOTIFY_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME,           "PRINTER_NOTIFY_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME,         "PRINTER_NOTIFY_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT,             "PRINTER_NOTIFY_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION,            "PRINTER_NOTIFY_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE,             "PRINTER_NOTIFY_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE,             "PRINTER_NOTIFY_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR,     "PRINTER_NOTIFY_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS,          "PRINTER_NOTIFY_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE,            "PRINTER_NOTIFY_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES,          "PRINTER_NOTIFY_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY,            "PRINTER_NOTIFY_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME,          "PRINTER_NOTIFY_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3421 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME,          "PRINTER_NOTIFY_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3422 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS,              "PRINTER_NOTIFY_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3423 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING,       "PRINTER_NOTIFY_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3424 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS,               "PRINTER_NOTIFY_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3425 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM,         "PRINTER_NOTIFY_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3426 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES,         "PRINTER_NOTIFY_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3427 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED,       "PRINTER_NOTIFY_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3428 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES,         "PRINTER_NOTIFY_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3429 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED,       "PRINTER_NOTIFY_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3430 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINTER_NAME,            "JOB_NOTIFY_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3431 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_MACHINE_NAME,            "JOB_NOTIFY_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3432 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PORT_NAME,               "JOB_NOTIFY_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3433 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_USER_NAME,               "JOB_NOTIFY_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3434 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_NOTIFY_NAME,             "JOB_NOTIFY_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3435 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DATATYPE,                "JOB_NOTIFY_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3436 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRINT_PROCESSOR,         "JOB_NOTIFY_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3437 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PARAMETERS,              "JOB_NOTIFY_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3438 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DRIVER_NAME,             "JOB_NOTIFY_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3439 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DEVMODE,                 "JOB_NOTIFY_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3440 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS,                  "JOB_NOTIFY_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3441 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_STATUS_STRING,           "JOB_NOTIFY_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3442 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3443 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_DOCUMENT,                "JOB_NOTIFY_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3444 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PRIORITY,                "JOB_NOTIFY_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3445 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_POSITION,                "JOB_NOTIFY_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3446 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_SUBMITTED,               "JOB_NOTIFY_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3447 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_START_TIME,              "JOB_NOTIFY_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3448 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_UNTIL_TIME,              "JOB_NOTIFY_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3449 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TIME,                    "JOB_NOTIFY_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3450 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_PAGES,             "JOB_NOTIFY_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3451 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_PAGES_PRINTED,           "JOB_NOTIFY_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3452 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_TOTAL_BYTES,             "JOB_NOTIFY_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3453 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3454 };
3455
3456 /*******************************************************************
3457  Return the variable_type of info_data structure.
3458 ********************************************************************/
3459
3460 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3461                                                   enum spoolss_Field field)
3462 {
3463         int i=0;
3464
3465         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3466                 if ( (notify_info_data_table[i].type == type) &&
3467                      (notify_info_data_table[i].field == field) ) {
3468                         return notify_info_data_table[i].variable_type;
3469                 }
3470         }
3471
3472         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3473
3474         return 0;
3475 }
3476
3477 /****************************************************************************
3478 ****************************************************************************/
3479
3480 static bool search_notify(uint16 type, uint16 field, int *value)
3481 {
3482         int i;
3483
3484         for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3485                 if (notify_info_data_table[i].type == type &&
3486                     notify_info_data_table[i].field == field &&
3487                     notify_info_data_table[i].fn != NULL) {
3488                         *value = i;
3489                         return True;
3490                 }
3491         }
3492
3493         return False;
3494 }
3495
3496 /****************************************************************************
3497 ****************************************************************************/
3498
3499 void construct_info_data(struct spoolss_Notify *info_data, uint16 type, uint16 field, int id)
3500 {
3501         info_data->type                 = type;
3502         info_data->field                = field;
3503         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3504         info_data->job_id               = id;
3505 }
3506
3507 /*******************************************************************
3508  *
3509  * fill a notify_info struct with info asked
3510  *
3511  ********************************************************************/
3512
3513 static bool construct_notify_printer_info(Printer_entry *print_hnd, struct spoolss_NotifyInfo *info, int
3514                                           snum, SPOOL_NOTIFY_OPTION_TYPE
3515                                           *option_type, uint32 id,
3516                                           TALLOC_CTX *mem_ctx)
3517 {
3518         int field_num,j;
3519         uint16 type;
3520         uint16 field;
3521
3522         struct spoolss_Notify *current_data;
3523         NT_PRINTER_INFO_LEVEL *printer = NULL;
3524         print_queue_struct *queue=NULL;
3525
3526         type=option_type->type;
3527
3528         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3529                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3530                 option_type->count, lp_servicename(snum)));
3531
3532         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3533                 return False;
3534
3535         for(field_num=0; field_num<option_type->count; field_num++) {
3536                 field = option_type->fields[field_num];
3537
3538                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3539
3540                 if (!search_notify(type, field, &j) )
3541                         continue;
3542
3543                 if((info->notifies = SMB_REALLOC_ARRAY(info->notifies, struct spoolss_Notify, info->count+1)) == NULL) {
3544                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3545                         free_a_printer(&printer, 2);
3546                         return False;
3547                 }
3548
3549                 current_data = &info->notifies[info->count];
3550
3551                 construct_info_data(current_data, type, field, id);
3552
3553                 DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
3554                                 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3555
3556                 notify_info_data_table[j].fn(snum, current_data, queue,
3557                                              printer, mem_ctx);
3558
3559                 info->count++;
3560         }
3561
3562         free_a_printer(&printer, 2);
3563         return True;
3564 }
3565
3566 /*******************************************************************
3567  *
3568  * fill a notify_info struct with info asked
3569  *
3570  ********************************************************************/
3571
3572 static bool construct_notify_jobs_info(print_queue_struct *queue,
3573                                        struct spoolss_NotifyInfo *info,
3574                                        NT_PRINTER_INFO_LEVEL *printer,
3575                                        int snum, SPOOL_NOTIFY_OPTION_TYPE
3576                                        *option_type, uint32 id,
3577                                        TALLOC_CTX *mem_ctx)
3578 {
3579         int field_num,j;
3580         uint16 type;
3581         uint16 field;
3582
3583         struct spoolss_Notify *current_data;
3584
3585         DEBUG(4,("construct_notify_jobs_info\n"));
3586
3587         type = option_type->type;
3588
3589         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3590                 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3591                 option_type->count));
3592
3593         for(field_num=0; field_num<option_type->count; field_num++) {
3594                 field = option_type->fields[field_num];
3595
3596                 if (!search_notify(type, field, &j) )
3597                         continue;
3598
3599                 if((info->notifies = SMB_REALLOC_ARRAY(info->notifies, struct spoolss_Notify, info->count+1)) == NULL) {
3600                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3601                         return False;
3602                 }
3603
3604                 current_data=&(info->notifies[info->count]);
3605
3606                 construct_info_data(current_data, type, field, id);
3607                 notify_info_data_table[j].fn(snum, current_data, queue,
3608                                              printer, mem_ctx);
3609                 info->count++;
3610         }
3611
3612         return True;
3613 }
3614
3615 /*
3616  * JFM: The enumeration is not that simple, it's even non obvious.
3617  *
3618  * let's take an example: I want to monitor the PRINTER SERVER for
3619  * the printer's name and the number of jobs currently queued.
3620  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3621  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3622  *
3623  * I have 3 printers on the back of my server.
3624  *
3625  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3626  * structures.
3627  *   Number     Data                    Id
3628  *      1       printer 1 name          1
3629  *      2       printer 1 cjob          1
3630  *      3       printer 2 name          2
3631  *      4       printer 2 cjob          2
3632  *      5       printer 3 name          3
3633  *      6       printer 3 name          3
3634  *
3635  * that's the print server case, the printer case is even worse.
3636  */
3637
3638 /*******************************************************************
3639  *
3640  * enumerate all printers on the printserver
3641  * fill a notify_info struct with info asked
3642  *
3643  ********************************************************************/
3644
3645 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3646                                       struct spoolss_NotifyInfo *info,
3647                                       TALLOC_CTX *mem_ctx)
3648 {
3649         int snum;
3650         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3651         int n_services=lp_numservices();
3652         int i;
3653         SPOOL_NOTIFY_OPTION *option;
3654         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3655
3656         DEBUG(4,("printserver_notify_info\n"));
3657
3658         if (!Printer)
3659                 return WERR_BADFID;
3660
3661         option=Printer->notify.option;
3662
3663         info->version   = 2;
3664         info->notifies  = NULL;
3665         info->count     = 0;
3666
3667         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3668            sending a ffpcn() request first */
3669
3670         if ( !option )
3671                 return WERR_BADFID;
3672
3673         for (i=0; i<option->count; i++) {
3674                 option_type=&(option->ctr.type[i]);
3675
3676                 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3677                         continue;
3678
3679                 for (snum=0; snum<n_services; snum++)
3680                 {
3681                         if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3682                                 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3683                 }
3684         }
3685
3686 #if 0
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 #endif
3701
3702         return WERR_OK;
3703 }
3704
3705 /*******************************************************************
3706  *
3707  * fill a notify_info struct with info asked
3708  *
3709  ********************************************************************/
3710
3711 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, struct spoolss_NotifyInfo *info,
3712                                   TALLOC_CTX *mem_ctx)
3713 {
3714         int snum;
3715         Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3716         int i;
3717         uint32 id;
3718         SPOOL_NOTIFY_OPTION *option;
3719         SPOOL_NOTIFY_OPTION_TYPE *option_type;
3720         int count,j;
3721         print_queue_struct *queue=NULL;
3722         print_status_struct status;
3723
3724         DEBUG(4,("printer_notify_info\n"));
3725
3726         if (!Printer)
3727                 return WERR_BADFID;
3728
3729         option=Printer->notify.option;
3730         id = 0x0;
3731
3732         info->version   = 2;
3733         info->notifies  = NULL;
3734         info->count     = 0;
3735
3736         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3737            sending a ffpcn() request first */
3738
3739         if ( !option )
3740                 return WERR_BADFID;
3741
3742         get_printer_snum(p, hnd, &snum, NULL);
3743
3744         for (i=0; i<option->count; i++) {
3745                 option_type=&option->ctr.type[i];
3746
3747                 switch ( option_type->type ) {
3748                 case PRINTER_NOTIFY_TYPE:
3749                         if(construct_notify_printer_info(Printer, info, snum,
3750                                                          option_type, id,
3751                                                          mem_ctx))
3752                                 id--;
3753                         break;
3754
3755                 case JOB_NOTIFY_TYPE: {
3756                         NT_PRINTER_INFO_LEVEL *printer = NULL;
3757
3758                         count = print_queue_status(snum, &queue, &status);
3759
3760                         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3761                                 goto done;
3762
3763                         for (j=0; j<count; j++) {
3764                                 construct_notify_jobs_info(&queue[j], info,
3765                                                            printer, snum,
3766                                                            option_type,
3767                                                            queue[j].job,
3768                                                            mem_ctx);
3769                         }
3770
3771                         free_a_printer(&printer, 2);
3772
3773                 done:
3774                         SAFE_FREE(queue);
3775                         break;
3776                 }
3777                 }
3778         }
3779
3780         /*
3781          * Debugging information, don't delete.
3782          */
3783         /*
3784         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3785         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3786         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3787
3788         for (i=0; i<info->count; i++) {
3789                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3790                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3791                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3792         }
3793         */
3794         return WERR_OK;
3795 }
3796
3797 /********************************************************************
3798  * spoolss_rfnpcnex
3799  ********************************************************************/
3800
3801 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3802 {
3803         POLICY_HND *handle = &q_u->handle;
3804         SPOOL_NOTIFY_INFO *info = &r_u->info;
3805
3806         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3807         WERROR result = WERR_BADFID;
3808
3809         /* we always have a NOTIFY_INFO struct */
3810         r_u->info_ptr=0x1;
3811
3812         if (!Printer) {
3813                 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3814                          OUR_HANDLE(handle)));
3815                 goto done;
3816         }
3817
3818         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3819
3820         /*
3821          *      We are now using the change value, and
3822          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3823          *      I don't have a global notification system, I'm sending back all the
3824          *      informations even when _NOTHING_ has changed.
3825          */
3826
3827         /* We need to keep track of the change value to send back in
3828            RRPCN replies otherwise our updates are ignored. */
3829
3830         Printer->notify.fnpcn = True;
3831
3832         if (Printer->notify.client_connected) {
3833                 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3834                 Printer->notify.change = q_u->change;
3835         }
3836
3837         /* just ignore the SPOOL_NOTIFY_OPTION */
3838
3839         switch (Printer->printer_type) {
3840                 case SPLHND_SERVER:
3841                         result = printserver_notify_info(p, handle, info, p->mem_ctx);
3842                         break;
3843
3844                 case SPLHND_PRINTER:
3845                         result = printer_notify_info(p, handle, info, p->mem_ctx);
3846                         break;
3847         }
3848
3849         Printer->notify.fnpcn = False;
3850
3851 done:
3852         return result;
3853 }
3854
3855 /********************************************************************
3856  * construct_printer_info_0
3857  * fill a printer_info_0 struct
3858  ********************************************************************/
3859
3860 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3861 {
3862         char *chaine = NULL;
3863         int count;
3864         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3865         counter_printer_0 *session_counter;
3866         uint32 global_counter;
3867         struct tm *t;
3868         time_t setuptime;
3869         print_status_struct status;
3870         TALLOC_CTX *ctx = talloc_tos();
3871
3872         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3873                 return False;
3874
3875         init_unistr(&printer->printername, ntprinter->info_2->printername);
3876
3877         chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3878         if (!chaine) {
3879                 free_a_printer(&ntprinter,2);
3880                 return false;
3881         }
3882
3883         count = print_queue_length(snum, &status);
3884
3885         /* check if we already have a counter for this printer */
3886         for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3887                 if (session_counter->snum == snum)
3888                         break;
3889         }
3890
3891         init_unistr(&printer->servername, chaine);
3892
3893         /* it's the first time, add it to the list */
3894         if (session_counter==NULL) {
3895                 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3896                         free_a_printer(&ntprinter, 2);
3897                         return False;
3898                 }
3899                 ZERO_STRUCTP(session_counter);
3900                 session_counter->snum=snum;
3901                 session_counter->counter=0;
3902                 DLIST_ADD(counter_list, session_counter);
3903         }
3904
3905         /* increment it */
3906         session_counter->counter++;
3907
3908         /* JFM:
3909          * the global_counter should be stored in a TDB as it's common to all the clients
3910          * and should be zeroed on samba startup
3911          */
3912         global_counter=session_counter->counter;
3913         printer->cjobs = count;
3914         printer->total_jobs = 0;
3915         printer->total_bytes = 0;
3916
3917         setuptime = (time_t)ntprinter->info_2->setuptime;
3918         t=gmtime(&setuptime);
3919
3920         printer->year = t->tm_year+1900;
3921         printer->month = t->tm_mon+1;
3922         printer->dayofweek = t->tm_wday;
3923         printer->day = t->tm_mday;
3924         printer->hour = t->tm_hour;
3925         printer->minute = t->tm_min;
3926         printer->second = t->tm_sec;
3927         printer->milliseconds = 0;
3928
3929         printer->global_counter = global_counter;
3930         printer->total_pages = 0;
3931
3932         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3933         printer->major_version = 0x0005;        /* NT 5 */
3934         printer->build_version = 0x0893;        /* build 2195 */
3935
3936         printer->unknown7 = 0x1;
3937         printer->unknown8 = 0x0;
3938         printer->unknown9 = 0x0;
3939         printer->session_counter = session_counter->counter;
3940         printer->unknown11 = 0x0;
3941         printer->printer_errors = 0x0;          /* number of print failure */
3942         printer->unknown13 = 0x0;
3943         printer->unknown14 = 0x1;
3944         printer->unknown15 = 0x024a;            /* 586 Pentium ? */
3945         printer->unknown16 =  0x0;
3946         printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3947         printer->unknown18 =  0x0;
3948         printer->status = nt_printq_status(status.status);
3949         printer->unknown20 =  0x0;
3950         printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3951         printer->unknown22 = 0x0;
3952         printer->unknown23 = 0x6;               /* 6  ???*/
3953         printer->unknown24 = 0;                 /* unknown 24 to 26 are always 0 */
3954         printer->unknown25 = 0;
3955         printer->unknown26 = 0;
3956         printer->unknown27 = 0;
3957         printer->unknown28 = 0;
3958         printer->unknown29 = 0;
3959
3960         free_a_printer(&ntprinter,2);
3961         return (True);
3962 }
3963
3964 /********************************************************************
3965  * construct_printer_info_1
3966  * fill a printer_info_1 struct
3967  ********************************************************************/
3968 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3969 {
3970         char *chaine = NULL;
3971         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3972         TALLOC_CTX *ctx = talloc_tos();
3973
3974         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3975                 return false;
3976
3977         printer->flags=flags;
3978
3979         if (*ntprinter->info_2->comment == '\0') {
3980                 init_unistr(&printer->comment, lp_comment(snum));
3981                 chaine = talloc_asprintf(ctx,
3982                                 "%s,%s,%s", ntprinter->info_2->printername,
3983                                 ntprinter->info_2->drivername, lp_comment(snum));
3984         }
3985         else {
3986                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3987                 chaine = talloc_asprintf(ctx,
3988                                 "%s,%s,%s", ntprinter->info_2->printername,
3989                                 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3990         }
3991
3992         if (!chaine) {
3993                 free_a_printer(&ntprinter,2);
3994                 return false;
3995         }
3996
3997         init_unistr(&printer->description, chaine);
3998         init_unistr(&printer->name, ntprinter->info_2->printername);
3999
4000         free_a_printer(&ntprinter,2);
4001
4002         return True;
4003 }
4004
4005 /****************************************************************************
4006  Free a DEVMODE struct.
4007 ****************************************************************************/
4008
4009 static void free_dev_mode(DEVICEMODE *dev)
4010 {
4011         if (dev == NULL)
4012                 return;
4013
4014         SAFE_FREE(dev->dev_private);
4015         SAFE_FREE(dev);
4016 }
4017
4018
4019 /****************************************************************************
4020  Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers
4021  should be valid upon entry
4022 ****************************************************************************/
4023
4024 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4025 {
4026         if ( !devmode || !ntdevmode )
4027                 return False;
4028
4029         init_unistr(&devmode->devicename, ntdevmode->devicename);
4030
4031         init_unistr(&devmode->formname, ntdevmode->formname);
4032
4033         devmode->specversion      = ntdevmode->specversion;
4034         devmode->driverversion    = ntdevmode->driverversion;
4035         devmode->size             = ntdevmode->size;
4036         devmode->driverextra      = ntdevmode->driverextra;
4037         devmode->fields           = ntdevmode->fields;
4038
4039         devmode->orientation      = ntdevmode->orientation;
4040         devmode->papersize        = ntdevmode->papersize;
4041         devmode->paperlength      = ntdevmode->paperlength;
4042         devmode->paperwidth       = ntdevmode->paperwidth;
4043         devmode->scale            = ntdevmode->scale;
4044         devmode->copies           = ntdevmode->copies;
4045         devmode->defaultsource    = ntdevmode->defaultsource;
4046         devmode->printquality     = ntdevmode->printquality;
4047         devmode->color            = ntdevmode->color;
4048         devmode->duplex           = ntdevmode->duplex;
4049         devmode->yresolution      = ntdevmode->yresolution;
4050         devmode->ttoption         = ntdevmode->ttoption;
4051         devmode->collate          = ntdevmode->collate;
4052         devmode->icmmethod        = ntdevmode->icmmethod;
4053         devmode->icmintent        = ntdevmode->icmintent;
4054         devmode->mediatype        = ntdevmode->mediatype;
4055         devmode->dithertype       = ntdevmode->dithertype;
4056
4057         if (ntdevmode->nt_dev_private != NULL) {
4058                 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4059                         return False;
4060         }
4061
4062         return True;
4063 }
4064
4065 /****************************************************************************
4066  Create a DEVMODE struct. Returns malloced memory.
4067 ****************************************************************************/
4068
4069 DEVICEMODE *construct_dev_mode(const char *servicename)
4070 {
4071         NT_PRINTER_INFO_LEVEL   *printer = NULL;
4072         DEVICEMODE              *devmode = NULL;
4073
4074         DEBUG(7,("construct_dev_mode\n"));
4075
4076         DEBUGADD(8,("getting printer characteristics\n"));
4077
4078         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4079                 return NULL;
4080
4081         if ( !printer->info_2->devmode ) {
4082                 DEBUG(5, ("BONG! There was no device mode!\n"));
4083                 goto done;
4084         }
4085
4086         if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4087                 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4088                 goto done;
4089         }
4090
4091         ZERO_STRUCTP(devmode);
4092
4093         DEBUGADD(8,("loading DEVICEMODE\n"));
4094
4095         if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4096                 free_dev_mode( devmode );
4097                 devmode = NULL;
4098         }
4099
4100 done:
4101         free_a_printer(&printer,2);
4102
4103         return devmode;
4104 }
4105
4106 /********************************************************************
4107  * construct_printer_info_2
4108  * fill a printer_info_2 struct
4109  ********************************************************************/
4110
4111 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4112 {
4113         int count;
4114         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4115
4116         print_status_struct status;
4117
4118         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4119                 return False;
4120
4121         count = print_queue_length(snum, &status);
4122
4123         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4124         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4125         init_unistr(&printer->sharename, lp_servicename(snum));                 /* sharename */
4126         init_unistr(&printer->portname, ntprinter->info_2->portname);                   /* port */
4127         init_unistr(&printer->drivername, ntprinter->info_2->drivername);       /* drivername */
4128
4129         if (*ntprinter->info_2->comment == '\0')
4130                 init_unistr(&printer->comment, lp_comment(snum));                       /* comment */
4131         else
4132                 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4133
4134         init_unistr(&printer->location, ntprinter->info_2->location);           /* location */
4135         init_unistr(&printer->sepfile, ntprinter->info_2->sepfile);             /* separator file */
4136         init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4137         init_unistr(&printer->datatype, ntprinter->info_2->datatype);           /* datatype */
4138         init_unistr(&printer->parameters, ntprinter->info_2->parameters);       /* parameters (of print processor) */
4139
4140         printer->attributes = ntprinter->info_2->attributes;
4141
4142         printer->priority = ntprinter->info_2->priority;                                /* priority */
4143         printer->defaultpriority = ntprinter->info_2->default_priority;         /* default priority */
4144         printer->starttime = ntprinter->info_2->starttime;                      /* starttime */
4145         printer->untiltime = ntprinter->info_2->untiltime;                      /* untiltime */
4146         printer->status = nt_printq_status(status.status);                      /* status */
4147         printer->cjobs = count;                                                 /* jobs */
4148         printer->averageppm = ntprinter->info_2->averageppm;                    /* average pages per minute */
4149
4150         if ( !(printer->devmode = construct_dev_mode(
4151                        lp_const_servicename(snum))) )
4152                 DEBUG(8, ("Returning NULL Devicemode!\n"));
4153
4154         printer->secdesc = NULL;
4155
4156         if ( ntprinter->info_2->secdesc_buf
4157                 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4158         {
4159                 /* don't use talloc_steal() here unless you do a deep steal of all
4160                    the SEC_DESC members */
4161
4162                 printer->secdesc = dup_sec_desc( talloc_tos(),
4163                         ntprinter->info_2->secdesc_buf->sd );
4164         }
4165
4166         free_a_printer(&ntprinter, 2);
4167
4168         return True;
4169 }
4170
4171 /********************************************************************
4172  * construct_printer_info_3
4173  * fill a printer_info_3 struct
4174  ********************************************************************/
4175
4176 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4177 {
4178         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4179         PRINTER_INFO_3 *printer = NULL;
4180
4181         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4182                 return False;
4183
4184         *pp_printer = NULL;
4185         if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4186                 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4187                 free_a_printer(&ntprinter, 2);
4188                 return False;
4189         }
4190
4191         ZERO_STRUCTP(printer);
4192
4193         /* These are the components of the SD we are returning. */
4194
4195         if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4196                 /* don't use talloc_steal() here unless you do a deep steal of all
4197                    the SEC_DESC members */
4198
4199                 printer->secdesc = dup_sec_desc( talloc_tos(),
4200                         ntprinter->info_2->secdesc_buf->sd );
4201         }
4202
4203         free_a_printer(&ntprinter, 2);
4204
4205         *pp_printer = printer;
4206         return True;
4207 }
4208
4209 /********************************************************************
4210  * construct_printer_info_4
4211  * fill a printer_info_4 struct
4212  ********************************************************************/
4213
4214 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4215 {
4216         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4217
4218         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4219                 return False;
4220
4221         init_unistr(&printer->printername, ntprinter->info_2->printername);                             /* printername*/
4222         init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4223         printer->attributes = ntprinter->info_2->attributes;
4224
4225         free_a_printer(&ntprinter, 2);
4226         return True;
4227 }
4228
4229 /********************************************************************
4230  * construct_printer_info_5
4231  * fill a printer_info_5 struct
4232  ********************************************************************/
4233
4234 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4235 {
4236         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4237
4238         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4239                 return False;
4240
4241         init_unistr(&printer->printername, ntprinter->info_2->printername);
4242         init_unistr(&printer->portname, ntprinter->info_2->portname);
4243         printer->attributes = ntprinter->info_2->attributes;
4244
4245         /* these two are not used by NT+ according to MSDN */
4246
4247         printer->device_not_selected_timeout = 0x0;  /* have seen 0x3a98 */
4248         printer->transmission_retry_timeout  = 0x0;  /* have seen 0xafc8 */
4249
4250         free_a_printer(&ntprinter, 2);
4251
4252         return True;
4253 }
4254
4255 /********************************************************************
4256  * construct_printer_info_6
4257  * fill a printer_info_6 struct
4258  ********************************************************************/
4259
4260 static bool construct_printer_info_6(Printer_entry *print_hnd,
4261                                      PRINTER_INFO_6 *printer,
4262                                      int snum)
4263 {
4264         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4265         int count;
4266         print_status_struct status;
4267
4268         if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4269                                          lp_const_servicename(snum))))
4270                 return False;
4271
4272         count = print_queue_length(snum, &status);
4273
4274         printer->status = nt_printq_status(status.status);
4275
4276         free_a_printer(&ntprinter, 2);
4277
4278         return True;
4279 }
4280
4281 /********************************************************************
4282  * construct_printer_info_7
4283  * fill a printer_info_7 struct
4284  ********************************************************************/
4285
4286 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4287 {
4288         char *guid_str = NULL;
4289         struct GUID guid;
4290
4291         if (is_printer_published(print_hnd, snum, &guid)) {
4292                 if (asprintf(&guid_str, "{%s}",
4293                              GUID_string(talloc_tos(), &guid)) == -1) {
4294                         return false;
4295                 }
4296                 strupper_m(guid_str);
4297                 init_unistr(&printer->guid, guid_str);
4298                 SAFE_FREE(guid_str);
4299                 printer->action = SPOOL_DS_PUBLISH;
4300         } else {
4301                 init_unistr(&printer->guid, "");
4302                 printer->action = SPOOL_DS_UNPUBLISH;
4303         }
4304
4305         return True;
4306 }
4307
4308 /********************************************************************
4309  Spoolss_enumprinters.
4310 ********************************************************************/
4311
4312 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4313 {
4314         int snum;
4315         int i;
4316         int n_services=lp_numservices();
4317         PRINTER_INFO_1 *printers=NULL;
4318         PRINTER_INFO_1 current_prt;
4319         WERROR result = WERR_OK;
4320
4321         DEBUG(4,("enum_all_printers_info_1\n"));
4322
4323         for (snum=0; snum<n_services; snum++) {
4324                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4325                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4326
4327                         if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4328                                 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4329                                         DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4330                                         *returned=0;
4331                                         return WERR_NOMEM;
4332                                 }
4333                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4334
4335                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4336                                 (*returned)++;
4337                         }
4338                 }
4339         }
4340
4341         /* check the required size. */
4342         for (i=0; i<*returned; i++)
4343                 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4344
4345         if (*needed > offered) {
4346                 result = WERR_INSUFFICIENT_BUFFER;
4347                 goto out;
4348         }
4349
4350         if (!rpcbuf_alloc_size(buffer, *needed)) {
4351                 result = WERR_NOMEM;
4352                 goto out;
4353         }
4354
4355         /* fill the buffer with the structures */
4356         for (i=0; i<*returned; i++)
4357                 smb_io_printer_info_1("", buffer, &printers[i], 0);
4358
4359 out:
4360         /* clear memory */
4361
4362         SAFE_FREE(printers);
4363
4364         if ( !W_ERROR_IS_OK(result) )
4365                 *returned = 0;
4366
4367         return result;
4368 }
4369
4370 /********************************************************************
4371  enum_all_printers_info_1_local.
4372 *********************************************************************/
4373
4374 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4375 {
4376         DEBUG(4,("enum_all_printers_info_1_local\n"));
4377
4378         return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4379 }
4380
4381 /********************************************************************
4382  enum_all_printers_info_1_name.
4383 *********************************************************************/
4384
4385 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4386 {
4387         char *s = name;
4388
4389         DEBUG(4,("enum_all_printers_info_1_name\n"));
4390
4391         if ((name[0] == '\\') && (name[1] == '\\'))
4392                 s = name + 2;
4393
4394         if (is_myname_or_ipaddr(s)) {
4395                 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4396         }
4397         else
4398                 return WERR_INVALID_NAME;
4399 }
4400
4401 #if 0   /* JERRY -- disabled for now.  Don't think this is used, tested, or correct */
4402 /********************************************************************
4403  enum_all_printers_info_1_remote.
4404 *********************************************************************/
4405
4406 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4407 {
4408         PRINTER_INFO_1 *printer;
4409         fstring printername;
4410         fstring desc;
4411         fstring comment;
4412         DEBUG(4,("enum_all_printers_info_1_remote\n"));
4413         WERROR result = WERR_OK;
4414
4415         /* JFM: currently it's more a place holder than anything else.
4416          * In the spooler world there is a notion of server registration.
4417          * the print servers are registered on the PDC (in the same domain)
4418          *
4419          * We should have a TDB here. The registration is done thru an
4420          * undocumented RPC call.
4421          */
4422
4423         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4424                 return WERR_NOMEM;
4425
4426         *returned=1;
4427
4428         slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4429         slprintf(desc, sizeof(desc)-1,"%s", name);
4430         slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4431
4432         init_unistr(&printer->description, desc);
4433         init_unistr(&printer->name, printername);
4434         init_unistr(&printer->comment, comment);
4435         printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4436
4437         /* check the required size. */
4438         *needed += spoolss_size_printer_info_1(printer);
4439
4440         if (*needed > offered) {
4441                 result = WERR_INSUFFICIENT_BUFFER;
4442                 goto out;
4443         }
4444
4445         if (!rpcbuf_alloc_size(buffer, *needed)) {
4446                 result = WERR_NOMEM;
4447                 goto out;
4448         }
4449
4450         /* fill the buffer with the structures */
4451         smb_io_printer_info_1("", buffer, printer, 0);
4452
4453 out:
4454         /* clear memory */
4455         SAFE_FREE(printer);
4456
4457         if ( !W_ERROR_IS_OK(result) )
4458                 *returned = 0;
4459
4460         return result;
4461 }
4462
4463 #endif
4464
4465 /********************************************************************
4466  enum_all_printers_info_1_network.
4467 *********************************************************************/
4468
4469 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 {
4471         char *s = name;
4472
4473         DEBUG(4,("enum_all_printers_info_1_network\n"));
4474
4475         /* If we respond to a enum_printers level 1 on our name with flags
4476            set to PRINTER_ENUM_REMOTE with a list of printers then these
4477            printers incorrectly appear in the APW browse list.
4478            Specifically the printers for the server appear at the workgroup
4479            level where all the other servers in the domain are
4480            listed. Windows responds to this call with a
4481            WERR_CAN_NOT_COMPLETE so we should do the same. */
4482
4483         if (name[0] == '\\' && name[1] == '\\')
4484                  s = name + 2;
4485
4486         if (is_myname_or_ipaddr(s))
4487                  return WERR_CAN_NOT_COMPLETE;
4488
4489         return enum_all_printers_info_1(PRINTER_ENUM_NAME, buffer, offered, needed, returned);
4490 }
4491
4492 /********************************************************************
4493  * api_spoolss_enumprinters
4494  *
4495  * called from api_spoolss_enumprinters (see this to understand)
4496  ********************************************************************/
4497
4498 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4499 {
4500         int snum;
4501         int i;
4502         int n_services=lp_numservices();
4503         PRINTER_INFO_2 *printers=NULL;
4504         PRINTER_INFO_2 current_prt;
4505         WERROR result = WERR_OK;
4506
4507         *returned = 0;
4508
4509         for (snum=0; snum<n_services; snum++) {
4510                 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4511                         DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4512
4513                         if (construct_printer_info_2(NULL, &current_prt, snum)) {
4514                                 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4515                                         DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4516                                         *returned = 0;
4517                                         return WERR_NOMEM;
4518                                 }
4519
4520                                 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4521
4522                                 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4523
4524                                 (*returned)++;
4525                         }
4526                 }
4527         }
4528
4529         /* check the required size. */
4530         for (i=0; i<*returned; i++)
4531                 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4532
4533         if (*needed > offered) {
4534                 result = WERR_INSUFFICIENT_BUFFER;
4535                 goto out;
4536         }
4537
4538         if (!rpcbuf_alloc_size(buffer, *needed)) {
4539                 result = WERR_NOMEM;
4540                 goto out;
4541         }
4542
4543         /* fill the buffer with the structures */
4544         for (i=0; i<*returned; i++)
4545                 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4546
4547 out:
4548         /* clear memory */
4549
4550         for (i=0; i<*returned; i++)
4551                 free_devmode(printers[i].devmode);
4552
4553         SAFE_FREE(printers);
4554
4555         if ( !W_ERROR_IS_OK(result) )
4556                 *returned = 0;
4557
4558         return result;
4559 }
4560
4561 /********************************************************************
4562  * handle enumeration of printers at level 1
4563  ********************************************************************/
4564
4565 static WERROR enumprinters_level1( uint32 flags, fstring name,
4566                                  RPC_BUFFER *buffer, uint32 offered,
4567                                  uint32 *needed, uint32 *returned)
4568 {
4569         /* Not all the flags are equals */
4570
4571         if (flags & PRINTER_ENUM_LOCAL)
4572                 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4573
4574         if (flags & PRINTER_ENUM_NAME)
4575                 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4576
4577 #if 0   /* JERRY - disabled for now */
4578         if (flags & PRINTER_ENUM_REMOTE)
4579                 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4580 #endif
4581
4582         if (flags & PRINTER_ENUM_NETWORK)
4583                 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4584
4585         return WERR_OK; /* NT4sp5 does that */
4586 }
4587
4588 /********************************************************************
4589  * handle enumeration of printers at level 2
4590  ********************************************************************/
4591
4592 static WERROR enumprinters_level2( uint32 flags, const char *servername,
4593                                  RPC_BUFFER *buffer, uint32 offered,
4594                                  uint32 *needed, uint32 *returned)
4595 {
4596         if (flags & PRINTER_ENUM_LOCAL) {
4597                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4598         }
4599
4600         if (flags & PRINTER_ENUM_NAME) {
4601                 if (is_myname_or_ipaddr(canon_servername(servername)))
4602                         return enum_all_printers_info_2(buffer, offered, needed, returned);
4603                 else
4604                         return WERR_INVALID_NAME;
4605         }
4606
4607         if (flags & PRINTER_ENUM_REMOTE)
4608                 return WERR_UNKNOWN_LEVEL;
4609
4610         return WERR_OK;
4611 }
4612
4613 /********************************************************************
4614  * handle enumeration of printers at level 5
4615  ********************************************************************/
4616
4617 static WERROR enumprinters_level5( uint32 flags, const char *servername,
4618                                  RPC_BUFFER *buffer, uint32 offered,
4619                                  uint32 *needed, uint32 *returned)
4620 {
4621 /*      return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4622         return WERR_OK;
4623 }
4624
4625 /********************************************************************
4626  * api_spoolss_enumprinters
4627  *
4628  * called from api_spoolss_enumprinters (see this to understand)
4629  ********************************************************************/
4630
4631 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4632 {
4633         uint32 flags = q_u->flags;
4634         UNISTR2 *servername = &q_u->servername;
4635         uint32 level = q_u->level;
4636         RPC_BUFFER *buffer = NULL;
4637         uint32 offered = q_u->offered;
4638         uint32 *needed = &r_u->needed;
4639         uint32 *returned = &r_u->returned;
4640
4641         fstring name;
4642
4643         /* that's an [in out] buffer */
4644
4645         if (!q_u->buffer && (offered!=0)) {
4646                 return WERR_INVALID_PARAM;
4647         }
4648
4649         if (offered > MAX_RPC_DATA_SIZE) {
4650                 return WERR_INVALID_PARAM;
4651         }
4652
4653         rpcbuf_move(q_u->buffer, &r_u->buffer);
4654         buffer = r_u->buffer;
4655
4656         DEBUG(4,("_spoolss_enumprinters\n"));
4657
4658         *needed=0;
4659         *returned=0;
4660
4661         /*
4662          * Level 1:
4663          *          flags==PRINTER_ENUM_NAME
4664          *           if name=="" then enumerates all printers
4665          *           if name!="" then enumerate the printer
4666          *          flags==PRINTER_ENUM_REMOTE
4667          *          name is NULL, enumerate printers
4668          * Level 2: name!="" enumerates printers, name can't be NULL
4669          * Level 3: doesn't exist
4670          * Level 4: does a local registry lookup
4671          * Level 5: same as Level 2
4672          */
4673
4674         unistr2_to_ascii(name, servername, sizeof(name));
4675         strupper_m(name);
4676
4677         switch (level) {
4678         case 1:
4679                 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4680         case 2:
4681                 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4682         case 5:
4683                 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4684         case 3:
4685         case 4:
4686                 break;
4687         }
4688         return WERR_UNKNOWN_LEVEL;
4689 }
4690
4691 /****************************************************************************
4692 ****************************************************************************/
4693
4694 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4695 {
4696         PRINTER_INFO_0 *printer=NULL;
4697         WERROR result = WERR_OK;
4698
4699         if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4700                 return WERR_NOMEM;
4701
4702         construct_printer_info_0(print_hnd, printer, snum);
4703
4704         /* check the required size. */
4705         *needed += spoolss_size_printer_info_0(printer);
4706
4707         if (*needed > offered) {
4708                 result = WERR_INSUFFICIENT_BUFFER;
4709                 goto out;
4710         }
4711
4712         if (!rpcbuf_alloc_size(buffer, *needed)) {
4713                 result = WERR_NOMEM;
4714                 goto out;
4715         }
4716
4717         /* fill the buffer with the structures */
4718         smb_io_printer_info_0("", buffer, printer, 0);
4719
4720 out:
4721         /* clear memory */
4722
4723         SAFE_FREE(printer);
4724
4725         return result;
4726 }
4727
4728 /****************************************************************************
4729 ****************************************************************************/
4730
4731 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4732 {
4733         PRINTER_INFO_1 *printer=NULL;
4734         WERROR result = WERR_OK;
4735
4736         if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4737                 return WERR_NOMEM;
4738
4739         construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4740
4741         /* check the required size. */
4742         *needed += spoolss_size_printer_info_1(printer);
4743
4744         if (*needed > offered) {
4745                 result = WERR_INSUFFICIENT_BUFFER;
4746                 goto out;
4747         }
4748
4749         if (!rpcbuf_alloc_size(buffer, *needed)) {
4750                 result = WERR_NOMEM;
4751                 goto out;
4752         }
4753
4754         /* fill the buffer with the structures */
4755         smb_io_printer_info_1("", buffer, printer, 0);
4756
4757 out:
4758         /* clear memory */
4759         SAFE_FREE(printer);
4760
4761         return result;
4762 }
4763
4764 /****************************************************************************
4765 ****************************************************************************/
4766
4767 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4768 {
4769         PRINTER_INFO_2 *printer=NULL;
4770         WERROR result = WERR_OK;
4771
4772         if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4773                 return WERR_NOMEM;
4774
4775         construct_printer_info_2(print_hnd, printer, snum);
4776
4777         /* check the required size. */
4778         *needed += spoolss_size_printer_info_2(printer);
4779
4780         if (*needed > offered) {
4781                 result = WERR_INSUFFICIENT_BUFFER;
4782                 goto out;
4783         }
4784
4785         if (!rpcbuf_alloc_size(buffer, *needed)) {
4786                 result = WERR_NOMEM;
4787                 goto out;
4788         }
4789
4790         /* fill the buffer with the structures */
4791         if (!smb_io_printer_info_2("", buffer, printer, 0))
4792                 result = WERR_NOMEM;
4793
4794 out:
4795         /* clear memory */
4796         free_printer_info_2(printer);
4797
4798         return result;
4799 }
4800
4801 /****************************************************************************
4802 ****************************************************************************/
4803
4804 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4805 {
4806         PRINTER_INFO_3 *printer=NULL;
4807         WERROR result = WERR_OK;
4808
4809         if (!construct_printer_info_3(print_hnd, &printer, snum))
4810                 return WERR_NOMEM;
4811
4812         /* check the required size. */
4813         *needed += spoolss_size_printer_info_3(printer);
4814
4815         if (*needed > offered) {
4816                 result = WERR_INSUFFICIENT_BUFFER;
4817                 goto out;
4818         }
4819
4820         if (!rpcbuf_alloc_size(buffer, *needed)) {
4821                 result = WERR_NOMEM;
4822                 goto out;
4823         }
4824
4825         /* fill the buffer with the structures */
4826         smb_io_printer_info_3("", buffer, printer, 0);
4827
4828 out:
4829         /* clear memory */
4830         free_printer_info_3(printer);
4831
4832         return result;
4833 }
4834
4835 /****************************************************************************
4836 ****************************************************************************/
4837
4838 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4839 {
4840         PRINTER_INFO_4 *printer=NULL;
4841         WERROR result = WERR_OK;
4842
4843         if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4844                 return WERR_NOMEM;
4845
4846         if (!construct_printer_info_4(print_hnd, printer, snum)) {
4847                 SAFE_FREE(printer);
4848                 return WERR_NOMEM;
4849         }
4850
4851         /* check the required size. */
4852         *needed += spoolss_size_printer_info_4(printer);
4853
4854         if (*needed > offered) {
4855                 result = WERR_INSUFFICIENT_BUFFER;
4856                 goto out;
4857         }
4858
4859         if (!rpcbuf_alloc_size(buffer, *needed)) {
4860                 result = WERR_NOMEM;
4861                 goto out;
4862         }
4863
4864         /* fill the buffer with the structures */
4865         smb_io_printer_info_4("", buffer, printer, 0);
4866
4867 out:
4868         /* clear memory */
4869         free_printer_info_4(printer);
4870
4871         return result;
4872 }
4873
4874 /****************************************************************************
4875 ****************************************************************************/
4876
4877 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4878 {
4879         PRINTER_INFO_5 *printer=NULL;
4880         WERROR result = WERR_OK;
4881
4882         if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4883                 return WERR_NOMEM;
4884
4885         if (!construct_printer_info_5(print_hnd, printer, snum)) {
4886                 free_printer_info_5(printer);
4887                 return WERR_NOMEM;
4888         }
4889
4890         /* check the required size. */
4891         *needed += spoolss_size_printer_info_5(printer);
4892
4893         if (*needed > offered) {
4894                 result = WERR_INSUFFICIENT_BUFFER;
4895                 goto out;
4896         }
4897
4898         if (!rpcbuf_alloc_size(buffer, *needed)) {
4899                 result = WERR_NOMEM;
4900                 goto out;
4901         }
4902
4903         /* fill the buffer with the structures */
4904         smb_io_printer_info_5("", buffer, printer, 0);
4905
4906 out:
4907         /* clear memory */
4908         free_printer_info_5(printer);
4909
4910         return result;
4911 }
4912
4913 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4914                                  int snum,
4915                                  RPC_BUFFER *buffer, uint32 offered,
4916                                  uint32 *needed)
4917 {
4918         PRINTER_INFO_6 *printer;
4919         WERROR result = WERR_OK;
4920
4921         if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4922                 return WERR_NOMEM;
4923         }
4924
4925         if (!construct_printer_info_6(print_hnd, printer, snum)) {
4926                 free_printer_info_6(printer);
4927                 return WERR_NOMEM;
4928         }
4929
4930         /* check the required size. */
4931         *needed += spoolss_size_printer_info_6(printer);
4932
4933         if (*needed > offered) {
4934                 result = WERR_INSUFFICIENT_BUFFER;
4935                 goto out;
4936         }
4937
4938         if (!rpcbuf_alloc_size(buffer, *needed)) {
4939                 result = WERR_NOMEM;
4940                 goto out;
4941         }
4942
4943         /* fill the buffer with the structures */
4944         smb_io_printer_info_6("", buffer, printer, 0);
4945
4946 out:
4947         /* clear memory */
4948         free_printer_info_6(printer);
4949
4950         return result;
4951 }
4952
4953 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4954 {
4955         PRINTER_INFO_7 *printer=NULL;
4956         WERROR result = WERR_OK;
4957
4958         if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4959                 return WERR_NOMEM;
4960
4961         if (!construct_printer_info_7(print_hnd, printer, snum)) {
4962                 result = WERR_NOMEM;
4963                 goto out;
4964         }
4965
4966         /* check the required size. */
4967         *needed += spoolss_size_printer_info_7(printer);
4968
4969         if (*needed > offered) {
4970                 result = WERR_INSUFFICIENT_BUFFER;
4971                 goto out;
4972         }
4973
4974         if (!rpcbuf_alloc_size(buffer, *needed)) {
4975                 result = WERR_NOMEM;
4976                 goto out;
4977
4978         }
4979
4980         /* fill the buffer with the structures */
4981         smb_io_printer_info_7("", buffer, printer, 0);
4982
4983 out:
4984         /* clear memory */
4985         free_printer_info_7(printer);
4986
4987         return result;
4988 }
4989
4990 /****************************************************************************
4991 ****************************************************************************/
4992
4993 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4994 {
4995         POLICY_HND *handle = &q_u->handle;
4996         uint32 level = q_u->level;
4997         RPC_BUFFER *buffer = NULL;
4998         uint32 offered = q_u->offered;
4999         uint32 *needed = &r_u->needed;
5000         Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5001
5002         int snum;
5003
5004         /* that's an [in out] buffer */
5005
5006         if (!q_u->buffer && (offered!=0)) {
5007                 return WERR_INVALID_PARAM;
5008         }
5009
5010         if (offered > MAX_RPC_DATA_SIZE) {
5011                 return WERR_INVALID_PARAM;
5012         }
5013
5014         rpcbuf_move(q_u->buffer, &r_u->buffer);
5015         buffer = r_u->buffer;
5016
5017         *needed=0;
5018
5019         if (!get_printer_snum(p, handle, &snum, NULL))
5020                 return WERR_BADFID;
5021
5022         switch (level) {
5023         case 0:
5024                 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5025         case 1:
5026                 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5027         case 2:
5028                 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5029         case 3:
5030                 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5031         case 4:
5032                 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5033         case 5:
5034                 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5035         case 6:
5036                 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5037         case 7:
5038                 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5039         }
5040         return WERR_UNKNOWN_LEVEL;
5041 }
5042
5043 /********************************************************************
5044  * fill a DRIVER_INFO_1 struct
5045  ********************************************************************/
5046
5047 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername, fstring architecture)
5048 {
5049         init_unistr( &info->name, driver.info_3->name);
5050 }
5051
5052 /********************************************************************
5053  * construct_printer_driver_info_1
5054  ********************************************************************/
5055
5056 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, const char *servername, fstring architecture, uint32 version)
5057 {
5058         NT_PRINTER_INFO_LEVEL *printer = NULL;
5059         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5060
5061         ZERO_STRUCT(driver);
5062
5063         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5064                 return WERR_INVALID_PRINTER_NAME;
5065
5066         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5067                 free_a_printer(&printer, 2);
5068                 return WERR_UNKNOWN_PRINTER_DRIVER;
5069         }
5070
5071         fill_printer_driver_info_1(info, driver, servername, architecture);
5072
5073         free_a_printer(&printer,2);
5074
5075         return WERR_OK;
5076 }
5077
5078 /********************************************************************
5079  * construct_printer_driver_info_2
5080  * fill a printer_info_2 struct
5081  ********************************************************************/
5082
5083 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5084 {
5085         TALLOC_CTX *ctx = talloc_tos();
5086         char *temp = NULL;
5087         const char *cservername = canon_servername(servername);
5088
5089         info->version=driver.info_3->cversion;
5090
5091         init_unistr( &info->name, driver.info_3->name );
5092         init_unistr( &info->architecture, driver.info_3->environment );
5093
5094         if (strlen(driver.info_3->driverpath)) {
5095                 temp = talloc_asprintf(ctx,
5096                                 "\\\\%s%s",
5097                                 cservername,
5098                                 driver.info_3->driverpath);
5099                 init_unistr( &info->driverpath, temp );
5100         } else {
5101                 init_unistr( &info->driverpath, "" );
5102         }
5103
5104         TALLOC_FREE(temp);
5105         if (strlen(driver.info_3->datafile)) {
5106                 temp = talloc_asprintf(ctx,
5107                                 "\\\\%s%s",
5108                                 cservername,
5109                                 driver.info_3->datafile);
5110                 init_unistr( &info->datafile, temp );
5111         } else
5112                 init_unistr( &info->datafile, "" );
5113
5114         TALLOC_FREE(temp);
5115         if (strlen(driver.info_3->configfile)) {
5116                 temp = talloc_asprintf(ctx,
5117                                 "\\\\%s%s",
5118                                 cservername,
5119                                 driver.info_3->configfile);
5120                 init_unistr( &info->configfile, temp );
5121         } else
5122                 init_unistr( &info->configfile, "" );
5123 }
5124
5125 /********************************************************************
5126  * construct_printer_driver_info_2
5127  * fill a printer_info_2 struct
5128  ********************************************************************/
5129
5130 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, const char *servername, fstring architecture, uint32 version)
5131 {
5132         NT_PRINTER_INFO_LEVEL *printer = NULL;
5133         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5134
5135         ZERO_STRUCT(printer);
5136         ZERO_STRUCT(driver);
5137
5138         if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5139                 return WERR_INVALID_PRINTER_NAME;
5140
5141         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5142                 free_a_printer(&printer, 2);
5143                 return WERR_UNKNOWN_PRINTER_DRIVER;
5144         }
5145
5146         fill_printer_driver_info_2(info, driver, servername);
5147
5148         free_a_printer(&printer,2);
5149
5150         return WERR_OK;
5151 }
5152
5153 /********************************************************************
5154  * copy a strings array and convert to UNICODE
5155  *
5156  * convert an array of ascii string to a UNICODE string
5157  ********************************************************************/
5158
5159 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5160 {
5161         int i=0;
5162         int j=0;
5163         const char *v;
5164         char *line = NULL;
5165         TALLOC_CTX *ctx = talloc_tos();
5166
5167         DEBUG(6,("init_unistr_array\n"));
5168         *uni_array=NULL;
5169
5170         while (true) {
5171                 if ( !char_array ) {
5172                         v = "";
5173                 } else {
5174                         v = char_array[i];
5175                         if (!v)
5176                                 v = ""; /* hack to handle null lists */
5177                 }
5178
5179                 /* hack to allow this to be used in places other than when generating
5180                    the list of dependent files */
5181
5182                 TALLOC_FREE(line);
5183                 if ( servername ) {
5184                         line = talloc_asprintf(ctx,
5185                                         "\\\\%s%s",
5186                                         canon_servername(servername),
5187                                         v);
5188                 } else {
5189                         line = talloc_strdup(ctx, v);
5190                 }
5191
5192                 if (!line) {
5193                         SAFE_FREE(*uni_array);
5194                         return 0;
5195                 }
5196                 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5197
5198                 /* add one extra unit16 for the second terminating NULL */
5199
5200                 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5201                         DEBUG(2,("init_unistr_array: Realloc error\n" ));
5202                         return 0;
5203                 }
5204
5205                 if ( !strlen(v) )
5206                         break;
5207
5208                 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5209                 i++;
5210         }
5211
5212         if (*uni_array) {
5213                 /* special case for ""; we need to add both NULL's here */
5214                 if (!j)
5215                         (*uni_array)[j++]=0x0000;
5216                 (*uni_array)[j]=0x0000;
5217         }
5218
5219         DEBUGADD(6,("last one:done\n"));
5220
5221         /* return size of array in uint16's */
5222
5223         return j+1;
5224 }
5225
5226 /********************************************************************
5227  * construct_printer_info_3
5228  * fill a printer_info_3 struct
5229  ********************************************************************/
5230
5231 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5232 {
5233         char *temp = NULL;
5234         TALLOC_CTX *ctx = talloc_tos();
5235         const char *cservername = canon_servername(servername);
5236
5237         ZERO_STRUCTP(info);
5238
5239         info->version=driver.info_3->cversion;
5240
5241         init_unistr( &info->name, driver.info_3->name );
5242         init_unistr( &info->architecture, driver.info_3->environment );
5243
5244         if (strlen(driver.info_3->driverpath)) {
5245                 temp = talloc_asprintf(ctx,
5246                                 "\\\\%s%s",
5247                                 cservername,
5248                                 driver.info_3->driverpath);
5249                 init_unistr( &info->driverpath, temp );
5250         } else
5251                 init_unistr( &info->driverpath, "" );
5252
5253         TALLOC_FREE(temp);
5254         if (strlen(driver.info_3->datafile)) {
5255                 temp = talloc_asprintf(ctx,
5256                                 "\\\\%s%s",
5257                                 cservername,
5258                                 driver.info_3->datafile);
5259                 init_unistr( &info->datafile, temp );
5260         } else
5261                 init_unistr( &info->datafile, "" );
5262
5263         TALLOC_FREE(temp);
5264         if (strlen(driver.info_3->configfile)) {
5265                 temp = talloc_asprintf(ctx,
5266                                 "\\\\%s%s",
5267                                 cservername,
5268                                 driver.info_3->configfile);
5269                 init_unistr( &info->configfile, temp );
5270         } else
5271                 init_unistr( &info->configfile, "" );
5272
5273         TALLOC_FREE(temp);
5274         if (strlen(driver.info_3->helpfile)) {
5275                 temp = talloc_asprintf(ctx,
5276                                 "\\\\%s%s",
5277                                 cservername,
5278                                 driver.info_3->helpfile);
5279                 init_unistr( &info->helpfile, temp );
5280         } else
5281                 init_unistr( &info->helpfile, "" );
5282
5283         TALLOC_FREE(temp);
5284         init_unistr( &info->monitorname, driver.info_3->monitorname );
5285         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5286
5287         info->dependentfiles=NULL;
5288         init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, cservername);
5289 }
5290
5291 /********************************************************************
5292  * construct_printer_info_3
5293  * fill a printer_info_3 struct
5294  ********************************************************************/
5295
5296 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, const char *servername, fstring architecture, uint32 version)
5297 {
5298         NT_PRINTER_INFO_LEVEL *printer = NULL;
5299         NT_PRINTER_DRIVER_INFO_LEVEL driver;
5300         WERROR status;
5301         ZERO_STRUCT(driver);
5302
5303         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5304         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5305         if (!W_ERROR_IS_OK(status))
5306                 return WERR_INVALID_PRINTER_NAME;
5307
5308         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5309         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5310
5311 #if 0   /* JERRY */
5312
5313         /*
5314          * I put this code in during testing.  Helpful when commenting out the
5315          * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
5316          * as win2k always queries the driver using an infor level of 6.
5317          * I've left it in (but ifdef'd out) because I'll probably
5318          * use it in experimentation again in the future.   --jerry 22/01/2002
5319          */
5320
5321         if (!W_ERROR_IS_OK(status)) {
5322                 /*
5323                  * Is this a W2k client ?
5324                  */
5325                 if (version == 3) {
5326                         /* Yes - try again with a WinNT driver. */
5327                         version = 2;
5328                         status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5329                         DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5330                 }
5331 #endif
5332
5333                 if (!W_ERROR_IS_OK(status)) {
5334                         free_a_printer(&printer,2);
5335                         return WERR_UNKNOWN_PRINTER_DRIVER;
5336                 }
5337
5338 #if 0   /* JERRY */
5339         }
5340 #endif
5341
5342
5343         fill_printer_driver_info_3(info, driver, servername);
5344
5345         free_a_printer(&printer,2);
5346
5347         return WERR_OK;
5348 }
5349
5350 /********************************************************************
5351  * construct_printer_info_6
5352  * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5353  ********************************************************************/
5354
5355 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, const char *servername)
5356 {
5357         char *temp = NULL;
5358         fstring nullstr;
5359         TALLOC_CTX *ctx = talloc_tos();
5360         const char *cservername = canon_servername(servername);
5361
5362         ZERO_STRUCTP(info);
5363         memset(&nullstr, '\0', sizeof(fstring));
5364
5365         info->version=driver.info_3->cversion;
5366
5367         init_unistr( &info->name, driver.info_3->name );
5368         init_unistr( &info->architecture, driver.info_3->environment );
5369
5370         if (strlen(driver.info_3->driverpath)) {
5371                 temp = talloc_asprintf(ctx,
5372                                 "\\\\%s%s",
5373                                 cservername,
5374                                 driver.info_3->driverpath);
5375                 init_unistr( &info->driverpath, temp );
5376         } else
5377                 init_unistr( &info->driverpath, "" );
5378
5379         TALLOC_FREE(temp);
5380         if (strlen(driver.info_3->datafile)) {
5381                 temp = talloc_asprintf(ctx,
5382                                 "\\\\%s%s",
5383                                 cservername,
5384                                 driver.info_3->datafile);
5385                 init_unistr( &info->datafile, temp );
5386         } else
5387                 init_unistr( &info->datafile, "" );
5388
5389         TALLOC_FREE(temp);
5390         if (strlen(driver.info_3->configfile)) {
5391                 temp = talloc_asprintf(ctx,
5392                                 "\\\\%s%s",
5393                                 cservername,
5394                                 driver.info_3->configfile);
5395                 init_unistr( &info->configfile, temp );
5396         } else
5397                 init_unistr( &info->configfile, "" );
5398
5399         TALLOC_FREE(temp);
5400         if (strlen(driver.info_3->helpfile)) {
5401                 temp = talloc_asprintf(ctx,
5402                                 "\\\\%s%s",
5403                                 cservername,
5404                                 driver.info_3->helpfile);
5405                 init_unistr( &info->helpfile, temp );
5406         } else
5407                 init_unistr( &info->helpfile, "" );
5408
5409         TALLOC_FREE(temp);
5410         init_unistr( &info->monitorname, driver.info_3->monitorname );
5411         init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5412
5413         info->dependentfiles = NULL;
5414         init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5415
5416         info->previousdrivernames=NULL;
5417         init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5418
5419         info->driver_date=0;
5420
5421         info->padding=0;
5422         info->driver_version_low=0;
5423         info->driver_version_high=0;
5424
5425         init_unistr( &info->mfgname, "");
5426         init_unistr( &info->oem_url, "");
5427         init_unistr( &info->hardware_id, "");
5428         init_unistr( &info->provider, "");
5429 }
5430
5431 /********************************************************************
5432  * construct_printer_info_6
5433  * fill a printer_info_6 struct
5434  ********************************************************************/
5435
5436 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5437               const char *servername, fstring architecture, uint32 version)
5438 {
5439         NT_PRINTER_INFO_LEVEL           *printer = NULL;
5440         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
5441         WERROR                          status;
5442
5443         ZERO_STRUCT(driver);
5444
5445         status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5446
5447         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5448
5449         if (!W_ERROR_IS_OK(status))
5450                 return WERR_INVALID_PRINTER_NAME;
5451
5452         status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5453
5454         DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5455
5456         if (!W_ERROR_IS_OK(status))
5457         {
5458                 /*
5459                  * Is this a W2k client ?
5460                  */
5461
5462                 if (version < 3) {
5463                         free_a_printer(&printer,2);
5464                         return WERR_UNKNOWN_PRINTER_DRIVER;
5465                 }
5466
5467                 /* Yes - try again with a WinNT driver. */
5468                 version = 2;
5469                 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5470                 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5471                 if (!W_ERROR_IS_OK(status)) {
5472                         free_a_printer(&printer,2);
5473                         return WERR_UNKNOWN_PRINTER_DRIVER;
5474                 }
5475         }
5476
5477         fill_printer_driver_info_6(info, driver, servername);
5478
5479         free_a_printer(&printer,2);
5480         free_a_printer_driver(driver, 3);
5481
5482         return WERR_OK;
5483 }
5484
5485 /****************************************************************************
5486 ****************************************************************************/
5487
5488 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5489 {
5490         SAFE_FREE(info->dependentfiles);
5491 }
5492
5493 /****************************************************************************
5494 ****************************************************************************/
5495
5496 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5497 {
5498         SAFE_FREE(info->dependentfiles);
5499 }
5500
5501 /****************************************************************************
5502 ****************************************************************************/
5503
5504 static WERROR getprinterdriver2_level1(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5505 {
5506         DRIVER_INFO_1 *info=NULL;
5507         WERROR result;
5508
5509         if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5510                 return WERR_NOMEM;
5511
5512         result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5513         if (!W_ERROR_IS_OK(result))
5514                 goto out;
5515
5516         /* check the required size. */
5517         *needed += spoolss_size_printer_driver_info_1(info);
5518
5519         if (*needed > offered) {
5520                 result = WERR_INSUFFICIENT_BUFFER;
5521                 goto out;
5522         }
5523
5524         if (!rpcbuf_alloc_size(buffer, *needed)) {
5525                 result = WERR_NOMEM;
5526                 goto out;
5527         }
5528
5529         /* fill the buffer with the structures */
5530         smb_io_printer_driver_info_1("", buffer, info, 0);
5531
5532 out:
5533         /* clear memory */
5534         SAFE_FREE(info);
5535
5536         return result;
5537 }
5538
5539 /****************************************************************************
5540 ****************************************************************************/
5541
5542 static WERROR getprinterdriver2_level2(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5543 {
5544         DRIVER_INFO_2 *info=NULL;
5545         WERROR result;
5546
5547         if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5548                 return WERR_NOMEM;
5549
5550         result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5551         if (!W_ERROR_IS_OK(result))
5552                 goto out;
5553
5554         /* check the required size. */
5555         *needed += spoolss_size_printer_driver_info_2(info);
5556
5557         if (*needed > offered) {
5558                 result = WERR_INSUFFICIENT_BUFFER;
5559                 goto out;
5560         }
5561
5562         if (!rpcbuf_alloc_size(buffer, *needed)) {
5563                 result = WERR_NOMEM;
5564                 goto out;
5565         }
5566
5567         /* fill the buffer with the structures */
5568         smb_io_printer_driver_info_2("", buffer, info, 0);
5569
5570 out:
5571         /* clear memory */
5572         SAFE_FREE(info);
5573
5574         return result;
5575 }
5576
5577 /****************************************************************************
5578 ****************************************************************************/
5579
5580 static WERROR getprinterdriver2_level3(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5581 {
5582         DRIVER_INFO_3 info;
5583         WERROR result;
5584
5585         ZERO_STRUCT(info);
5586
5587         result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5588         if (!W_ERROR_IS_OK(result))
5589                 goto out;
5590
5591         /* check the required size. */
5592         *needed += spoolss_size_printer_driver_info_3(&info);
5593
5594         if (*needed > offered) {
5595                 result = WERR_INSUFFICIENT_BUFFER;
5596                 goto out;
5597         }
5598
5599         if (!rpcbuf_alloc_size(buffer, *needed)) {
5600                 result = WERR_NOMEM;
5601                 goto out;
5602         }
5603
5604         /* fill the buffer with the structures */
5605         smb_io_printer_driver_info_3("", buffer, &info, 0);
5606
5607 out:
5608         free_printer_driver_info_3(&info);
5609
5610         return result;
5611 }
5612
5613 /****************************************************************************
5614 ****************************************************************************/
5615
5616 static WERROR getprinterdriver2_level6(const char *servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5617 {
5618         DRIVER_INFO_6 info;
5619         WERROR result;
5620
5621         ZERO_STRUCT(info);
5622
5623         result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5624         if (!W_ERROR_IS_OK(result))
5625                 goto out;
5626
5627         /* check the required size. */
5628         *needed += spoolss_size_printer_driver_info_6(&info);
5629
5630         if (*needed > offered) {
5631                 result = WERR_INSUFFICIENT_BUFFER;
5632                 goto out;
5633         }
5634
5635         if (!rpcbuf_alloc_size(buffer, *needed)) {
5636                 result = WERR_NOMEM;
5637                 goto out;
5638         }
5639
5640         /* fill the buffer with the structures */
5641         smb_io_printer_driver_info_6("", buffer, &info, 0);
5642
5643 out:
5644         free_printer_driver_info_6(&info);
5645
5646         return result;
5647 }
5648
5649 /****************************************************************************
5650 ****************************************************************************/
5651
5652 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5653 {
5654         POLICY_HND *handle = &q_u->handle;
5655         UNISTR2 *uni_arch = &q_u->architecture;
5656         uint32 level = q_u->level;
5657         uint32 clientmajorversion = q_u->clientmajorversion;
5658         RPC_BUFFER *buffer = NULL;
5659         uint32 offered = q_u->offered;
5660         uint32 *needed = &r_u->needed;
5661         uint32 *servermajorversion = &r_u->servermajorversion;
5662         uint32 *serverminorversion = &r_u->serverminorversion;
5663         Printer_entry *printer;
5664
5665         fstring servername;
5666         fstring architecture;
5667         int snum;
5668
5669         /* that's an [in out] buffer */
5670
5671         if (!q_u->buffer && (offered!=0)) {
5672                 return WERR_INVALID_PARAM;
5673         }
5674
5675         if (offered > MAX_RPC_DATA_SIZE) {
5676                 return WERR_INVALID_PARAM;
5677         }
5678
5679         rpcbuf_move(q_u->buffer, &r_u->buffer);
5680         buffer = r_u->buffer;
5681
5682         DEBUG(4,("_spoolss_getprinterdriver2\n"));
5683
5684         if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5685                 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5686                 return WERR_INVALID_PRINTER_NAME;
5687         }
5688
5689         *needed = 0;
5690         *servermajorversion = 0;
5691         *serverminorversion = 0;
5692
5693         fstrcpy(servername, get_server_name( printer ));
5694         unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5695
5696         if (!get_printer_snum(p, handle, &snum, NULL))
5697                 return WERR_BADFID;
5698
5699         switch (level) {
5700         case 1:
5701                 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5702         case 2:
5703                 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5704         case 3:
5705                 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5706         case 6:
5707                 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5708 #if 0   /* JERRY */
5709         case 101:
5710                 /* apparently this call is the equivalent of
5711                    EnumPrinterDataEx() for the DsDriver key */
5712                 break;
5713 #endif
5714         }
5715
5716         return WERR_UNKNOWN_LEVEL;
5717 }
5718
5719
5720 /****************************************************************
5721  _spoolss_StartPagePrinter
5722 ****************************************************************/
5723
5724 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5725                                  struct spoolss_StartPagePrinter *r)
5726 {
5727         POLICY_HND *handle = r->in.handle;
5728
5729         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5730
5731         if (!Printer) {
5732                 DEBUG(3,("_spoolss_StartPagePrinter: "
5733                         "Error in startpageprinter printer handle\n"));
5734                 return WERR_BADFID;
5735         }
5736
5737         Printer->page_started=True;
5738         return WERR_OK;
5739 }
5740
5741 /****************************************************************
5742  _spoolss_EndPagePrinter
5743 ****************************************************************/
5744
5745 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5746                                struct spoolss_EndPagePrinter *r)
5747 {
5748         POLICY_HND *handle = r->in.handle;
5749         int snum;
5750
5751         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5752
5753         if (!Printer) {
5754                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5755                         OUR_HANDLE(handle)));
5756                 return WERR_BADFID;
5757         }
5758
5759         if (!get_printer_snum(p, handle, &snum, NULL))
5760                 return WERR_BADFID;
5761
5762         Printer->page_started=False;
5763         print_job_endpage(snum, Printer->jobid);
5764
5765         return WERR_OK;
5766 }
5767
5768 /****************************************************************
5769  _spoolss_StartDocPrinter
5770 ****************************************************************/
5771
5772 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5773                                 struct spoolss_StartDocPrinter *r)
5774 {
5775         POLICY_HND *handle = r->in.handle;
5776         uint32_t *jobid = r->out.job_id;
5777         struct spoolss_DocumentInfo1 *info_1;
5778         int snum;
5779         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5780
5781         if (!Printer) {
5782                 DEBUG(2,("_spoolss_StartDocPrinter: "
5783                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5784                 return WERR_BADFID;
5785         }
5786
5787         if (r->in.level != 1) {
5788                 return WERR_UNKNOWN_LEVEL;
5789         }
5790
5791         info_1 = r->in.info.info1;
5792
5793         /*
5794          * a nice thing with NT is it doesn't listen to what you tell it.
5795          * when asked to send _only_ RAW datas, it tries to send datas
5796          * in EMF format.
5797          *
5798          * So I add checks like in NT Server ...
5799          */
5800
5801         if (info_1->datatype) {
5802                 if (strcmp(info_1->datatype, "RAW") != 0) {
5803                         (*jobid)=0;
5804                         return WERR_INVALID_DATATYPE;
5805                 }
5806         }
5807
5808         /* get the share number of the printer */
5809         if (!get_printer_snum(p, handle, &snum, NULL)) {
5810                 return WERR_BADFID;
5811         }
5812
5813         Printer->jobid = print_job_start(p->server_info, snum,
5814                                          CONST_DISCARD(char *,info_1->document_name),
5815                                          Printer->nt_devmode);
5816
5817         /* An error occured in print_job_start() so return an appropriate
5818            NT error code. */
5819
5820         if (Printer->jobid == -1) {
5821                 return map_werror_from_unix(errno);
5822         }
5823
5824         Printer->document_started=True;
5825         (*jobid) = Printer->jobid;
5826
5827         return WERR_OK;
5828 }
5829
5830 /****************************************************************
5831  _spoolss_EndDocPrinter
5832 ****************************************************************/
5833
5834 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5835                               struct spoolss_EndDocPrinter *r)
5836 {
5837         POLICY_HND *handle = r->in.handle;
5838
5839         return _spoolss_enddocprinter_internal(p, handle);
5840 }
5841
5842 /****************************************************************
5843  _spoolss_WritePrinter
5844 ****************************************************************/
5845
5846 WERROR _spoolss_WritePrinter(pipes_struct *p,
5847                              struct spoolss_WritePrinter *r)
5848 {
5849         POLICY_HND *handle = r->in.handle;
5850         uint32 buffer_size = r->in._data_size;
5851         uint8 *buffer = r->in.data.data;
5852         uint32 *buffer_written = &r->in._data_size;
5853         int snum;
5854         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5855
5856         if (!Printer) {
5857                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5858                         OUR_HANDLE(handle)));
5859                 *r->out.num_written = r->in._data_size;
5860                 return WERR_BADFID;
5861         }
5862
5863         if (!get_printer_snum(p, handle, &snum, NULL))
5864                 return WERR_BADFID;
5865
5866         (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5867                                         (SMB_OFF_T)-1, (size_t)buffer_size);
5868         if (*buffer_written == (uint32)-1) {
5869                 *r->out.num_written = 0;
5870                 if (errno == ENOSPC)
5871                         return WERR_NO_SPOOL_SPACE;
5872                 else
5873                         return WERR_ACCESS_DENIED;
5874         }
5875
5876         *r->out.num_written = r->in._data_size;
5877
5878         return WERR_OK;
5879 }
5880
5881 /********************************************************************
5882  * api_spoolss_getprinter
5883  * called from the spoolss dispatcher
5884  *
5885  ********************************************************************/
5886
5887 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5888                               pipes_struct *p)
5889 {
5890         int snum;
5891         WERROR errcode = WERR_BADFUNC;
5892         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5893
5894         if (!Printer) {
5895                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5896                 return WERR_BADFID;
5897         }
5898
5899         if (!get_printer_snum(p, handle, &snum, NULL))
5900                 return WERR_BADFID;
5901
5902         switch (command) {
5903         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5904                 if (print_queue_pause(p->server_info, snum, &errcode)) {
5905                         errcode = WERR_OK;
5906                 }
5907                 break;
5908         case SPOOLSS_PRINTER_CONTROL_RESUME:
5909         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5910                 if (print_queue_resume(p->server_info, snum, &errcode)) {
5911                         errcode = WERR_OK;
5912                 }
5913                 break;
5914         case SPOOLSS_PRINTER_CONTROL_PURGE:
5915                 if (print_queue_purge(p->server_info, snum, &errcode)) {
5916                         errcode = WERR_OK;
5917                 }
5918                 break;
5919         default:
5920                 return WERR_UNKNOWN_LEVEL;
5921         }
5922
5923         return errcode;
5924 }
5925
5926
5927 /****************************************************************
5928  _spoolss_AbortPrinter
5929  * From MSDN: "Deletes printer's spool file if printer is configured
5930  * for spooling"
5931 ****************************************************************/
5932
5933 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5934                              struct spoolss_AbortPrinter *r)
5935 {
5936         POLICY_HND      *handle = r->in.handle;
5937         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
5938         int             snum;
5939         WERROR          errcode = WERR_OK;
5940
5941         if (!Printer) {
5942                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5943                         OUR_HANDLE(handle)));
5944                 return WERR_BADFID;
5945         }
5946
5947         if (!get_printer_snum(p, handle, &snum, NULL))
5948                 return WERR_BADFID;
5949
5950         print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5951
5952         return errcode;
5953 }
5954
5955 /********************************************************************
5956  * called by spoolss_api_setprinter
5957  * when updating a printer description
5958  ********************************************************************/
5959
5960 static WERROR update_printer_sec(POLICY_HND *handle,
5961                                  pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5962 {
5963         SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5964         WERROR result;
5965         int snum;
5966
5967         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5968
5969         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5970                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5971                          OUR_HANDLE(handle)));
5972
5973                 result = WERR_BADFID;
5974                 goto done;
5975         }
5976
5977         if (!secdesc_ctr) {
5978                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5979                 result = WERR_INVALID_PARAM;
5980                 goto done;
5981         }
5982
5983         /* Check the user has permissions to change the security
5984            descriptor.  By experimentation with two NT machines, the user
5985            requires Full Access to the printer to change security
5986            information. */
5987
5988         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5989                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5990                 result = WERR_ACCESS_DENIED;
5991                 goto done;
5992         }
5993
5994         /* NT seems to like setting the security descriptor even though
5995            nothing may have actually changed. */
5996
5997         if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5998                 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5999                 result = WERR_BADFID;
6000                 goto done;
6001         }
6002
6003         if (DEBUGLEVEL >= 10) {
6004                 SEC_ACL *the_acl;
6005                 int i;
6006
6007                 the_acl = old_secdesc_ctr->sd->dacl;
6008                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6009                            PRINTERNAME(snum), the_acl->num_aces));
6010
6011                 for (i = 0; i < the_acl->num_aces; i++) {
6012                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6013                                            &the_acl->aces[i].trustee),
6014                                   the_acl->aces[i].access_mask));
6015                 }
6016
6017                 the_acl = secdesc_ctr->sd->dacl;
6018
6019                 if (the_acl) {
6020                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6021                                    PRINTERNAME(snum), the_acl->num_aces));
6022
6023                         for (i = 0; i < the_acl->num_aces; i++) {
6024                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6025                                                    &the_acl->aces[i].trustee),
6026                                            the_acl->aces[i].access_mask));
6027                         }
6028                 } else {
6029                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6030                 }
6031         }
6032
6033         new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6034         if (!new_secdesc_ctr) {
6035                 result = WERR_NOMEM;
6036                 goto done;
6037         }
6038
6039         if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6040                 result = WERR_OK;
6041                 goto done;
6042         }
6043
6044         result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6045
6046  done:
6047
6048         return result;
6049 }
6050
6051 /********************************************************************
6052  Canonicalize printer info from a client
6053
6054  ATTN: It does not matter what we set the servername to hear
6055  since we do the necessary work in get_a_printer() to set it to
6056  the correct value based on what the client sent in the
6057  _spoolss_open_printer_ex().
6058  ********************************************************************/
6059
6060 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6061 {
6062         fstring printername;
6063         const char *p;
6064
6065         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6066                 "portname=%s drivername=%s comment=%s location=%s\n",
6067                 info->servername, info->printername, info->sharename,
6068                 info->portname, info->drivername, info->comment, info->location));
6069
6070         /* we force some elements to "correct" values */
6071         slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6072         fstrcpy(info->sharename, lp_servicename(snum));
6073
6074         /* check to see if we allow printername != sharename */
6075
6076         if ( lp_force_printername(snum) ) {
6077                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6078                         global_myname(), info->sharename );
6079         } else {
6080
6081                 /* make sure printername is in \\server\printername format */
6082
6083                 fstrcpy( printername, info->printername );
6084                 p = printername;
6085                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6086                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6087                                 p++;
6088                 }
6089
6090                 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6091                          global_myname(), p );
6092         }
6093
6094         info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6095         info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6096
6097
6098
6099         return True;
6100 }
6101
6102 /****************************************************************************
6103 ****************************************************************************/
6104
6105 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6106 {
6107         char *cmd = lp_addport_cmd();
6108         char *command = NULL;
6109         int ret;
6110         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6111         bool is_print_op = False;
6112
6113         if ( !*cmd ) {
6114                 return WERR_ACCESS_DENIED;
6115         }
6116
6117         command = talloc_asprintf(ctx,
6118                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6119         if (!command) {
6120                 return WERR_NOMEM;
6121         }
6122
6123         if ( token )
6124                 is_print_op = user_has_privileges( token, &se_printop );
6125
6126         DEBUG(10,("Running [%s]\n", command));
6127
6128         /********* BEGIN SePrintOperatorPrivilege **********/
6129
6130         if ( is_print_op )
6131                 become_root();
6132
6133         ret = smbrun(command, NULL);
6134
6135         if ( is_print_op )
6136                 unbecome_root();
6137
6138         /********* END SePrintOperatorPrivilege **********/
6139
6140         DEBUGADD(10,("returned [%d]\n", ret));
6141
6142         TALLOC_FREE(command);
6143
6144         if ( ret != 0 ) {
6145                 return WERR_ACCESS_DENIED;
6146         }
6147
6148         return WERR_OK;
6149 }
6150
6151 /****************************************************************************
6152 ****************************************************************************/
6153
6154 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6155 {
6156         char *cmd = lp_addprinter_cmd();
6157         char **qlines;
6158         char *command = NULL;
6159         int numlines;
6160         int ret;
6161         int fd;
6162         SE_PRIV se_printop = SE_PRINT_OPERATOR;
6163         bool is_print_op = False;
6164         char *remote_machine = talloc_strdup(ctx, "%m");
6165
6166         if (!remote_machine) {
6167                 return false;
6168         }
6169         remote_machine = talloc_sub_basic(ctx,
6170                                 current_user_info.smb_name,
6171                                 current_user_info.domain,
6172                                 remote_machine);
6173         if (!remote_machine) {
6174                 return false;
6175         }
6176
6177         command = talloc_asprintf(ctx,
6178                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6179                         cmd, printer->info_2->printername, printer->info_2->sharename,
6180                         printer->info_2->portname, printer->info_2->drivername,
6181                         printer->info_2->location, printer->info_2->comment, remote_machine);
6182         if (!command) {
6183                 return false;
6184         }
6185
6186         if ( token )
6187                 is_print_op = user_has_privileges( token, &se_printop );
6188
6189         DEBUG(10,("Running [%s]\n", command));
6190
6191         /********* BEGIN SePrintOperatorPrivilege **********/
6192
6193         if ( is_print_op )
6194                 become_root();
6195
6196         if ( (ret = smbrun(command, &fd)) == 0 ) {
6197                 /* Tell everyone we updated smb.conf. */
6198                 message_send_all(smbd_messaging_context(),
6199                                  MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6200         }
6201
6202         if ( is_print_op )
6203                 unbecome_root();
6204
6205         /********* END SePrintOperatorPrivilege **********/
6206
6207         DEBUGADD(10,("returned [%d]\n", ret));
6208
6209         TALLOC_FREE(command);
6210         TALLOC_FREE(remote_machine);
6211
6212         if ( ret != 0 ) {
6213                 if (fd != -1)
6214                         close(fd);
6215                 return False;
6216         }
6217
6218         /* reload our services immediately */
6219         reload_services( False );
6220
6221         numlines = 0;
6222         /* Get lines and convert them back to dos-codepage */
6223         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6224         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6225         close(fd);
6226
6227         /* Set the portname to what the script says the portname should be. */
6228         /* but don't require anything to be return from the script exit a good error code */
6229
6230         if (numlines) {
6231                 /* Set the portname to what the script says the portname should be. */
6232                 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6233                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6234         }
6235
6236         TALLOC_FREE(qlines);
6237         return True;
6238 }
6239
6240
6241 /********************************************************************
6242  * Called by spoolss_api_setprinter
6243  * when updating a printer description.
6244  ********************************************************************/
6245
6246 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
6247                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6248                              struct spoolss_DeviceMode *devmode)
6249 {
6250         int snum;
6251         NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6252         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6253         WERROR result;
6254         UNISTR2 buffer;
6255         fstring asc_buffer;
6256
6257         DEBUG(8,("update_printer\n"));
6258
6259         result = WERR_OK;
6260
6261         if (!Printer) {
6262                 result = WERR_BADFID;
6263                 goto done;
6264         }
6265
6266         if (!get_printer_snum(p, handle, &snum, NULL)) {
6267                 result = WERR_BADFID;
6268                 goto done;
6269         }
6270
6271         if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6272             (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6273                 result = WERR_BADFID;
6274                 goto done;
6275         }
6276
6277         DEBUGADD(8,("Converting info_2 struct\n"));
6278
6279         /*
6280          * convert_printer_info converts the incoming
6281          * info from the client and overwrites the info
6282          * just read from the tdb in the pointer 'printer'.
6283          */
6284
6285         if (!convert_printer_info_new(info_ctr, printer)) {
6286                 result =  WERR_NOMEM;
6287                 goto done;
6288         }
6289
6290         if (devmode) {
6291                 /* we have a valid devmode
6292                    convert it and link it*/
6293
6294                 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6295                 if (!convert_devicemode_new(printer->info_2->printername,
6296                                             devmode,
6297                                             &printer->info_2->devmode)) {
6298                         result =  WERR_NOMEM;
6299                         goto done;
6300                 }
6301         }
6302
6303         /* Do sanity check on the requested changes for Samba */
6304
6305         if (!check_printer_ok(printer->info_2, snum)) {
6306                 result = WERR_INVALID_PARAM;
6307                 goto done;
6308         }
6309
6310         /* FIXME!!! If the driver has changed we really should verify that
6311            it is installed before doing much else   --jerry */
6312
6313         /* Check calling user has permission to update printer description */
6314
6315         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6316                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6317                 result = WERR_ACCESS_DENIED;
6318                 goto done;
6319         }
6320
6321         /* Call addprinter hook */
6322         /* Check changes to see if this is really needed */
6323
6324         if ( *lp_addprinter_cmd()
6325                 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6326                         || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6327                         || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6328                         || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6329         {
6330                 /* add_printer_hook() will call reload_services() */
6331
6332                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6333                                        printer) ) {
6334                         result = WERR_ACCESS_DENIED;
6335                         goto done;
6336                 }
6337         }
6338
6339         /*
6340          * When a *new* driver is bound to a printer, the drivername is used to
6341          * lookup previously saved driver initialization info, which is then
6342          * bound to the printer, simulating what happens in the Windows arch.
6343          */
6344         if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6345         {
6346                 if (!set_driver_init(printer, 2))
6347                 {
6348                         DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6349                                 printer->info_2->drivername));
6350                 }
6351
6352                 DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6353                         printer->info_2->drivername));
6354
6355                 notify_printer_driver(snum, printer->info_2->drivername);
6356         }
6357
6358         /*
6359          * flag which changes actually occured.  This is a small subset of
6360          * all the possible changes.  We also have to update things in the
6361          * DsSpooler key.
6362          */
6363
6364         if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6365                 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6366                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6367                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6368
6369                 notify_printer_comment(snum, printer->info_2->comment);
6370         }
6371
6372         if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6373                 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6374                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6375                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6376
6377                 notify_printer_sharename(snum, printer->info_2->sharename);
6378         }
6379
6380         if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6381                 char *pname;
6382
6383                 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6384                         pname++;
6385                 else
6386                         pname = printer->info_2->printername;
6387
6388
6389                 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6390                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6391                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6392
6393                 notify_printer_printername( snum, pname );
6394         }
6395
6396         if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6397                 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6398                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6399                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6400
6401                 notify_printer_port(snum, printer->info_2->portname);
6402         }
6403
6404         if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6405                 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6406                 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6407                         REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6408
6409                 notify_printer_location(snum, printer->info_2->location);
6410         }
6411
6412         /* here we need to update some more DsSpooler keys */
6413         /* uNCName, serverName, shortServerName */
6414
6415         init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6416         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6417                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6418         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6419                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6420
6421         slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6422                  global_myname(), printer->info_2->sharename );
6423         init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6424         set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6425                 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6426
6427         /* Update printer info */
6428         result = mod_a_printer(printer, 2);
6429
6430 done:
6431         free_a_printer(&printer, 2);
6432         free_a_printer(&old_printer, 2);
6433
6434
6435         return result;
6436 }
6437
6438 /****************************************************************************
6439 ****************************************************************************/
6440 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6441                                            struct spoolss_SetPrinterInfo7 *info7)
6442 {
6443 #ifdef HAVE_ADS
6444         int snum;
6445         Printer_entry *Printer;
6446
6447         if ( lp_security() != SEC_ADS ) {
6448                 return WERR_UNKNOWN_LEVEL;
6449         }
6450
6451         Printer = find_printer_index_by_hnd(p, handle);
6452
6453         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6454
6455         if (!Printer)
6456                 return WERR_BADFID;
6457
6458         if (!get_printer_snum(p, handle, &snum, NULL))
6459                 return WERR_BADFID;
6460
6461         nt_printer_publish(Printer, snum, info7->action);
6462
6463         return WERR_OK;
6464 #else
6465         return WERR_UNKNOWN_LEVEL;
6466 #endif
6467 }
6468
6469 /****************************************************************
6470  _spoolss_SetPrinter
6471 ****************************************************************/
6472
6473 WERROR _spoolss_SetPrinter(pipes_struct *p,
6474                            struct spoolss_SetPrinter *r)
6475 {
6476         POLICY_HND *handle = r->in.handle;
6477         WERROR result;
6478
6479         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6480
6481         if (!Printer) {
6482                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6483                         OUR_HANDLE(handle)));
6484                 return WERR_BADFID;
6485         }
6486
6487         /* check the level */
6488         switch (r->in.info_ctr->level) {
6489                 case 0:
6490                         return control_printer(handle, r->in.command, p);
6491                 case 2:
6492                         result = update_printer(p, handle,
6493                                                 r->in.info_ctr,
6494                                                 r->in.devmode_ctr->devmode);
6495                         if (!W_ERROR_IS_OK(result))
6496                                 return result;
6497                         if (r->in.secdesc_ctr->sd)
6498                                 result = update_printer_sec(handle, p,
6499                                                             r->in.secdesc_ctr);
6500                         return result;
6501                 case 3:
6502                         return update_printer_sec(handle, p,
6503                                                   r->in.secdesc_ctr);
6504                 case 7:
6505                         return publish_or_unpublish_printer(p, handle,
6506                                                             r->in.info_ctr->info.info7);
6507                 default:
6508                         return WERR_UNKNOWN_LEVEL;
6509         }
6510 }
6511
6512 /****************************************************************
6513  _spoolss_FindClosePrinterNotify
6514 ****************************************************************/
6515
6516 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6517                                        struct spoolss_FindClosePrinterNotify *r)
6518 {
6519         POLICY_HND *handle = r->in.handle;
6520         Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6521
6522         if (!Printer) {
6523                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6524                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6525                 return WERR_BADFID;
6526         }
6527
6528         if (Printer->notify.client_connected==True) {
6529                 int snum = -1;
6530
6531                 if ( Printer->printer_type == SPLHND_SERVER)
6532                         snum = -1;
6533                 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6534                                 !get_printer_snum(p, handle, &snum, NULL) )
6535                         return WERR_BADFID;
6536
6537                 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6538         }
6539
6540         Printer->notify.flags=0;
6541         Printer->notify.options=0;
6542         Printer->notify.localmachine[0]='\0';
6543         Printer->notify.printerlocal=0;
6544         if (Printer->notify.option)
6545                 free_spool_notify_option(&Printer->notify.option);
6546         Printer->notify.client_connected=False;
6547
6548         return WERR_OK;
6549 }
6550
6551 /****************************************************************
6552  _spoolss_AddJob
6553 ****************************************************************/
6554
6555 WERROR _spoolss_AddJob(pipes_struct *p,
6556                        struct spoolss_AddJob *r)
6557 {
6558         if (!r->in.buffer && (r->in.offered != 0)) {
6559                 return WERR_INVALID_PARAM;
6560         }
6561
6562         /* this is what a NT server returns for AddJob. AddJob must fail on
6563          * non-local printers */
6564
6565         return WERR_INVALID_PARAM;
6566 }
6567
6568 /****************************************************************************
6569 ****************************************************************************/
6570
6571 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6572                             int position, int snum,
6573                             const NT_PRINTER_INFO_LEVEL *ntprinter)
6574 {
6575         struct tm *t;
6576
6577         t=gmtime(&queue->time);
6578
6579         job_info->jobid=queue->job;
6580         init_unistr(&job_info->printername, lp_servicename(snum));
6581         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6582         init_unistr(&job_info->username, queue->fs_user);
6583         init_unistr(&job_info->document, queue->fs_file);
6584         init_unistr(&job_info->datatype, "RAW");
6585         init_unistr(&job_info->text_status, "");
6586         job_info->status=nt_printj_status(queue->status);
6587         job_info->priority=queue->priority;
6588         job_info->position=position;
6589         job_info->totalpages=queue->page_count;
6590         job_info->pagesprinted=0;
6591
6592         make_systemtime(&job_info->submitted, t);
6593 }
6594
6595 /****************************************************************************
6596 ****************************************************************************/
6597
6598 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6599                             int position, int snum,
6600                             const NT_PRINTER_INFO_LEVEL *ntprinter,
6601                             DEVICEMODE *devmode)
6602 {
6603         struct tm *t;
6604
6605         t=gmtime(&queue->time);
6606
6607         job_info->jobid=queue->job;
6608
6609         init_unistr(&job_info->printername, ntprinter->info_2->printername);
6610
6611         init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6612         init_unistr(&job_info->username, queue->fs_user);
6613         init_unistr(&job_info->document, queue->fs_file);
6614         init_unistr(&job_info->notifyname, queue->fs_user);
6615         init_unistr(&job_info->datatype, "RAW");
6616         init_unistr(&job_info->printprocessor, "winprint");
6617         init_unistr(&job_info->parameters, "");
6618         init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6619         init_unistr(&job_info->text_status, "");
6620
6621 /* and here the security descriptor */
6622
6623         job_info->status=nt_printj_status(queue->status);
6624         job_info->priority=queue->priority;
6625         job_info->position=position;
6626         job_info->starttime=0;
6627         job_info->untiltime=0;
6628         job_info->totalpages=queue->page_count;
6629         job_info->size=queue->size;
6630         make_systemtime(&(job_info->submitted), t);
6631         job_info->timeelapsed=0;
6632         job_info->pagesprinted=0;
6633
6634         job_info->devmode = devmode;
6635
6636         return (True);
6637 }
6638
6639 /****************************************************************************
6640  Enumjobs at level 1.
6641 ****************************************************************************/
6642
6643 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6644                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6645                               RPC_BUFFER *buffer, uint32 offered,
6646                               uint32 *needed, uint32 *returned)
6647 {
6648         JOB_INFO_1 *info;
6649         int i;
6650         WERROR result = WERR_OK;
6651
6652         info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6653         if (info==NULL) {
6654                 *returned=0;
6655                 return WERR_NOMEM;
6656         }
6657
6658         for (i=0; i<*returned; i++)
6659                 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6660
6661         /* check the required size. */
6662         for (i=0; i<*returned; i++)
6663                 (*needed) += spoolss_size_job_info_1(&info[i]);
6664
6665         if (*needed > offered) {
6666                 result = WERR_INSUFFICIENT_BUFFER;
6667                 goto out;
6668         }
6669
6670         if (!rpcbuf_alloc_size(buffer, *needed)) {
6671                 result = WERR_NOMEM;
6672                 goto out;
6673         }
6674
6675         /* fill the buffer with the structures */
6676         for (i=0; i<*returned; i++)
6677                 smb_io_job_info_1("", buffer, &info[i], 0);
6678
6679 out:
6680         /* clear memory */
6681         SAFE_FREE(info);
6682
6683         if ( !W_ERROR_IS_OK(result) )
6684                 *returned = 0;
6685
6686         return result;
6687 }
6688
6689 /****************************************************************************
6690  Enumjobs at level 2.
6691 ****************************************************************************/
6692
6693 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6694                               const NT_PRINTER_INFO_LEVEL *ntprinter,
6695                               RPC_BUFFER *buffer, uint32 offered,
6696                               uint32 *needed, uint32 *returned)
6697 {
6698         JOB_INFO_2 *info = NULL;
6699         int i;
6700         WERROR result = WERR_OK;
6701         DEVICEMODE *devmode = NULL;
6702
6703         if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6704                 *returned=0;
6705                 return WERR_NOMEM;
6706         }
6707
6708         /* this should not be a failure condition if the devmode is NULL */
6709
6710         devmode = construct_dev_mode(lp_const_servicename(snum));
6711
6712         for (i=0; i<*returned; i++)
6713                 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6714
6715         /* check the required size. */
6716         for (i=0; i<*returned; i++)
6717                 (*needed) += spoolss_size_job_info_2(&info[i]);
6718
6719         if (*needed > offered) {
6720                 result = WERR_INSUFFICIENT_BUFFER;
6721                 goto out;
6722         }
6723
6724         if (!rpcbuf_alloc_size(buffer, *needed)) {
6725                 result = WERR_NOMEM;
6726                 goto out;
6727         }
6728
6729         /* fill the buffer with the structures */
6730         for (i=0; i<*returned; i++)
6731                 smb_io_job_info_2("", buffer, &info[i], 0);
6732
6733 out:
6734         free_devmode(devmode);
6735         SAFE_FREE(info);
6736
6737         if ( !W_ERROR_IS_OK(result) )
6738                 *returned = 0;
6739
6740         return result;
6741
6742 }
6743
6744 /****************************************************************************
6745  Enumjobs.
6746 ****************************************************************************/
6747
6748 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6749 {
6750         POLICY_HND *handle = &q_u->handle;
6751         uint32 level = q_u->level;
6752         RPC_BUFFER *buffer = NULL;
6753         uint32 offered = q_u->offered;
6754         uint32 *needed = &r_u->needed;
6755         uint32 *returned = &r_u->returned;
6756         WERROR wret;
6757         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6758         int snum;
6759         print_status_struct prt_status;
6760         print_queue_struct *queue=NULL;
6761
6762         /* that's an [in out] buffer */
6763
6764         if (!q_u->buffer && (offered!=0)) {
6765                 return WERR_INVALID_PARAM;
6766         }
6767
6768         if (offered > MAX_RPC_DATA_SIZE) {
6769                 return WERR_INVALID_PARAM;
6770         }
6771
6772         rpcbuf_move(q_u->buffer, &r_u->buffer);
6773         buffer = r_u->buffer;
6774
6775         DEBUG(4,("_spoolss_enumjobs\n"));
6776
6777         *needed=0;
6778         *returned=0;
6779
6780         /* lookup the printer snum and tdb entry */
6781
6782         if (!get_printer_snum(p, handle, &snum, NULL))
6783                 return WERR_BADFID;
6784
6785         wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6786         if ( !W_ERROR_IS_OK(wret) )
6787                 return wret;
6788
6789         *returned = print_queue_status(snum, &queue, &prt_status);
6790         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6791
6792         if (*returned == 0) {
6793                 SAFE_FREE(queue);
6794                 free_a_printer(&ntprinter, 2);
6795                 return WERR_OK;
6796         }
6797
6798         switch (level) {
6799         case 1:
6800                 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6801                 break;
6802         case 2:
6803                 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6804                 break;
6805         default:
6806                 *returned=0;
6807                 wret = WERR_UNKNOWN_LEVEL;
6808                 break;
6809         }
6810
6811         SAFE_FREE(queue);
6812         free_a_printer( &ntprinter, 2 );
6813         return wret;
6814 }
6815
6816 /****************************************************************
6817  _spoolss_ScheduleJob
6818 ****************************************************************/
6819
6820 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6821                             struct spoolss_ScheduleJob *r)
6822 {
6823         return WERR_OK;
6824 }
6825
6826 /****************************************************************
6827  _spoolss_SetJob
6828 ****************************************************************/
6829
6830 WERROR _spoolss_SetJob(pipes_struct *p,
6831                        struct spoolss_SetJob *r)
6832 {
6833         POLICY_HND *handle = r->in.handle;
6834         uint32 jobid = r->in.job_id;
6835         uint32 command = r->in.command;
6836
6837         int snum;
6838         WERROR errcode = WERR_BADFUNC;
6839
6840         if (!get_printer_snum(p, handle, &snum, NULL)) {
6841                 return WERR_BADFID;
6842         }
6843
6844         if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6845                 return WERR_INVALID_PRINTER_NAME;
6846         }
6847
6848         switch (command) {
6849         case SPOOLSS_JOB_CONTROL_CANCEL:
6850         case SPOOLSS_JOB_CONTROL_DELETE:
6851                 if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
6852                         errcode = WERR_OK;
6853                 }
6854                 break;
6855         case SPOOLSS_JOB_CONTROL_PAUSE:
6856                 if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
6857                         errcode = WERR_OK;
6858                 }
6859                 break;
6860         case SPOOLSS_JOB_CONTROL_RESTART:
6861         case SPOOLSS_JOB_CONTROL_RESUME:
6862                 if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
6863                         errcode = WERR_OK;
6864                 }
6865                 break;
6866         default:
6867                 return WERR_UNKNOWN_LEVEL;
6868         }
6869
6870         return errcode;
6871 }
6872
6873 /****************************************************************************
6874  Enumerates all printer drivers at level 1.
6875 ****************************************************************************/
6876
6877 static WERROR enumprinterdrivers_level1(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6878 {
6879         int i;
6880         int ndrivers;
6881         uint32 version;
6882         fstring *list = NULL;
6883         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6884         DRIVER_INFO_1 *driver_info_1=NULL;
6885         WERROR result = WERR_OK;
6886
6887         *returned=0;
6888
6889         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6890                 list=NULL;
6891                 ndrivers=get_ntdrivers(&list, architecture, version);
6892                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6893
6894                 if(ndrivers == -1) {
6895                         SAFE_FREE(driver_info_1);
6896                         return WERR_NOMEM;
6897                 }
6898
6899                 if(ndrivers != 0) {
6900                         if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6901                                 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6902                                 SAFE_FREE(list);
6903                                 return WERR_NOMEM;
6904                         }
6905                 }
6906
6907                 for (i=0; i<ndrivers; i++) {
6908                         WERROR status;
6909                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6910                         ZERO_STRUCT(driver);
6911                         status = get_a_printer_driver(&driver, 3, list[i],
6912                                                       architecture, version);
6913                         if (!W_ERROR_IS_OK(status)) {
6914                                 SAFE_FREE(list);
6915                                 SAFE_FREE(driver_info_1);
6916                                 return status;
6917                         }
6918                         fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6919                         free_a_printer_driver(driver, 3);
6920                 }
6921
6922                 *returned+=ndrivers;
6923                 SAFE_FREE(list);
6924         }
6925
6926         /* check the required size. */
6927         for (i=0; i<*returned; i++) {
6928                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6929                 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6930         }
6931
6932         if (*needed > offered) {
6933                 result = WERR_INSUFFICIENT_BUFFER;
6934                 goto out;
6935         }
6936
6937         if (!rpcbuf_alloc_size(buffer, *needed)) {
6938                 result = WERR_NOMEM;
6939                 goto out;
6940         }
6941
6942         /* fill the buffer with the driver structures */
6943         for (i=0; i<*returned; i++) {
6944                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6945                 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6946         }
6947
6948 out:
6949         SAFE_FREE(driver_info_1);
6950
6951         if ( !W_ERROR_IS_OK(result) )
6952                 *returned = 0;
6953
6954         return result;
6955 }
6956
6957 /****************************************************************************
6958  Enumerates all printer drivers at level 2.
6959 ****************************************************************************/
6960
6961 static WERROR enumprinterdrivers_level2(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6962 {
6963         int i;
6964         int ndrivers;
6965         uint32 version;
6966         fstring *list = NULL;
6967         NT_PRINTER_DRIVER_INFO_LEVEL driver;
6968         DRIVER_INFO_2 *driver_info_2=NULL;
6969         WERROR result = WERR_OK;
6970
6971         *returned=0;
6972
6973         for (version=0; version<DRIVER_MAX_VERSION; version++) {
6974                 list=NULL;
6975                 ndrivers=get_ntdrivers(&list, architecture, version);
6976                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6977
6978                 if(ndrivers == -1) {
6979                         SAFE_FREE(driver_info_2);
6980                         return WERR_NOMEM;
6981                 }
6982
6983                 if(ndrivers != 0) {
6984                         if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6985                                 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6986                                 SAFE_FREE(list);
6987                                 return WERR_NOMEM;
6988                         }
6989                 }
6990
6991                 for (i=0; i<ndrivers; i++) {
6992                         WERROR status;
6993
6994                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6995                         ZERO_STRUCT(driver);
6996                         status = get_a_printer_driver(&driver, 3, list[i],
6997                                                       architecture, version);
6998                         if (!W_ERROR_IS_OK(status)) {
6999                                 SAFE_FREE(list);
7000                                 SAFE_FREE(driver_info_2);
7001                                 return status;
7002                         }
7003                         fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7004                         free_a_printer_driver(driver, 3);
7005                 }
7006
7007                 *returned+=ndrivers;
7008                 SAFE_FREE(list);
7009         }
7010
7011         /* check the required size. */
7012         for (i=0; i<*returned; i++) {
7013                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7014                 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7015         }
7016
7017         if (*needed > offered) {
7018                 result = WERR_INSUFFICIENT_BUFFER;
7019                 goto out;
7020         }
7021
7022         if (!rpcbuf_alloc_size(buffer, *needed)) {
7023                 result = WERR_NOMEM;
7024                 goto out;
7025         }
7026
7027         /* fill the buffer with the form structures */
7028         for (i=0; i<*returned; i++) {
7029                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7030                 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7031         }
7032
7033 out:
7034         SAFE_FREE(driver_info_2);
7035
7036         if ( !W_ERROR_IS_OK(result) )
7037                 *returned = 0;
7038
7039         return result;
7040 }
7041
7042 /****************************************************************************
7043  Enumerates all printer drivers at level 3.
7044 ****************************************************************************/
7045
7046 static WERROR enumprinterdrivers_level3(const char *servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7047 {
7048         int i;
7049         int ndrivers;
7050         uint32 version;
7051         fstring *list = NULL;
7052         DRIVER_INFO_3 *driver_info_3=NULL;
7053         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7054         WERROR result = WERR_OK;
7055
7056         *returned=0;
7057
7058         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7059                 list=NULL;
7060                 ndrivers=get_ntdrivers(&list, architecture, version);
7061                 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7062
7063                 if(ndrivers == -1) {
7064                         SAFE_FREE(driver_info_3);
7065                         return WERR_NOMEM;
7066                 }
7067
7068                 if(ndrivers != 0) {
7069                         if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7070                                 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7071                                 SAFE_FREE(list);
7072                                 return WERR_NOMEM;
7073                         }
7074                 }
7075
7076                 for (i=0; i<ndrivers; i++) {
7077                         WERROR status;
7078
7079                         DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7080                         ZERO_STRUCT(driver);
7081                         status = get_a_printer_driver(&driver, 3, list[i],
7082                                                       architecture, version);
7083                         if (!W_ERROR_IS_OK(status)) {
7084                                 SAFE_FREE(list);
7085                                 SAFE_FREE(driver_info_3);
7086                                 return status;
7087                         }
7088                         fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7089                         free_a_printer_driver(driver, 3);
7090                 }
7091
7092                 *returned+=ndrivers;
7093                 SAFE_FREE(list);
7094         }
7095
7096         /* check the required size. */
7097         for (i=0; i<*returned; i++) {
7098                 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7099                 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7100         }
7101
7102         if (*needed > offered) {
7103                 result = WERR_INSUFFICIENT_BUFFER;
7104                 goto out;
7105         }
7106
7107         if (!rpcbuf_alloc_size(buffer, *needed)) {
7108                 result = WERR_NOMEM;
7109                 goto out;
7110         }
7111
7112         /* fill the buffer with the driver structures */
7113         for (i=0; i<*returned; i++) {
7114                 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7115                 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7116         }
7117
7118 out:
7119         for (i=0; i<*returned; i++) {
7120                 SAFE_FREE(driver_info_3[i].dependentfiles);
7121         }
7122
7123         SAFE_FREE(driver_info_3);
7124
7125         if ( !W_ERROR_IS_OK(result) )
7126                 *returned = 0;
7127
7128         return result;
7129 }
7130
7131 /****************************************************************************
7132  Enumerates all printer drivers.
7133 ****************************************************************************/
7134
7135 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7136 {
7137         uint32 level = q_u->level;
7138         RPC_BUFFER *buffer = NULL;
7139         uint32 offered = q_u->offered;
7140         uint32 *needed = &r_u->needed;
7141         uint32 *returned = &r_u->returned;
7142         const char *cservername;
7143         fstring servername;
7144         fstring architecture;
7145
7146         /* that's an [in out] buffer */
7147
7148         if (!q_u->buffer && (offered!=0)) {
7149                 return WERR_INVALID_PARAM;
7150         }
7151
7152         if (offered > MAX_RPC_DATA_SIZE) {
7153                 return WERR_INVALID_PARAM;
7154         }
7155
7156         rpcbuf_move(q_u->buffer, &r_u->buffer);
7157         buffer = r_u->buffer;
7158
7159         DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7160
7161         *needed   = 0;
7162         *returned = 0;
7163
7164         unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7165         unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7166
7167         cservername = canon_servername(servername);
7168
7169         if (!is_myname_or_ipaddr(cservername))
7170                 return WERR_UNKNOWN_PRINTER_DRIVER;
7171
7172         switch (level) {
7173         case 1:
7174                 return enumprinterdrivers_level1(cservername, architecture, buffer, offered, needed, returned);
7175         case 2:
7176                 return enumprinterdrivers_level2(cservername, architecture, buffer, offered, needed, returned);
7177         case 3:
7178                 return enumprinterdrivers_level3(cservername, architecture, buffer, offered, needed, returned);
7179         default:
7180                 return WERR_UNKNOWN_LEVEL;
7181         }
7182 }
7183
7184 /****************************************************************************
7185 ****************************************************************************/
7186
7187 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7188 {
7189         form->flag=list->flag;
7190         init_unistr(&form->name, list->name);
7191         form->width=list->width;
7192         form->length=list->length;
7193         form->left=list->left;
7194         form->top=list->top;
7195         form->right=list->right;
7196         form->bottom=list->bottom;
7197 }
7198
7199 /****************************************************************************
7200 ****************************************************************************/
7201
7202 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7203                                struct spoolss_FormInfo1 *form,
7204                                nt_forms_struct *list)
7205 {
7206         form->form_name         = talloc_strdup(mem_ctx, list->name);
7207         W_ERROR_HAVE_NO_MEMORY(form->form_name);
7208
7209         form->flags             = list->flag;
7210         form->size.width        = list->width;
7211         form->size.height       = list->length;
7212         form->area.left         = list->left;
7213         form->area.top          = list->top;
7214         form->area.right        = list->right;
7215         form->area.bottom       = list->bottom;
7216
7217         return WERR_OK;
7218 }
7219
7220 /****************************************************************************
7221 ****************************************************************************/
7222
7223 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7224 {
7225         uint32 level = q_u->level;
7226         RPC_BUFFER *buffer = NULL;
7227         uint32 offered = q_u->offered;
7228         uint32 *needed = &r_u->needed;
7229         uint32 *numofforms = &r_u->numofforms;
7230         uint32 numbuiltinforms;
7231
7232         nt_forms_struct *list=NULL;
7233         nt_forms_struct *builtinlist=NULL;
7234         FORM_1 *forms_1;
7235         int buffer_size=0;
7236         int i;
7237
7238         /* that's an [in out] buffer */
7239
7240         if (!q_u->buffer && (offered!=0) ) {
7241                 return WERR_INVALID_PARAM;
7242         }
7243
7244         if (offered > MAX_RPC_DATA_SIZE) {
7245                 return WERR_INVALID_PARAM;
7246         }
7247
7248         rpcbuf_move(q_u->buffer, &r_u->buffer);
7249         buffer = r_u->buffer;
7250
7251         DEBUG(4,("_spoolss_enumforms\n"));
7252         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7253         DEBUGADD(5,("Info level [%d]\n",          level));
7254
7255         numbuiltinforms = get_builtin_ntforms(&builtinlist);
7256         DEBUGADD(5,("Number of builtin forms [%d]\n",     numbuiltinforms));
7257         *numofforms = get_ntforms(&list);
7258         DEBUGADD(5,("Number of user forms [%d]\n",     *numofforms));
7259         *numofforms += numbuiltinforms;
7260
7261         if (*numofforms == 0) {
7262                 SAFE_FREE(builtinlist);
7263                 SAFE_FREE(list);
7264                 return WERR_NO_MORE_ITEMS;
7265         }
7266
7267         switch (level) {
7268         case 1:
7269                 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7270                         SAFE_FREE(builtinlist);
7271                         SAFE_FREE(list);
7272                         *numofforms=0;
7273                         return WERR_NOMEM;
7274                 }
7275
7276                 /* construct the list of form structures */
7277                 for (i=0; i<numbuiltinforms; i++) {
7278                         DEBUGADD(6,("Filling form number [%d]\n",i));
7279                         fill_form_1(&forms_1[i], &builtinlist[i]);
7280                 }
7281
7282                 SAFE_FREE(builtinlist);
7283
7284                 for (; i<*numofforms; i++) {
7285                         DEBUGADD(6,("Filling form number [%d]\n",i));
7286                         fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7287                 }
7288
7289                 SAFE_FREE(list);
7290
7291                 /* check the required size. */
7292                 for (i=0; i<numbuiltinforms; i++) {
7293                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7294                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7295                 }
7296                 for (; i<*numofforms; i++) {
7297                         DEBUGADD(6,("adding form [%d]'s size\n",i));
7298                         buffer_size += spoolss_size_form_1(&forms_1[i]);
7299                 }
7300
7301                 *needed=buffer_size;
7302
7303                 if (*needed > offered) {
7304                         SAFE_FREE(forms_1);
7305                         *numofforms=0;
7306                         return WERR_INSUFFICIENT_BUFFER;
7307                 }
7308
7309                 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7310                         SAFE_FREE(forms_1);
7311                         *numofforms=0;
7312                         return WERR_NOMEM;
7313                 }
7314
7315                 /* fill the buffer with the form structures */
7316                 for (i=0; i<numbuiltinforms; i++) {
7317                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7318                         smb_io_form_1("", buffer, &forms_1[i], 0);
7319                 }
7320                 for (; i<*numofforms; i++) {
7321                         DEBUGADD(6,("adding form [%d] to buffer\n",i));
7322                         smb_io_form_1("", buffer, &forms_1[i], 0);
7323                 }
7324
7325                 SAFE_FREE(forms_1);
7326
7327                 return WERR_OK;
7328
7329         default:
7330                 SAFE_FREE(list);
7331                 SAFE_FREE(builtinlist);
7332                 return WERR_UNKNOWN_LEVEL;
7333         }
7334 }
7335
7336 /****************************************************************
7337  _spoolss_GetForm
7338 ****************************************************************/
7339
7340 WERROR _spoolss_GetForm(pipes_struct *p,
7341                         struct spoolss_GetForm *r)
7342 {
7343         uint32 level = r->in.level;
7344         uint32 offered = r->in.offered;
7345         uint32 *needed = r->out.needed;
7346
7347         nt_forms_struct *list=NULL;
7348         nt_forms_struct builtin_form;
7349         bool foundBuiltin;
7350         union spoolss_FormInfo info;
7351         struct spoolss_FormInfo1 form_1;
7352         int numofforms=0, i=0;
7353
7354         /* that's an [in out] buffer */
7355
7356         if (!r->in.buffer && (offered!=0)) {
7357                 return WERR_INVALID_PARAM;
7358         }
7359
7360         DEBUG(4,("_spoolss_GetForm\n"));
7361         DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7362         DEBUGADD(5,("Info level [%d]\n",          level));
7363
7364         foundBuiltin = get_a_builtin_ntform_by_string(r->in.form_name, &builtin_form);
7365         if (!foundBuiltin) {
7366                 numofforms = get_ntforms(&list);
7367                 DEBUGADD(5,("Number of forms [%d]\n",     numofforms));
7368
7369                 if (numofforms == 0)
7370                         return WERR_BADFID;
7371         }
7372
7373         ZERO_STRUCT(form_1);
7374
7375         switch (level) {
7376         case 1:
7377                 if (foundBuiltin) {
7378                         fill_form_info_1(p->mem_ctx, &form_1, &builtin_form);
7379                 } else {
7380
7381                         /* Check if the requested name is in the list of form structures */
7382                         for (i=0; i<numofforms; i++) {
7383
7384                                 DEBUG(4,("_spoolss_GetForm: checking form %s (want %s)\n",
7385                                         list[i].name, r->in.form_name));
7386
7387                                 if (strequal(r->in.form_name, list[i].name)) {
7388                                         DEBUGADD(6,("Found form %s number [%d]\n",
7389                                                 r->in.form_name, i));
7390                                         fill_form_info_1(p->mem_ctx, &form_1, &list[i]);
7391                                         break;
7392                                 }
7393                         }
7394
7395                         SAFE_FREE(list);
7396                         if (i == numofforms) {
7397                                 return WERR_BADFID;
7398                         }
7399                 }
7400                 /* check the required size. */
7401
7402                 info.info1 = form_1;
7403
7404                 *needed = ndr_size_spoolss_FormInfo(&info, 1, NULL, 0);
7405
7406                 if (*needed > offered) {
7407                         r->out.info = NULL;
7408                         return WERR_INSUFFICIENT_BUFFER;
7409                 }
7410
7411                 r->out.info->info1 = form_1;
7412
7413                 /* fill the buffer with the form structures */
7414                 DEBUGADD(6,("adding form %s [%d] to buffer\n",
7415                         r->in.form_name, i));
7416
7417                 return WERR_OK;
7418
7419         default:
7420                 SAFE_FREE(list);
7421                 return WERR_UNKNOWN_LEVEL;
7422         }
7423 }
7424
7425 /****************************************************************************
7426 ****************************************************************************/
7427
7428 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7429 {
7430         init_unistr(&port->port_name, name);
7431 }
7432
7433 /****************************************************************************
7434  TODO: This probably needs distinguish between TCP/IP and Local ports
7435  somehow.
7436 ****************************************************************************/
7437
7438 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7439 {
7440         init_unistr(&port->port_name, name);
7441         init_unistr(&port->monitor_name, "Local Monitor");
7442         init_unistr(&port->description, SPL_LOCAL_PORT );
7443         port->port_type=PORT_TYPE_WRITE;
7444         port->reserved=0x0;
7445 }
7446
7447
7448 /****************************************************************************
7449  wrapper around the enumer ports command
7450 ****************************************************************************/
7451
7452 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7453 {
7454         char *cmd = lp_enumports_cmd();
7455         char **qlines = NULL;
7456         char *command = NULL;
7457         int numlines;
7458         int ret;
7459         int fd;
7460
7461         *count = 0;
7462         *lines = NULL;
7463
7464         /* if no hook then just fill in the default port */
7465
7466         if ( !*cmd ) {
7467                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7468                         return WERR_NOMEM;
7469                 }
7470                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7471                         TALLOC_FREE(qlines);
7472                         return WERR_NOMEM;
7473                 }
7474                 qlines[1] = NULL;
7475                 numlines = 1;
7476         }
7477         else {
7478                 /* we have a valid enumport command */
7479
7480                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7481                 if (!command) {
7482                         return WERR_NOMEM;
7483                 }
7484
7485                 DEBUG(10,("Running [%s]\n", command));
7486                 ret = smbrun(command, &fd);
7487                 DEBUG(10,("Returned [%d]\n", ret));
7488                 TALLOC_FREE(command);
7489                 if (ret != 0) {
7490                         if (fd != -1) {
7491                                 close(fd);
7492                         }
7493                         return WERR_ACCESS_DENIED;
7494                 }
7495
7496                 numlines = 0;
7497                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7498                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7499                 close(fd);
7500         }
7501
7502         *count = numlines;
7503         *lines = qlines;
7504
7505         return WERR_OK;
7506 }
7507
7508 /****************************************************************************
7509  enumports level 1.
7510 ****************************************************************************/
7511
7512 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7513 {
7514         PORT_INFO_1 *ports=NULL;
7515         int i=0;
7516         WERROR result = WERR_OK;
7517         char **qlines = NULL;
7518         int numlines = 0;
7519
7520         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7521         if (!W_ERROR_IS_OK(result)) {
7522                 TALLOC_FREE(qlines);
7523                 return result;
7524         }
7525
7526         if(numlines) {
7527                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7528                         DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7529                                   win_errstr(WERR_NOMEM)));
7530                         TALLOC_FREE(qlines);
7531                         return WERR_NOMEM;
7532                 }
7533
7534                 for (i=0; i<numlines; i++) {
7535                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7536                         fill_port_1(&ports[i], qlines[i]);
7537                 }
7538         }
7539         TALLOC_FREE(qlines);
7540
7541         *returned = numlines;
7542
7543         /* check the required size. */
7544         for (i=0; i<*returned; i++) {
7545                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7546                 *needed += spoolss_size_port_info_1(&ports[i]);
7547         }
7548
7549         if (*needed > offered) {
7550                 result = WERR_INSUFFICIENT_BUFFER;
7551                 goto out;
7552         }
7553
7554         if (!rpcbuf_alloc_size(buffer, *needed)) {
7555                 result = WERR_NOMEM;
7556                 goto out;
7557         }
7558
7559         /* fill the buffer with the ports structures */
7560         for (i=0; i<*returned; i++) {
7561                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7562                 smb_io_port_1("", buffer, &ports[i], 0);
7563         }
7564
7565 out:
7566         SAFE_FREE(ports);
7567
7568         if ( !W_ERROR_IS_OK(result) )
7569                 *returned = 0;
7570
7571         return result;
7572 }
7573
7574 /****************************************************************************
7575  enumports level 2.
7576 ****************************************************************************/
7577
7578 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7579 {
7580         PORT_INFO_2 *ports=NULL;
7581         int i=0;
7582         WERROR result = WERR_OK;
7583         char **qlines = NULL;
7584         int numlines = 0;
7585
7586         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7587         if ( !W_ERROR_IS_OK(result)) {
7588                 TALLOC_FREE(qlines);
7589                 return result;
7590         }
7591
7592         if(numlines) {
7593                 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7594                         TALLOC_FREE(qlines);
7595                         return WERR_NOMEM;
7596                 }
7597
7598                 for (i=0; i<numlines; i++) {
7599                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7600                         fill_port_2(&(ports[i]), qlines[i]);
7601                 }
7602         }
7603
7604         TALLOC_FREE(qlines);
7605
7606         *returned = numlines;
7607
7608         /* check the required size. */
7609         for (i=0; i<*returned; i++) {
7610                 DEBUGADD(6,("adding port [%d]'s size\n", i));
7611                 *needed += spoolss_size_port_info_2(&ports[i]);
7612         }
7613
7614         if (*needed > offered) {
7615                 result = WERR_INSUFFICIENT_BUFFER;
7616                 goto out;
7617         }
7618
7619         if (!rpcbuf_alloc_size(buffer, *needed)) {
7620                 result = WERR_NOMEM;
7621                 goto out;
7622         }
7623
7624         /* fill the buffer with the ports structures */
7625         for (i=0; i<*returned; i++) {
7626                 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7627                 smb_io_port_2("", buffer, &ports[i], 0);
7628         }
7629
7630 out:
7631         SAFE_FREE(ports);
7632
7633         if ( !W_ERROR_IS_OK(result) )
7634                 *returned = 0;
7635
7636         return result;
7637 }
7638
7639 /****************************************************************************
7640  enumports.
7641 ****************************************************************************/
7642
7643 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7644 {
7645         uint32 level = q_u->level;
7646         RPC_BUFFER *buffer = NULL;
7647         uint32 offered = q_u->offered;
7648         uint32 *needed = &r_u->needed;
7649         uint32 *returned = &r_u->returned;
7650
7651         /* that's an [in out] buffer */
7652
7653         if (!q_u->buffer && (offered!=0)) {
7654                 return WERR_INVALID_PARAM;
7655         }
7656
7657         if (offered > MAX_RPC_DATA_SIZE) {
7658                 return WERR_INVALID_PARAM;
7659         }
7660
7661         rpcbuf_move(q_u->buffer, &r_u->buffer);
7662         buffer = r_u->buffer;
7663
7664         DEBUG(4,("_spoolss_enumports\n"));
7665
7666         *returned=0;
7667         *needed=0;
7668
7669         switch (level) {
7670         case 1:
7671                 return enumports_level_1(buffer, offered, needed, returned);
7672         case 2:
7673                 return enumports_level_2(buffer, offered, needed, returned);
7674         default:
7675                 return WERR_UNKNOWN_LEVEL;
7676         }
7677 }
7678
7679 /****************************************************************************
7680 ****************************************************************************/
7681
7682 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7683                                            const char *server,
7684                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7685                                            struct spoolss_DeviceMode *devmode,
7686                                            struct security_descriptor *sec_desc,
7687                                            struct spoolss_UserLevelCtr *user_ctr,
7688                                            POLICY_HND *handle)
7689 {
7690         NT_PRINTER_INFO_LEVEL *printer = NULL;
7691         fstring name;
7692         int     snum;
7693         WERROR err = WERR_OK;
7694
7695         if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7696                 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7697                 return WERR_NOMEM;
7698         }
7699
7700         /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7701         if (!convert_printer_info_new(info_ctr, printer)) {
7702                 free_a_printer(&printer, 2);
7703                 return WERR_NOMEM;
7704         }
7705
7706         /* check to see if the printer already exists */
7707
7708         if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7709                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7710                         printer->info_2->sharename));
7711                 free_a_printer(&printer, 2);
7712                 return WERR_PRINTER_ALREADY_EXISTS;
7713         }
7714
7715         /* FIXME!!!  smbd should check to see if the driver is installed before
7716            trying to add a printer like this  --jerry */
7717
7718         if (*lp_addprinter_cmd() ) {
7719                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7720                                        printer) ) {
7721                         free_a_printer(&printer,2);
7722                         return WERR_ACCESS_DENIED;
7723                 }
7724         } else {
7725                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7726                         "smb.conf parameter \"addprinter command\" is defined. This"
7727                         "parameter must exist for this call to succeed\n",
7728                         printer->info_2->sharename ));
7729         }
7730
7731         /* use our primary netbios name since get_a_printer() will convert
7732            it to what the client expects on a case by case basis */
7733
7734         slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7735              printer->info_2->sharename);
7736
7737
7738         if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7739                 free_a_printer(&printer,2);
7740                 return WERR_ACCESS_DENIED;
7741         }
7742
7743         /* you must be a printer admin to add a new printer */
7744         if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7745                 free_a_printer(&printer,2);
7746                 return WERR_ACCESS_DENIED;
7747         }
7748
7749         /*
7750          * Do sanity check on the requested changes for Samba.
7751          */
7752
7753         if (!check_printer_ok(printer->info_2, snum)) {
7754                 free_a_printer(&printer,2);
7755                 return WERR_INVALID_PARAM;
7756         }
7757
7758         /*
7759          * When a printer is created, the drivername bound to the printer is used
7760          * to lookup previously saved driver initialization info, which is then
7761          * bound to the new printer, simulating what happens in the Windows arch.
7762          */
7763
7764         if (!devmode)
7765         {
7766                 set_driver_init(printer, 2);
7767         }
7768         else
7769         {
7770                 /* A valid devmode was included, convert and link it
7771                 */
7772                 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7773
7774                 if (!convert_devicemode_new(printer->info_2->printername,
7775                                             devmode,
7776                                             &printer->info_2->devmode))
7777                         return  WERR_NOMEM;
7778         }
7779
7780         /* write the ASCII on disk */
7781         err = mod_a_printer(printer, 2);
7782         if (!W_ERROR_IS_OK(err)) {
7783                 free_a_printer(&printer,2);
7784                 return err;
7785         }
7786
7787         if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7788                 /* Handle open failed - remove addition. */
7789                 del_a_printer(printer->info_2->sharename);
7790                 free_a_printer(&printer,2);
7791                 ZERO_STRUCTP(handle);
7792                 return WERR_ACCESS_DENIED;
7793         }
7794
7795         update_c_setprinter(False);
7796         free_a_printer(&printer,2);
7797
7798         return WERR_OK;
7799 }
7800
7801 /****************************************************************
7802  _spoolss_AddPrinterEx
7803 ****************************************************************/
7804
7805 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7806                              struct spoolss_AddPrinterEx *r)
7807 {
7808         switch (r->in.info_ctr->level) {
7809         case 1:
7810                 /* we don't handle yet */
7811                 /* but I know what to do ... */
7812                 return WERR_UNKNOWN_LEVEL;
7813         case 2:
7814                 return spoolss_addprinterex_level_2(p, r->in.server,
7815                                                     r->in.info_ctr,
7816                                                     r->in.devmode_ctr->devmode,
7817                                                     r->in.secdesc_ctr->sd,
7818                                                     r->in.userlevel_ctr,
7819                                                     r->out.handle);
7820         default:
7821                 return WERR_UNKNOWN_LEVEL;
7822         }
7823 }
7824
7825 /****************************************************************
7826  _spoolss_AddPrinterDriver
7827 ****************************************************************/
7828
7829 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7830                                  struct spoolss_AddPrinterDriver *r)
7831 {
7832         uint32_t level = r->in.info_ctr->level;
7833         struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7834         WERROR err = WERR_OK;
7835         NT_PRINTER_DRIVER_INFO_LEVEL driver;
7836         fstring driver_name;
7837         uint32 version;
7838         const char *fn;
7839
7840         switch (p->hdr_req.opnum) {
7841                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7842                         fn = "_spoolss_AddPrinterDriver";
7843                         break;
7844                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7845                         fn = "_spoolss_AddPrinterDriverEx";
7846                         break;
7847                 default:
7848                         return WERR_INVALID_PARAM;
7849         }
7850
7851
7852         /* FIXME */
7853         if (level != 3 && level != 6) {
7854                 /* Clever hack from Martin Zielinski <mz@seh.de>
7855                  * to allow downgrade from level 8 (Vista).
7856                  */
7857                 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7858                 return WERR_UNKNOWN_LEVEL;
7859         }
7860
7861         ZERO_STRUCT(driver);
7862
7863         if (!convert_printer_driver_info(info, &driver, level)) {
7864                 err = WERR_NOMEM;
7865                 goto done;
7866         }
7867
7868         DEBUG(5,("Cleaning driver's information\n"));
7869         err = clean_up_driver_struct(p, driver, level);
7870         if (!W_ERROR_IS_OK(err))
7871                 goto done;
7872
7873         DEBUG(5,("Moving driver to final destination\n"));
7874         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7875                                                               &err)) ) {
7876                 goto done;
7877         }
7878
7879         if (add_a_printer_driver(driver, level)!=0) {
7880                 err = WERR_ACCESS_DENIED;
7881                 goto done;
7882         }
7883
7884         switch(level) {
7885         case 3:
7886                 fstrcpy(driver_name,
7887                         driver.info_3->name ? driver.info_3->name : "");
7888                 break;
7889         case 6:
7890                 fstrcpy(driver_name,
7891                         driver.info_6->name ?  driver.info_6->name : "");
7892                 break;
7893         }
7894
7895         /*
7896          * I think this is where he DrvUpgradePrinter() hook would be
7897          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7898          * server.  Right now, we just need to send ourselves a message
7899          * to update each printer bound to this driver.   --jerry
7900          */
7901
7902         if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7903                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7904                         fn, driver_name));
7905         }
7906
7907         /*
7908          * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7909          * decide if the driver init data should be deleted. The rules are:
7910          *  1) never delete init data if it is a 9x driver, they don't use it anyway
7911          *  2) delete init data only if there is no 2k/Xp driver
7912          *  3) always delete init data
7913          * The generalized rule is always use init data from the highest order driver.
7914          * It is necessary to follow the driver install by an initialization step to
7915          * finish off this process.
7916         */
7917         if (level == 3)
7918                 version = driver.info_3->cversion;
7919         else if (level == 6)
7920                 version = driver.info_6->version;
7921         else
7922                 version = -1;
7923         switch (version) {
7924                 /*
7925                  * 9x printer driver - never delete init data
7926                 */
7927                 case 0:
7928                         DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7929                                 fn, driver_name));
7930                         break;
7931
7932                 /*
7933                  * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7934                  * there is no 2k/Xp driver init data for this driver name.
7935                 */
7936                 case 2:
7937                 {
7938                         NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7939
7940                         if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7941                                 /*
7942                                  * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7943                                 */
7944                                 if (!del_driver_init(driver_name))
7945                                         DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7946                                                 fn, driver_name));
7947                         } else {
7948                                 /*
7949                                  * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7950                                 */
7951                                 free_a_printer_driver(driver1,3);
7952                                 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7953                                         fn, driver_name));
7954                         }
7955                 }
7956                 break;
7957
7958                 /*
7959                  * 2k or Xp printer driver - always delete init data
7960                 */
7961                 case 3:
7962                         if (!del_driver_init(driver_name))
7963                                 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7964                                         fn, driver_name));
7965                         break;
7966
7967                 default:
7968                         DEBUG(0,("%s: invalid level=%d\n", fn, level));
7969                         break;
7970         }
7971
7972
7973 done:
7974         free_a_printer_driver(driver, level);
7975         return err;
7976 }
7977
7978 /****************************************************************
7979  _spoolss_AddPrinterDriverEx
7980 ****************************************************************/
7981
7982 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7983                                    struct spoolss_AddPrinterDriverEx *r)
7984 {
7985         struct spoolss_AddPrinterDriver a;
7986
7987         /*
7988          * we only support the semantics of AddPrinterDriver()
7989          * i.e. only copy files that are newer than existing ones
7990          */
7991
7992         if (r->in.flags != APD_COPY_NEW_FILES) {
7993                 return WERR_ACCESS_DENIED;
7994         }
7995
7996         a.in.servername         = r->in.servername;
7997         a.in.info_ctr           = r->in.info_ctr;
7998
7999         return _spoolss_AddPrinterDriver(p, &a);
8000 }
8001
8002 /****************************************************************************
8003 ****************************************************************************/
8004
8005 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8006                                           const char *servername,
8007                                           const char *environment,
8008                                           struct spoolss_DriverDirectoryInfo1 *info1,
8009                                           uint32_t offered,
8010                                           uint32_t *needed)
8011 {
8012         char *path = NULL;
8013         const char *pservername = NULL;
8014         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8015         const char *short_archi;
8016
8017         if (environment) {
8018                 long_archi = environment;
8019         }
8020
8021         pservername = canon_servername(servername);
8022
8023         if ( !is_myname_or_ipaddr(pservername))
8024                 return WERR_INVALID_PARAM;
8025
8026         if (!(short_archi = get_short_archi(long_archi)))
8027                 return WERR_INVALID_ENVIRONMENT;
8028
8029         path = talloc_asprintf(mem_ctx,
8030                         "\\\\%s\\print$\\%s", pservername, short_archi);
8031         if (!path) {
8032                 return WERR_NOMEM;
8033         }
8034
8035         DEBUG(4,("printer driver directory: [%s]\n", path));
8036
8037         info1->directory_name = path;
8038
8039         *needed += ndr_size_spoolss_DriverDirectoryInfo1(info1, NULL, 0);
8040
8041         if (*needed > offered) {
8042                 talloc_free(path);
8043                 ZERO_STRUCTP(info1);
8044                 return WERR_INSUFFICIENT_BUFFER;
8045         }
8046
8047         return WERR_OK;
8048 }
8049
8050 /****************************************************************
8051  _spoolss_GetPrinterDriverDirectory
8052 ****************************************************************/
8053
8054 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
8055                                           struct spoolss_GetPrinterDriverDirectory *r)
8056 {
8057         WERROR werror;
8058
8059         /* that's an [in out] buffer */
8060
8061         if (!r->in.buffer && (r->in.offered != 0)) {
8062                 return WERR_INVALID_PARAM;
8063         }
8064
8065         if (r->in.offered > MAX_RPC_DATA_SIZE) {
8066                 return WERR_INVALID_PARAM;
8067         }
8068
8069         DEBUG(4,("_spoolss_GetPrinterDriverDirectory\n"));
8070
8071         *r->out.needed = 0;
8072
8073         switch (r->in.level) {
8074         case 1:
8075                 werror = getprinterdriverdir_level_1(p->mem_ctx,
8076                                                      r->in.server,
8077                                                      r->in.environment,
8078                                                      &r->out.info->info1,
8079                                                      r->in.offered,
8080                                                      r->out.needed);
8081                 if (!W_ERROR_IS_OK(werror)) {
8082                         TALLOC_FREE(r->out.info);
8083                 }
8084                 break;
8085         default:
8086                 return WERR_UNKNOWN_LEVEL;
8087         }
8088
8089         return werror;
8090 }
8091
8092 /****************************************************************************
8093 ****************************************************************************/
8094
8095 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8096 {
8097         POLICY_HND *handle = &q_u->handle;
8098         uint32 idx               = q_u->index;
8099         uint32 in_value_len      = q_u->valuesize;
8100         uint32 in_data_len       = q_u->datasize;
8101         uint32 *out_max_value_len = &r_u->valuesize;
8102         uint16 **out_value       = &r_u->value;
8103         uint32 *out_value_len    = &r_u->realvaluesize;
8104         uint32 *out_type         = &r_u->type;
8105         uint32 *out_max_data_len = &r_u->datasize;
8106         uint8  **data_out        = &r_u->data;
8107         uint32 *out_data_len     = &r_u->realdatasize;
8108
8109         NT_PRINTER_INFO_LEVEL *printer = NULL;
8110
8111         uint32          biggest_valuesize;
8112         uint32          biggest_datasize;
8113         uint32          data_len;
8114         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
8115         int             snum;
8116         WERROR          result;
8117         REGISTRY_VALUE  *val = NULL;
8118         NT_PRINTER_DATA *p_data;
8119         int             i, key_index, num_values;
8120         int             name_length;
8121
8122         *out_type = 0;
8123
8124         *out_max_data_len = 0;
8125         *data_out         = NULL;
8126         *out_data_len     = 0;
8127
8128         DEBUG(5,("spoolss_enumprinterdata\n"));
8129
8130         if (!Printer) {
8131                 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8132                 return WERR_BADFID;
8133         }
8134
8135         if (!get_printer_snum(p,handle, &snum, NULL))
8136                 return WERR_BADFID;
8137
8138         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8139         if (!W_ERROR_IS_OK(result))
8140                 return result;
8141
8142         p_data = printer->info_2->data;
8143         key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8144
8145         result = WERR_OK;
8146
8147         /*
8148          * The NT machine wants to know the biggest size of value and data
8149          *
8150          * cf: MSDN EnumPrinterData remark section
8151          */
8152
8153         if ( !in_value_len && !in_data_len && (key_index != -1) )
8154         {
8155                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8156
8157                 biggest_valuesize = 0;
8158                 biggest_datasize  = 0;
8159
8160                 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8161
8162                 for ( i=0; i<num_values; i++ )
8163                 {
8164                         val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8165
8166                         name_length = strlen(val->valuename);
8167                         if ( strlen(val->valuename) > biggest_valuesize )
8168                                 biggest_valuesize = name_length;
8169
8170                         if ( val->size > biggest_datasize )
8171                                 biggest_datasize = val->size;
8172
8173                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8174                                 biggest_datasize));
8175                 }
8176
8177                 /* the value is an UNICODE string but real_value_size is the length
8178                    in bytes including the trailing 0 */
8179
8180                 *out_value_len = 2 * (1+biggest_valuesize);
8181                 *out_data_len  = biggest_datasize;
8182
8183                 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8184
8185                 goto done;
8186         }
8187
8188         /*
8189          * the value len is wrong in NT sp3
8190          * that's the number of bytes not the number of unicode chars
8191          */
8192
8193         if ( key_index != -1 )
8194                 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8195
8196         if ( !val )
8197         {
8198
8199                 /* out_value should default to "" or else NT4 has
8200                    problems unmarshalling the response */
8201
8202                 *out_max_value_len=(in_value_len/sizeof(uint16));
8203
8204                 if (in_value_len) {
8205                         if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8206                         {
8207                                 result = WERR_NOMEM;
8208                                 goto done;
8209                         }
8210                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8211                 } else {
8212                         *out_value=NULL;
8213                         *out_value_len = 0;
8214                 }
8215
8216                 /* the data is counted in bytes */
8217
8218                 *out_max_data_len = in_data_len;
8219                 *out_data_len     = in_data_len;
8220
8221                 /* only allocate when given a non-zero data_len */
8222
8223                 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8224                 {
8225                         result = WERR_NOMEM;
8226                         goto done;
8227                 }
8228
8229                 result = WERR_NO_MORE_ITEMS;
8230         }
8231         else
8232         {
8233                 /*
8234                  * the value is:
8235                  * - counted in bytes in the request
8236                  * - counted in UNICODE chars in the max reply
8237                  * - counted in bytes in the real size
8238                  *
8239                  * take a pause *before* coding not *during* coding
8240                  */
8241
8242                 /* name */
8243                 *out_max_value_len=(in_value_len/sizeof(uint16));
8244                 if (in_value_len) {
8245                         if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8246                         {
8247                                 result = WERR_NOMEM;
8248                                 goto done;
8249                         }
8250
8251                         *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8252                 } else {
8253                         *out_value = NULL;
8254                         *out_value_len = 0;
8255                 }
8256
8257                 /* type */
8258
8259                 *out_type = regval_type( val );
8260
8261                 /* data - counted in bytes */
8262
8263                 *out_max_data_len = in_data_len;
8264                 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8265                 {
8266                         result = WERR_NOMEM;
8267                         goto done;
8268                 }
8269                 data_len = regval_size(val);
8270                 if ( *data_out && data_len )
8271                         memcpy( *data_out, regval_data_p(val), data_len );
8272                 *out_data_len = data_len;
8273         }
8274
8275 done:
8276         free_a_printer(&printer, 2);
8277         return result;
8278 }
8279
8280 /****************************************************************************
8281 ****************************************************************************/
8282
8283 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8284 {
8285         POLICY_HND              *handle = &q_u->handle;
8286         UNISTR2                 *value = &q_u->value;
8287         uint32                  type = q_u->type;
8288         uint8                   *data = q_u->data;
8289         uint32                  real_len = q_u->real_len;
8290
8291         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8292         int                     snum=0;
8293         WERROR                  status = WERR_OK;
8294         Printer_entry           *Printer=find_printer_index_by_hnd(p, handle);
8295         fstring                 valuename;
8296
8297         DEBUG(5,("spoolss_setprinterdata\n"));
8298
8299         if (!Printer) {
8300                 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8301                 return WERR_BADFID;
8302         }
8303
8304         if ( Printer->printer_type == SPLHND_SERVER ) {
8305                 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8306                 return WERR_INVALID_PARAM;
8307         }
8308
8309         if (!get_printer_snum(p,handle, &snum, NULL))
8310                 return WERR_BADFID;
8311
8312         /*
8313          * Access check : NT returns "access denied" if you make a
8314          * SetPrinterData call without the necessary privildge.
8315          * we were originally returning OK if nothing changed
8316          * which made Win2k issue **a lot** of SetPrinterData
8317          * when connecting to a printer  --jerry
8318          */
8319
8320         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8321         {
8322                 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8323                 status = WERR_ACCESS_DENIED;
8324                 goto done;
8325         }
8326
8327         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8328         if (!W_ERROR_IS_OK(status))
8329                 return status;
8330
8331         unistr2_to_ascii(valuename, value, sizeof(valuename));
8332
8333         /*
8334          * When client side code sets a magic printer data key, detect it and save
8335          * the current printer data and the magic key's data (its the DEVMODE) for
8336          * future printer/driver initializations.
8337          */
8338         if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8339         {
8340                 /* Set devmode and printer initialization info */
8341                 status = save_driver_init( printer, 2, data, real_len );
8342
8343                 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8344         }
8345         else
8346         {
8347         status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8348                                         type, data, real_len );
8349                 if ( W_ERROR_IS_OK(status) )
8350                         status = mod_a_printer(printer, 2);
8351         }
8352
8353 done:
8354         free_a_printer(&printer, 2);
8355
8356         return status;
8357 }
8358
8359 /****************************************************************
8360  _spoolss_ResetPrinter
8361 ****************************************************************/
8362
8363 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8364                              struct spoolss_ResetPrinter *r)
8365 {
8366         POLICY_HND      *handle = r->in.handle;
8367         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8368         int             snum;
8369
8370         DEBUG(5,("_spoolss_ResetPrinter\n"));
8371
8372         /*
8373          * All we do is to check to see if the handle and queue is valid.
8374          * This call really doesn't mean anything to us because we only
8375          * support RAW printing.   --jerry
8376          */
8377
8378         if (!Printer) {
8379                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8380                         OUR_HANDLE(handle)));
8381                 return WERR_BADFID;
8382         }
8383
8384         if (!get_printer_snum(p,handle, &snum, NULL))
8385                 return WERR_BADFID;
8386
8387
8388         /* blindly return success */
8389         return WERR_OK;
8390 }
8391
8392 /****************************************************************
8393  _spoolss_DeletePrinterData
8394 ****************************************************************/
8395
8396 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8397                                   struct spoolss_DeletePrinterData *r)
8398 {
8399         POLICY_HND      *handle = r->in.handle;
8400         NT_PRINTER_INFO_LEVEL   *printer = NULL;
8401         int             snum=0;
8402         WERROR          status = WERR_OK;
8403         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
8404
8405         DEBUG(5,("_spoolss_DeletePrinterData\n"));
8406
8407         if (!Printer) {
8408                 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8409                         OUR_HANDLE(handle)));
8410                 return WERR_BADFID;
8411         }
8412
8413         if (!get_printer_snum(p, handle, &snum, NULL))
8414                 return WERR_BADFID;
8415
8416         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8417                 DEBUG(3, ("_spoolss_DeletePrinterData: "
8418                         "printer properties change denied by handle\n"));
8419                 return WERR_ACCESS_DENIED;
8420         }
8421
8422         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8423         if (!W_ERROR_IS_OK(status))
8424                 return status;
8425
8426         if (!r->in.value_name) {
8427                 free_a_printer(&printer, 2);
8428                 return WERR_NOMEM;
8429         }
8430
8431         status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8432                                         r->in.value_name );
8433
8434         if ( W_ERROR_IS_OK(status) )
8435                 mod_a_printer( printer, 2 );
8436
8437         free_a_printer(&printer, 2);
8438
8439         return status;
8440 }
8441
8442 /****************************************************************
8443  _spoolss_AddForm
8444 ****************************************************************/
8445
8446 WERROR _spoolss_AddForm(pipes_struct *p,
8447                         struct spoolss_AddForm *r)
8448 {
8449         POLICY_HND *handle = r->in.handle;
8450         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8451         nt_forms_struct tmpForm;
8452         int snum;
8453         WERROR status = WERR_OK;
8454         NT_PRINTER_INFO_LEVEL *printer = NULL;
8455
8456         int count=0;
8457         nt_forms_struct *list=NULL;
8458         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8459
8460         DEBUG(5,("_spoolss_AddForm\n"));
8461
8462         if (!Printer) {
8463                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8464                         OUR_HANDLE(handle)));
8465                 return WERR_BADFID;
8466         }
8467
8468
8469         /* forms can be added on printer of on the print server handle */
8470
8471         if ( Printer->printer_type == SPLHND_PRINTER )
8472         {
8473                 if (!get_printer_snum(p,handle, &snum, NULL))
8474                         return WERR_BADFID;
8475
8476                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8477                 if (!W_ERROR_IS_OK(status))
8478                         goto done;
8479         }
8480
8481         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8482                 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8483                 status = WERR_ACCESS_DENIED;
8484                 goto done;
8485         }
8486
8487         /* can't add if builtin */
8488
8489         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8490                 status = WERR_FILE_EXISTS;
8491                 goto done;
8492         }
8493
8494         count = get_ntforms(&list);
8495
8496         if(!add_a_form(&list, form, &count)) {
8497                 status =  WERR_NOMEM;
8498                 goto done;
8499         }
8500
8501         write_ntforms(&list, count);
8502
8503         /*
8504          * ChangeID must always be set if this is a printer
8505          */
8506
8507         if ( Printer->printer_type == SPLHND_PRINTER )
8508                 status = mod_a_printer(printer, 2);
8509
8510 done:
8511         if ( printer )
8512                 free_a_printer(&printer, 2);
8513         SAFE_FREE(list);
8514
8515         return status;
8516 }
8517
8518 /****************************************************************
8519  _spoolss_DeleteForm
8520 ****************************************************************/
8521
8522 WERROR _spoolss_DeleteForm(pipes_struct *p,
8523                            struct spoolss_DeleteForm *r)
8524 {
8525         POLICY_HND *handle = r->in.handle;
8526         const char *form_name = r->in.form_name;
8527         nt_forms_struct tmpForm;
8528         int count=0;
8529         nt_forms_struct *list=NULL;
8530         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8531         int snum;
8532         WERROR status = WERR_OK;
8533         NT_PRINTER_INFO_LEVEL *printer = NULL;
8534
8535         DEBUG(5,("_spoolss_DeleteForm\n"));
8536
8537         if (!Printer) {
8538                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8539                         OUR_HANDLE(handle)));
8540                 return WERR_BADFID;
8541         }
8542
8543         /* forms can be deleted on printer of on the print server handle */
8544
8545         if ( Printer->printer_type == SPLHND_PRINTER )
8546         {
8547                 if (!get_printer_snum(p,handle, &snum, NULL))
8548                         return WERR_BADFID;
8549
8550                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8551                 if (!W_ERROR_IS_OK(status))
8552                         goto done;
8553         }
8554
8555         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8556                 DEBUG(2,("_spoolss_DeleteForm: denied by handle permissions.\n"));
8557                 status = WERR_ACCESS_DENIED;
8558                 goto done;
8559         }
8560
8561         /* can't delete if builtin */
8562
8563         if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8564                 status = WERR_INVALID_PARAM;
8565                 goto done;
8566         }
8567
8568         count = get_ntforms(&list);
8569
8570         if ( !delete_a_form(&list, form_name, &count, &status ))
8571                 goto done;
8572
8573         /*
8574          * ChangeID must always be set if this is a printer
8575          */
8576
8577         if ( Printer->printer_type == SPLHND_PRINTER )
8578                 status = mod_a_printer(printer, 2);
8579
8580 done:
8581         if ( printer )
8582                 free_a_printer(&printer, 2);
8583         SAFE_FREE(list);
8584
8585         return status;
8586 }
8587
8588 /****************************************************************
8589  _spoolss_SetForm
8590 ****************************************************************/
8591
8592 WERROR _spoolss_SetForm(pipes_struct *p,
8593                         struct spoolss_SetForm *r)
8594 {
8595         POLICY_HND *handle = r->in.handle;
8596         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8597         nt_forms_struct tmpForm;
8598         int snum;
8599         WERROR status = WERR_OK;
8600         NT_PRINTER_INFO_LEVEL *printer = NULL;
8601
8602         int count=0;
8603         nt_forms_struct *list=NULL;
8604         Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8605
8606         DEBUG(5,("_spoolss_SetForm\n"));
8607
8608         if (!Printer) {
8609                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8610                         OUR_HANDLE(handle)));
8611                 return WERR_BADFID;
8612         }
8613
8614         /* forms can be modified on printer of on the print server handle */
8615
8616         if ( Printer->printer_type == SPLHND_PRINTER )
8617         {
8618                 if (!get_printer_snum(p,handle, &snum, NULL))
8619                         return WERR_BADFID;
8620
8621                 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8622                 if (!W_ERROR_IS_OK(status))
8623                         goto done;
8624         }
8625
8626         if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8627                 DEBUG(2,("_spoolss_SetForm: denied by handle permissions\n"));
8628                 status = WERR_ACCESS_DENIED;
8629                 goto done;
8630         }
8631
8632         /* can't set if builtin */
8633         if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8634                 status = WERR_INVALID_PARAM;
8635                 goto done;
8636         }
8637
8638         count = get_ntforms(&list);
8639         update_a_form(&list, form, count);
8640         write_ntforms(&list, count);
8641
8642         /*
8643          * ChangeID must always be set if this is a printer
8644          */
8645
8646         if ( Printer->printer_type == SPLHND_PRINTER )
8647                 status = mod_a_printer(printer, 2);
8648
8649
8650 done:
8651         if ( printer )
8652                 free_a_printer(&printer, 2);
8653         SAFE_FREE(list);
8654
8655         return status;
8656 }
8657
8658 /****************************************************************************
8659  enumprintprocessors level 1.
8660 ****************************************************************************/
8661
8662 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8663 {
8664         PRINTPROCESSOR_1 *info_1=NULL;
8665         WERROR result = WERR_OK;
8666
8667         if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8668                 return WERR_NOMEM;
8669
8670         (*returned) = 0x1;
8671
8672         init_unistr(&info_1->name, "winprint");
8673
8674         *needed += spoolss_size_printprocessor_info_1(info_1);
8675
8676         if (*needed > offered) {
8677                 result = WERR_INSUFFICIENT_BUFFER;
8678                 goto out;
8679         }
8680
8681         if (!rpcbuf_alloc_size(buffer, *needed)) {
8682                 result = WERR_NOMEM;
8683                 goto out;
8684         }
8685
8686         smb_io_printprocessor_info_1("", buffer, info_1, 0);
8687
8688 out:
8689         SAFE_FREE(info_1);
8690
8691         if ( !W_ERROR_IS_OK(result) )
8692                 *returned = 0;
8693
8694         return result;
8695 }
8696
8697 /****************************************************************************
8698 ****************************************************************************/
8699
8700 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8701 {
8702         uint32 level = q_u->level;
8703         RPC_BUFFER *buffer = NULL;
8704         uint32 offered = q_u->offered;
8705         uint32 *needed = &r_u->needed;
8706         uint32 *returned = &r_u->returned;
8707
8708         /* that's an [in out] buffer */
8709
8710         if (!q_u->buffer && (offered!=0)) {
8711                 return WERR_INVALID_PARAM;
8712         }
8713
8714         if (offered > MAX_RPC_DATA_SIZE) {
8715                 return WERR_INVALID_PARAM;
8716         }
8717
8718         rpcbuf_move(q_u->buffer, &r_u->buffer);
8719         buffer = r_u->buffer;
8720
8721         DEBUG(5,("spoolss_enumprintprocessors\n"));
8722
8723         /*
8724          * Enumerate the print processors ...
8725          *
8726          * Just reply with "winprint", to keep NT happy
8727          * and I can use my nice printer checker.
8728          */
8729
8730         *returned=0;
8731         *needed=0;
8732
8733         switch (level) {
8734         case 1:
8735                 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8736         default:
8737                 return WERR_UNKNOWN_LEVEL;
8738         }
8739 }
8740
8741 /****************************************************************************
8742  enumprintprocdatatypes level 1.
8743 ****************************************************************************/
8744
8745 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8746 {
8747         PRINTPROCDATATYPE_1 *info_1=NULL;
8748         WERROR result = WERR_OK;
8749
8750         if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8751                 return WERR_NOMEM;
8752
8753         (*returned) = 0x1;
8754
8755         init_unistr(&info_1->name, "RAW");
8756
8757         *needed += spoolss_size_printprocdatatype_info_1(info_1);
8758
8759         if (*needed > offered) {
8760                 result = WERR_INSUFFICIENT_BUFFER;
8761                 goto out;
8762         }
8763
8764         if (!rpcbuf_alloc_size(buffer, *needed)) {
8765                 result = WERR_NOMEM;
8766                 goto out;
8767         }
8768
8769         smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8770
8771 out:
8772         SAFE_FREE(info_1);
8773
8774         if ( !W_ERROR_IS_OK(result) )
8775                 *returned = 0;
8776
8777         return result;
8778 }
8779
8780 /****************************************************************************
8781 ****************************************************************************/
8782
8783 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8784 {
8785         uint32 level = q_u->level;
8786         RPC_BUFFER *buffer = NULL;
8787         uint32 offered = q_u->offered;
8788         uint32 *needed = &r_u->needed;
8789         uint32 *returned = &r_u->returned;
8790
8791         /* that's an [in out] buffer */
8792
8793         if (!q_u->buffer && (offered!=0)) {
8794                 return WERR_INVALID_PARAM;
8795         }
8796
8797         if (offered > MAX_RPC_DATA_SIZE) {
8798                 return WERR_INVALID_PARAM;
8799         }
8800
8801         rpcbuf_move(q_u->buffer, &r_u->buffer);
8802         buffer = r_u->buffer;
8803
8804         DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8805
8806         *returned=0;
8807         *needed=0;
8808
8809         switch (level) {
8810         case 1:
8811                 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8812         default:
8813                 return WERR_UNKNOWN_LEVEL;
8814         }
8815 }
8816
8817 /****************************************************************************
8818  enumprintmonitors level 1.
8819 ****************************************************************************/
8820
8821 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8822 {
8823         PRINTMONITOR_1 *info_1;
8824         WERROR result = WERR_OK;
8825         int i;
8826
8827         if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8828                 return WERR_NOMEM;
8829
8830         *returned = 2;
8831
8832         init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8833         init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8834
8835         for ( i=0; i<*returned; i++ ) {
8836                 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8837         }
8838
8839         if (*needed > offered) {
8840                 result = WERR_INSUFFICIENT_BUFFER;
8841                 goto out;
8842         }
8843
8844         if (!rpcbuf_alloc_size(buffer, *needed)) {
8845                 result = WERR_NOMEM;
8846                 goto out;
8847         }
8848
8849         for ( i=0; i<*returned; i++ ) {
8850                 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8851         }
8852
8853 out:
8854         SAFE_FREE(info_1);
8855
8856         if ( !W_ERROR_IS_OK(result) )
8857                 *returned = 0;
8858
8859         return result;
8860 }
8861
8862 /****************************************************************************
8863  enumprintmonitors level 2.
8864 ****************************************************************************/
8865
8866 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8867 {
8868         PRINTMONITOR_2 *info_2;
8869         WERROR result = WERR_OK;
8870         int i;
8871
8872         if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8873                 return WERR_NOMEM;
8874
8875         *returned = 2;
8876
8877         init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8878         init_unistr( &(info_2[0].environment), "Windows NT X86" );
8879         init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8880
8881         init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8882         init_unistr( &(info_2[1].environment), "Windows NT X86" );
8883         init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8884
8885         for ( i=0; i<*returned; i++ ) {
8886                 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8887         }
8888
8889         if (*needed > offered) {
8890                 result = WERR_INSUFFICIENT_BUFFER;
8891                 goto out;
8892         }
8893
8894         if (!rpcbuf_alloc_size(buffer, *needed)) {
8895                 result = WERR_NOMEM;
8896                 goto out;
8897         }
8898
8899         for ( i=0; i<*returned; i++ ) {
8900                 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8901         }
8902
8903 out:
8904         SAFE_FREE(info_2);
8905
8906         if ( !W_ERROR_IS_OK(result) )
8907                 *returned = 0;
8908
8909         return result;
8910 }
8911
8912 /****************************************************************************
8913 ****************************************************************************/
8914
8915 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8916 {
8917         uint32 level = q_u->level;
8918         RPC_BUFFER *buffer = NULL;
8919         uint32 offered = q_u->offered;
8920         uint32 *needed = &r_u->needed;
8921         uint32 *returned = &r_u->returned;
8922
8923         /* that's an [in out] buffer */
8924
8925         if (!q_u->buffer && (offered!=0)) {
8926                 return WERR_INVALID_PARAM;
8927         }
8928
8929         if (offered > MAX_RPC_DATA_SIZE) {
8930                 return WERR_INVALID_PARAM;
8931         }
8932
8933         rpcbuf_move(q_u->buffer, &r_u->buffer);
8934         buffer = r_u->buffer;
8935
8936         DEBUG(5,("spoolss_enumprintmonitors\n"));
8937
8938         /*
8939          * Enumerate the print monitors ...
8940          *
8941          * Just reply with "Local Port", to keep NT happy
8942          * and I can use my nice printer checker.
8943          */
8944
8945         *returned=0;
8946         *needed=0;
8947
8948         switch (level) {
8949         case 1:
8950                 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8951         case 2:
8952                 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8953         default:
8954                 return WERR_UNKNOWN_LEVEL;
8955         }
8956 }
8957
8958 /****************************************************************************
8959 ****************************************************************************/
8960
8961 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8962                              NT_PRINTER_INFO_LEVEL *ntprinter,
8963                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8964                              uint32 *needed)
8965 {
8966         int i=0;
8967         bool found=False;
8968         JOB_INFO_1 *info_1=NULL;
8969         WERROR result = WERR_OK;
8970
8971         info_1=SMB_MALLOC_P(JOB_INFO_1);
8972
8973         if (info_1 == NULL) {
8974                 return WERR_NOMEM;
8975         }
8976
8977         for (i=0; i<count && found==False; i++) {
8978                 if ((*queue)[i].job==(int)jobid)
8979                         found=True;
8980         }
8981
8982         if (found==False) {
8983                 SAFE_FREE(info_1);
8984                 /* NT treats not found as bad param... yet another bad choice */
8985                 return WERR_INVALID_PARAM;
8986         }
8987
8988         fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8989
8990         *needed += spoolss_size_job_info_1(info_1);
8991
8992         if (*needed > offered) {
8993                 result = WERR_INSUFFICIENT_BUFFER;
8994                 goto out;
8995         }
8996
8997         if (!rpcbuf_alloc_size(buffer, *needed)) {
8998                 result = WERR_NOMEM;
8999                 goto out;
9000         }
9001
9002         smb_io_job_info_1("", buffer, info_1, 0);
9003
9004 out:
9005         SAFE_FREE(info_1);
9006
9007         return result;
9008 }
9009
9010 /****************************************************************************
9011 ****************************************************************************/
9012
9013 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
9014                              NT_PRINTER_INFO_LEVEL *ntprinter,
9015                              uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
9016                              uint32 *needed)
9017 {
9018         int             i = 0;
9019         bool            found = False;
9020         JOB_INFO_2      *info_2;
9021         WERROR          result;
9022         DEVICEMODE      *devmode = NULL;
9023         NT_DEVICEMODE   *nt_devmode = NULL;
9024
9025         if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
9026                 return WERR_NOMEM;
9027
9028         ZERO_STRUCTP(info_2);
9029
9030         for ( i=0; i<count && found==False; i++ )
9031         {
9032                 if ((*queue)[i].job == (int)jobid)
9033                         found = True;
9034         }
9035
9036         if ( !found ) {
9037                 /* NT treats not found as bad param... yet another bad
9038                    choice */
9039                 result = WERR_INVALID_PARAM;
9040                 goto done;
9041         }
9042
9043         /*
9044          * if the print job does not have a DEVMODE associated with it,
9045          * just use the one for the printer. A NULL devicemode is not
9046          *  a failure condition
9047          */
9048
9049         if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9050                 devmode = construct_dev_mode(lp_const_servicename(snum));
9051         else {
9052                 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9053                         ZERO_STRUCTP( devmode );
9054                         convert_nt_devicemode( devmode, nt_devmode );
9055                 }
9056         }
9057
9058         fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9059
9060         *needed += spoolss_size_job_info_2(info_2);
9061
9062         if (*needed > offered) {
9063                 result = WERR_INSUFFICIENT_BUFFER;
9064                 goto done;
9065         }
9066
9067         if (!rpcbuf_alloc_size(buffer, *needed)) {
9068                 result = WERR_NOMEM;
9069                 goto done;
9070         }
9071
9072         smb_io_job_info_2("", buffer, info_2, 0);
9073
9074         result = WERR_OK;
9075
9076  done:
9077         /* Cleanup allocated memory */
9078
9079         free_job_info_2(info_2);        /* Also frees devmode */
9080         SAFE_FREE(info_2);
9081
9082         return result;
9083 }
9084
9085 /****************************************************************************
9086 ****************************************************************************/
9087
9088 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9089 {
9090         POLICY_HND *handle = &q_u->handle;
9091         uint32 jobid = q_u->jobid;
9092         uint32 level = q_u->level;
9093         RPC_BUFFER *buffer = NULL;
9094         uint32 offered = q_u->offered;
9095         uint32 *needed = &r_u->needed;
9096         WERROR          wstatus = WERR_OK;
9097         NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9098         int snum;
9099         int count;
9100         print_queue_struct      *queue = NULL;
9101         print_status_struct prt_status;
9102
9103         /* that's an [in out] buffer */
9104
9105         if (!q_u->buffer && (offered!=0)) {
9106                 return WERR_INVALID_PARAM;
9107         }
9108
9109         if (offered > MAX_RPC_DATA_SIZE) {
9110                 return WERR_INVALID_PARAM;
9111         }
9112
9113         rpcbuf_move(q_u->buffer, &r_u->buffer);
9114         buffer = r_u->buffer;
9115
9116         DEBUG(5,("spoolss_getjob\n"));
9117
9118         *needed = 0;
9119
9120         if (!get_printer_snum(p, handle, &snum, NULL))
9121                 return WERR_BADFID;
9122
9123         wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9124         if ( !W_ERROR_IS_OK(wstatus) )
9125                 return wstatus;
9126
9127         count = print_queue_status(snum, &queue, &prt_status);
9128
9129         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9130                      count, prt_status.status, prt_status.message));
9131
9132         switch ( level ) {
9133         case 1:
9134                         wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9135                                 buffer, offered, needed);
9136                         break;
9137         case 2:
9138                         wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9139                                 buffer, offered, needed);
9140                         break;
9141         default:
9142                         wstatus = WERR_UNKNOWN_LEVEL;
9143                         break;
9144         }
9145
9146         SAFE_FREE(queue);
9147         free_a_printer( &ntprinter, 2 );
9148
9149         return wstatus;
9150 }
9151
9152 /****************************************************************
9153  _spoolss_GetPrinterDataEx
9154
9155  From MSDN documentation of GetPrinterDataEx: pass request
9156  to GetPrinterData if key is "PrinterDriverData".
9157 ****************************************************************/
9158
9159 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9160                                  struct spoolss_GetPrinterDataEx *r)
9161 {
9162         POLICY_HND      *handle = r->in.handle;
9163         uint8           *data = NULL;
9164         const char      *keyname = r->in.key_name;
9165         const char      *valuename = r->in.value_name;
9166
9167         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9168
9169         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9170         int                     snum = 0;
9171         WERROR                  status = WERR_OK;
9172
9173         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9174
9175         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9176                 keyname, valuename));
9177
9178         /* in case of problem, return some default values */
9179
9180         *r->out.needed  = 0;
9181         *r->out.type    = 0;
9182
9183         if (!Printer) {
9184                 DEBUG(2,("_spoolss_GetPrinterDataEx: "
9185                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9186                 status = WERR_BADFID;
9187                 goto done;
9188         }
9189
9190         /* Is the handle to a printer or to the server? */
9191
9192         if (Printer->printer_type == SPLHND_SERVER) {
9193                 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9194                         "Not implemented for server handles yet\n"));
9195                 status = WERR_INVALID_PARAM;
9196                 goto done;
9197         }
9198
9199         if ( !get_printer_snum(p,handle, &snum, NULL) )
9200                 return WERR_BADFID;
9201
9202         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9203         if ( !W_ERROR_IS_OK(status) )
9204                 goto done;
9205
9206         /* check to see if the keyname is valid */
9207         if ( !strlen(keyname) ) {
9208                 status = WERR_INVALID_PARAM;
9209                 goto done;
9210         }
9211
9212         if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9213                 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9214                         "Invalid keyname [%s]\n", keyname ));
9215                 free_a_printer( &printer, 2 );
9216                 status = WERR_BADFILE;
9217                 goto done;
9218         }
9219
9220         /* When given a new keyname, we should just create it */
9221
9222         status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
9223                                      r->out.type, &data, r->out.needed,
9224                                      r->in.offered );
9225
9226         if (*r->out.needed > r->in.offered) {
9227                 status = WERR_MORE_DATA;
9228         }
9229
9230         if (W_ERROR_IS_OK(status)) {
9231                 memcpy(r->out.buffer, data, r->in.offered);
9232         }
9233
9234 done:
9235         if ( printer )
9236         free_a_printer( &printer, 2 );
9237
9238         return status;
9239 }
9240
9241 /****************************************************************
9242  _spoolss_SetPrinterDataEx
9243 ****************************************************************/
9244
9245 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9246                                  struct spoolss_SetPrinterDataEx *r)
9247 {
9248         POLICY_HND              *handle = r->in.handle;
9249         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9250         int                     snum = 0;
9251         WERROR                  status = WERR_OK;
9252         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9253         char                    *oid_string;
9254
9255         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9256
9257         /* From MSDN documentation of SetPrinterDataEx: pass request to
9258            SetPrinterData if key is "PrinterDriverData" */
9259
9260         if (!Printer) {
9261                 DEBUG(2,("_spoolss_SetPrinterDataEx: "
9262                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9263                 return WERR_BADFID;
9264         }
9265
9266         if ( Printer->printer_type == SPLHND_SERVER ) {
9267                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9268                         "Not implemented for server handles yet\n"));
9269                 return WERR_INVALID_PARAM;
9270         }
9271
9272         if ( !get_printer_snum(p,handle, &snum, NULL) )
9273                 return WERR_BADFID;
9274
9275         /*
9276          * Access check : NT returns "access denied" if you make a
9277          * SetPrinterData call without the necessary privildge.
9278          * we were originally returning OK if nothing changed
9279          * which made Win2k issue **a lot** of SetPrinterData
9280          * when connecting to a printer  --jerry
9281          */
9282
9283         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9284         {
9285                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9286                         "change denied by handle access permissions\n"));
9287                 return WERR_ACCESS_DENIED;
9288         }
9289
9290         status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9291         if (!W_ERROR_IS_OK(status))
9292                 return status;
9293
9294         /* check for OID in valuename */
9295
9296         if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
9297         {
9298                 *oid_string = '\0';
9299                 oid_string++;
9300         }
9301
9302         /* save the registry data */
9303
9304         status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
9305                                      r->in.type, r->in.buffer, r->in.offered );
9306
9307         if ( W_ERROR_IS_OK(status) )
9308         {
9309                 /* save the OID if one was specified */
9310                 if ( oid_string ) {
9311                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9312                                 r->in.key_name, SPOOL_OID_KEY);
9313                         if (!str) {
9314                                 return WERR_NOMEM;
9315                         }
9316
9317                         /*
9318                          * I'm not checking the status here on purpose.  Don't know
9319                          * if this is right, but I'm returning the status from the
9320                          * previous set_printer_dataex() call.  I have no idea if
9321                          * this is right.    --jerry
9322                          */
9323
9324                         set_printer_dataex( printer, str, r->in.value_name,
9325                                             REG_SZ, (uint8 *)oid_string,
9326                                             strlen(oid_string)+1 );
9327                 }
9328
9329                 status = mod_a_printer(printer, 2);
9330         }
9331
9332         free_a_printer(&printer, 2);
9333
9334         return status;
9335 }
9336
9337 /****************************************************************
9338  _spoolss_DeletePrinterDataEx
9339 ****************************************************************/
9340
9341 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9342                                     struct spoolss_DeletePrinterDataEx *r)
9343 {
9344         POLICY_HND      *handle = r->in.handle;
9345         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9346         int             snum=0;
9347         WERROR          status = WERR_OK;
9348         Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
9349
9350         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9351
9352         if (!Printer) {
9353                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9354                         "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9355                 return WERR_BADFID;
9356         }
9357
9358         if (!get_printer_snum(p, handle, &snum, NULL))
9359                 return WERR_BADFID;
9360
9361         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9362                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9363                         "printer properties change denied by handle\n"));
9364                 return WERR_ACCESS_DENIED;
9365         }
9366
9367         if (!r->in.value_name || !r->in.key_name) {
9368                 return WERR_NOMEM;
9369         }
9370
9371         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9372         if (!W_ERROR_IS_OK(status))
9373                 return status;
9374
9375         status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9376
9377         if ( W_ERROR_IS_OK(status) )
9378                 mod_a_printer( printer, 2 );
9379
9380         free_a_printer(&printer, 2);
9381
9382         return status;
9383 }
9384
9385 /********************************************************************
9386  * spoolss_enumprinterkey
9387  ********************************************************************/
9388
9389
9390 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9391 {
9392         fstring         key;
9393         fstring         *keynames = NULL;
9394         uint16          *enumkeys = NULL;
9395         int             num_keys;
9396         int             printerkey_len;
9397         POLICY_HND      *handle = &q_u->handle;
9398         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9399         NT_PRINTER_DATA *data;
9400         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9401         int             snum = 0;
9402         WERROR          status = WERR_BADFILE;
9403
9404
9405         DEBUG(4,("_spoolss_enumprinterkey\n"));
9406
9407         if (!Printer) {
9408                 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9409                 return WERR_BADFID;
9410         }
9411
9412         if ( !get_printer_snum(p,handle, &snum, NULL) )
9413                 return WERR_BADFID;
9414
9415         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9416         if (!W_ERROR_IS_OK(status))
9417                 return status;
9418
9419         /* get the list of subkey names */
9420
9421         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9422         data = printer->info_2->data;
9423
9424         num_keys = get_printer_subkeys( data, key, &keynames );
9425
9426         if ( num_keys == -1 ) {
9427                 status = WERR_BADFILE;
9428                 goto done;
9429         }
9430
9431         printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
9432
9433         r_u->needed = printerkey_len*2;
9434
9435         if ( q_u->size < r_u->needed ) {
9436                 status = WERR_MORE_DATA;
9437                 goto done;
9438         }
9439
9440         if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9441                 status = WERR_NOMEM;
9442                 goto done;
9443         }
9444
9445         status = WERR_OK;
9446
9447         if ( q_u->size < r_u->needed )
9448                 status = WERR_MORE_DATA;
9449
9450 done:
9451         free_a_printer( &printer, 2 );
9452         SAFE_FREE( keynames );
9453
9454         return status;
9455 }
9456
9457 /****************************************************************
9458  _spoolss_DeletePrinterKey
9459 ****************************************************************/
9460
9461 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9462                                  struct spoolss_DeletePrinterKey *r)
9463 {
9464         POLICY_HND              *handle = r->in.handle;
9465         Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
9466         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9467         int                     snum=0;
9468         WERROR                  status;
9469
9470         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9471
9472         if (!Printer) {
9473                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9474                         OUR_HANDLE(handle)));
9475                 return WERR_BADFID;
9476         }
9477
9478         /* if keyname == NULL, return error */
9479
9480         if ( !r->in.key_name )
9481                 return WERR_INVALID_PARAM;
9482
9483         if (!get_printer_snum(p, handle, &snum, NULL))
9484                 return WERR_BADFID;
9485
9486         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9487                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9488                         "printer properties change denied by handle\n"));
9489                 return WERR_ACCESS_DENIED;
9490         }
9491
9492         status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9493         if (!W_ERROR_IS_OK(status))
9494                 return status;
9495
9496         /* delete the key and all subneys */
9497
9498         status = delete_all_printer_data( printer->info_2, r->in.key_name );
9499
9500         if ( W_ERROR_IS_OK(status) )
9501                 status = mod_a_printer(printer, 2);
9502
9503         free_a_printer( &printer, 2 );
9504
9505         return status;
9506 }
9507
9508
9509 /********************************************************************
9510  * spoolss_enumprinterdataex
9511  ********************************************************************/
9512
9513 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9514 {
9515         POLICY_HND      *handle = &q_u->handle;
9516         uint32          in_size = q_u->size;
9517         uint32          num_entries,
9518                         needed;
9519         NT_PRINTER_INFO_LEVEL   *printer = NULL;
9520         PRINTER_ENUM_VALUES     *enum_values = NULL;
9521         NT_PRINTER_DATA         *p_data;
9522         fstring         key;
9523         Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
9524         int             snum;
9525         WERROR          result;
9526         int             key_index;
9527         int             i;
9528         REGISTRY_VALUE  *val;
9529         char            *value_name;
9530         uint32          data_len;
9531
9532
9533         DEBUG(4,("_spoolss_enumprinterdataex\n"));
9534
9535         if (!Printer) {
9536                 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9537                 return WERR_BADFID;
9538         }
9539
9540         /*
9541          * first check for a keyname of NULL or "".  Win2k seems to send
9542          * this a lot and we should send back WERR_INVALID_PARAM
9543          * no need to spend time looking up the printer in this case.
9544          * --jerry
9545          */
9546
9547         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9548         if ( !strlen(key) ) {
9549                 result = WERR_INVALID_PARAM;
9550                 goto done;
9551         }
9552
9553         /* get the printer off of disk */
9554
9555         if (!get_printer_snum(p,handle, &snum, NULL))
9556                 return WERR_BADFID;
9557
9558         ZERO_STRUCT(printer);
9559         result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9560         if (!W_ERROR_IS_OK(result))
9561                 return result;
9562
9563         /* now look for a match on the key name */
9564
9565         p_data = printer->info_2->data;
9566
9567         unistr2_to_ascii(key, &q_u->key, sizeof(key));
9568         if ( (key_index = lookup_printerkey( p_data, key)) == -1  )
9569         {
9570                 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9571                 result = WERR_INVALID_PARAM;
9572                 goto done;
9573         }
9574
9575         result = WERR_OK;
9576         needed = 0;
9577
9578         /* allocate the memory for the array of pointers -- if necessary */
9579
9580         num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9581         if ( num_entries )
9582         {
9583                 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9584                 {
9585                         DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9586                                 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9587                         result = WERR_NOMEM;
9588                         goto done;
9589                 }
9590
9591                 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9592         }
9593
9594         /*
9595          * loop through all params and build the array to pass
9596          * back to the  client
9597          */
9598
9599         for ( i=0; i<num_entries; i++ )
9600         {
9601                 /* lookup the registry value */
9602
9603                 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9604                 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9605
9606                 /* copy the data */
9607
9608                 value_name = regval_name( val );
9609                 init_unistr( &enum_values[i].valuename, value_name );
9610                 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9611                 enum_values[i].type      = regval_type( val );
9612
9613                 data_len = regval_size( val );
9614                 if ( data_len ) {
9615                         if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9616                         {
9617                                 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9618                                         data_len ));
9619                                 result = WERR_NOMEM;
9620                                 goto done;
9621                         }
9622                 }
9623                 enum_values[i].data_len = data_len;
9624
9625                 /* keep track of the size of the array in bytes */
9626
9627                 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9628         }
9629
9630         /* housekeeping information in the reply */
9631
9632         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9633          * the hand marshalled container size is a multiple
9634          * of 4 bytes for RPC alignment.
9635          */
9636
9637         if (needed % 4) {
9638                 needed += 4-(needed % 4);
9639         }
9640
9641         r_u->needed     = needed;
9642         r_u->returned   = num_entries;
9643
9644         if (needed > in_size) {
9645                 result = WERR_MORE_DATA;
9646                 goto done;
9647         }
9648
9649         /* copy data into the reply */
9650
9651         /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9652            response buffer size is != the offered buffer size
9653
9654                 r_u->ctr.size           = r_u->needed;
9655         */
9656         r_u->ctr.size           = in_size;
9657
9658         r_u->ctr.size_of_array  = r_u->returned;
9659         r_u->ctr.values         = enum_values;
9660
9661 done:
9662         if ( printer )
9663         free_a_printer(&printer, 2);
9664
9665         return result;
9666 }
9667
9668 /****************************************************************************
9669 ****************************************************************************/
9670
9671 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9672                                                  const char *servername,
9673                                                  const char *environment,
9674                                                  struct spoolss_PrintProcessorDirectoryInfo1 *info1,
9675                                                  uint32_t offered,
9676                                                  uint32_t *needed)
9677 {
9678         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
9679         const char *short_archi;
9680
9681         if (environment) {
9682                 long_archi = environment;
9683         }
9684
9685         short_archi = get_short_archi(long_archi);
9686         if (!short_archi) {
9687                 return WERR_INVALID_ENVIRONMENT;
9688         }
9689
9690         /* I think this should look like this - gd
9691         info1->directory_name = talloc_asprintf(mem_ctx,
9692                 "C:\\WINNT\\System32\\spool\\PRTPROCS\\%s", short_archi);
9693         */
9694         info1->directory_name = talloc_strdup(mem_ctx,
9695                 "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9696
9697         if (!info1->directory_name) {
9698                 return WERR_NOMEM;
9699         }
9700
9701         *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(info1, NULL, 0);
9702
9703         if (*needed > offered) {
9704                 return WERR_INSUFFICIENT_BUFFER;
9705         }
9706
9707         return WERR_OK;
9708 }
9709
9710 /****************************************************************
9711  _spoolss_GetPrintProcessorDirectory
9712 ****************************************************************/
9713
9714 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9715                                            struct spoolss_GetPrintProcessorDirectory *r)
9716 {
9717         WERROR result;
9718
9719         /* that's an [in out] buffer */
9720
9721         if (!r->in.buffer && (r->in.offered != 0)) {
9722                 return WERR_INVALID_PARAM;
9723         }
9724
9725         if (r->in.offered > MAX_RPC_DATA_SIZE) {
9726                 return WERR_INVALID_PARAM;
9727         }
9728
9729         DEBUG(5,("_spoolss_GetPrintProcessorDirectory\n"));
9730
9731         *r->out.needed = 0;
9732
9733         switch (r->in.level) {
9734         case 1:
9735                 result = getprintprocessordirectory_level_1(p->mem_ctx,
9736                                                             r->in.server,
9737                                                             r->in.environment,
9738                                                             &r->out.info->info1,
9739                                                             r->in.offered,
9740                                                             r->out.needed);
9741                 if (!W_ERROR_IS_OK(result)) {
9742                         TALLOC_FREE(r->out.info);
9743                 }
9744                 break;
9745         default:
9746                 result = WERR_UNKNOWN_LEVEL;
9747         }
9748
9749         return result;
9750 }
9751
9752 /*******************************************************************
9753  ********************************************************************/
9754
9755 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9756                                const char *dllname)
9757 {
9758         enum ndr_err_code ndr_err;
9759         struct spoolss_MonitorUi ui;
9760
9761         ui.dll_name = dllname;
9762
9763         ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9764                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9765         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9766                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9767         }
9768         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9769 }
9770
9771 /*******************************************************************
9772  Streams the monitor UI DLL name in UNICODE
9773 *******************************************************************/
9774
9775 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9776                                NT_USER_TOKEN *token, DATA_BLOB *in,
9777                                DATA_BLOB *out, uint32_t *needed)
9778 {
9779         const char *dllname = "tcpmonui.dll";
9780
9781         *needed = (strlen(dllname)+1) * 2;
9782
9783         if (out->length < *needed) {
9784                 return WERR_INSUFFICIENT_BUFFER;
9785         }
9786
9787         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9788                 return WERR_NOMEM;
9789         }
9790
9791         return WERR_OK;
9792 }
9793
9794 /*******************************************************************
9795  ********************************************************************/
9796
9797 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9798                              struct spoolss_PortData1 *port1,
9799                              const DATA_BLOB *buf)
9800 {
9801         enum ndr_err_code ndr_err;
9802         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9803                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9804         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9805                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9806         }
9807         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9808 }
9809
9810 /*******************************************************************
9811  ********************************************************************/
9812
9813 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9814                              struct spoolss_PortData2 *port2,
9815                              const DATA_BLOB *buf)
9816 {
9817         enum ndr_err_code ndr_err;
9818         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9819                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9820         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9821                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9822         }
9823         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9824 }
9825
9826 /*******************************************************************
9827  Create a new TCP/IP port
9828 *******************************************************************/
9829
9830 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9831                              NT_USER_TOKEN *token, DATA_BLOB *in,
9832                              DATA_BLOB *out, uint32_t *needed)
9833 {
9834         struct spoolss_PortData1 port1;
9835         struct spoolss_PortData2 port2;
9836         char *device_uri = NULL;
9837         uint32_t version;
9838
9839         const char *portname;
9840         const char *hostaddress;
9841         const char *queue;
9842         uint32_t port_number;
9843         uint32_t protocol;
9844
9845         /* peek for spoolss_PortData version */
9846
9847         if (!in || (in->length < (128 + 4))) {
9848                 return WERR_GENERAL_FAILURE;
9849         }
9850
9851         version = IVAL(in->data, 128);
9852
9853         switch (version) {
9854                 case 1:
9855                         ZERO_STRUCT(port1);
9856
9857                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9858                                 return WERR_NOMEM;
9859                         }
9860
9861                         portname        = port1.portname;
9862                         hostaddress     = port1.hostaddress;
9863                         queue           = port1.queue;
9864                         protocol        = port1.protocol;
9865                         port_number     = port1.port_number;
9866
9867                         break;
9868                 case 2:
9869                         ZERO_STRUCT(port2);
9870
9871                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9872                                 return WERR_NOMEM;
9873                         }
9874
9875                         portname        = port2.portname;
9876                         hostaddress     = port2.hostaddress;
9877                         queue           = port2.queue;
9878                         protocol        = port2.protocol;
9879                         port_number     = port2.port_number;
9880
9881                         break;
9882                 default:
9883                         DEBUG(1,("xcvtcp_addport: "
9884                                 "unknown version of port_data: %d\n", version));
9885                         return WERR_UNKNOWN_PORT;
9886         }
9887
9888         /* create the device URI and call the add_port_hook() */
9889
9890         switch (protocol) {
9891         case PROTOCOL_RAWTCP_TYPE:
9892                 device_uri = talloc_asprintf(mem_ctx,
9893                                 "socket://%s:%d/", hostaddress,
9894                                 port_number);
9895                 break;
9896
9897         case PROTOCOL_LPR_TYPE:
9898                 device_uri = talloc_asprintf(mem_ctx,
9899                         "lpr://%s/%s", hostaddress, queue );
9900                 break;
9901
9902         default:
9903                 return WERR_UNKNOWN_PORT;
9904         }
9905
9906         if (!device_uri) {
9907                 return WERR_NOMEM;
9908         }
9909
9910         return add_port_hook(mem_ctx, token, portname, device_uri);
9911 }
9912
9913 /*******************************************************************
9914 *******************************************************************/
9915
9916 struct xcv_api_table xcvtcp_cmds[] = {
9917         { "MonitorUI",  xcvtcp_monitorui },
9918         { "AddPort",    xcvtcp_addport},
9919         { NULL,         NULL }
9920 };
9921
9922 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9923                                      NT_USER_TOKEN *token, const char *command,
9924                                      DATA_BLOB *inbuf,
9925                                      DATA_BLOB *outbuf,
9926                                      uint32_t *needed )
9927 {
9928         int i;
9929
9930         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9931
9932         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9933                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9934                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9935         }
9936
9937         return WERR_BADFUNC;
9938 }
9939
9940 /*******************************************************************
9941 *******************************************************************/
9942 #if 0   /* don't support management using the "Local Port" monitor */
9943
9944 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9945                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9946                                  DATA_BLOB *out, uint32_t *needed)
9947 {
9948         const char *dllname = "localui.dll";
9949
9950         *needed = (strlen(dllname)+1) * 2;
9951
9952         if (out->length < *needed) {
9953                 return WERR_INSUFFICIENT_BUFFER;
9954         }
9955
9956         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9957                 return WERR_NOMEM;
9958         }
9959
9960         return WERR_OK;
9961 }
9962
9963 /*******************************************************************
9964 *******************************************************************/
9965
9966 struct xcv_api_table xcvlocal_cmds[] = {
9967         { "MonitorUI",  xcvlocal_monitorui },
9968         { NULL,         NULL }
9969 };
9970 #else
9971 struct xcv_api_table xcvlocal_cmds[] = {
9972         { NULL,         NULL }
9973 };
9974 #endif
9975
9976
9977
9978 /*******************************************************************
9979 *******************************************************************/
9980
9981 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9982                                        NT_USER_TOKEN *token, const char *command,
9983                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9984                                        uint32_t *needed)
9985 {
9986         int i;
9987
9988         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9989
9990         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9991                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9992                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9993         }
9994         return WERR_BADFUNC;
9995 }
9996
9997 /****************************************************************
9998  _spoolss_XcvData
9999 ****************************************************************/
10000
10001 WERROR _spoolss_XcvData(pipes_struct *p,
10002                         struct spoolss_XcvData *r)
10003 {
10004         Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
10005         DATA_BLOB out_data;
10006         WERROR werror;
10007
10008         if (!Printer) {
10009                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10010                         OUR_HANDLE(r->in.handle)));
10011                 return WERR_BADFID;
10012         }
10013
10014         /* Has to be a handle to the TCP/IP port monitor */
10015
10016         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10017                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10018                 return WERR_BADFID;
10019         }
10020
10021         /* requires administrative access to the server */
10022
10023         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10024                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10025                 return WERR_ACCESS_DENIED;
10026         }
10027
10028         /* Allocate the outgoing buffer */
10029
10030         if (r->in.out_data_size) {
10031                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10032                 if (out_data.data == NULL) {
10033                         return WERR_NOMEM;
10034                 }
10035         }
10036
10037         switch ( Printer->printer_type ) {
10038         case SPLHND_PORTMON_TCP:
10039                 werror = process_xcvtcp_command(p->mem_ctx,
10040                                                 p->server_info->ptok,
10041                                                 r->in.function_name,
10042                                                 &r->in.in_data, &out_data,
10043                                                 r->out.needed);
10044                 break;
10045         case SPLHND_PORTMON_LOCAL:
10046                 werror = process_xcvlocal_command(p->mem_ctx,
10047                                                   p->server_info->ptok,
10048                                                   r->in.function_name,
10049                                                   &r->in.in_data, &out_data,
10050                                                   r->out.needed);
10051                 break;
10052         default:
10053                 werror = WERR_INVALID_PRINT_MONITOR;
10054         }
10055
10056         if (!W_ERROR_IS_OK(werror)) {
10057                 return werror;
10058         }
10059
10060         *r->out.status_code = 0;
10061
10062         memcpy(r->out.out_data, out_data.data, out_data.length);
10063
10064         return WERR_OK;
10065 }
10066
10067 /****************************************************************
10068  _spoolss_AddPrintProcessor
10069 ****************************************************************/
10070
10071 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10072                                   struct spoolss_AddPrintProcessor *r)
10073 {
10074         /* for now, just indicate success and ignore the add.  We'll
10075            automatically set the winprint processor for printer
10076            entries later.  Used to debug the LexMark Optra S 1855 PCL
10077            driver --jerry */
10078
10079         return WERR_OK;
10080 }
10081
10082 /****************************************************************
10083  _spoolss_EnumPrinters
10084 ****************************************************************/
10085
10086 WERROR _spoolss_EnumPrinters(pipes_struct *p,
10087                              struct spoolss_EnumPrinters *r)
10088 {
10089         p->rng_fault_state = true;
10090         return WERR_NOT_SUPPORTED;
10091 }
10092
10093 /****************************************************************
10094  _spoolss_GetJob
10095 ****************************************************************/
10096
10097 WERROR _spoolss_GetJob(pipes_struct *p,
10098                        struct spoolss_GetJob *r)
10099 {
10100         p->rng_fault_state = true;
10101         return WERR_NOT_SUPPORTED;
10102 }
10103
10104 /****************************************************************
10105  _spoolss_EnumJobs
10106 ****************************************************************/
10107
10108 WERROR _spoolss_EnumJobs(pipes_struct *p,
10109                          struct spoolss_EnumJobs *r)
10110 {
10111         p->rng_fault_state = true;
10112         return WERR_NOT_SUPPORTED;
10113 }
10114
10115 /****************************************************************
10116  _spoolss_AddPrinter
10117 ****************************************************************/
10118
10119 WERROR _spoolss_AddPrinter(pipes_struct *p,
10120                            struct spoolss_AddPrinter *r)
10121 {
10122         p->rng_fault_state = true;
10123         return WERR_NOT_SUPPORTED;
10124 }
10125
10126 /****************************************************************
10127  _spoolss_GetPrinter
10128 ****************************************************************/
10129
10130 WERROR _spoolss_GetPrinter(pipes_struct *p,
10131                            struct spoolss_GetPrinter *r)
10132 {
10133         p->rng_fault_state = true;
10134         return WERR_NOT_SUPPORTED;
10135 }
10136
10137 /****************************************************************
10138  _spoolss_EnumPrinterDrivers
10139 ****************************************************************/
10140
10141 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
10142                                    struct spoolss_EnumPrinterDrivers *r)
10143 {
10144         p->rng_fault_state = true;
10145         return WERR_NOT_SUPPORTED;
10146 }
10147
10148 /****************************************************************
10149  _spoolss_GetPrinterDriver
10150 ****************************************************************/
10151
10152 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10153                                  struct spoolss_GetPrinterDriver *r)
10154 {
10155         p->rng_fault_state = true;
10156         return WERR_NOT_SUPPORTED;
10157 }
10158
10159 /****************************************************************
10160  _spoolss_EnumPrintProcessors
10161 ****************************************************************/
10162
10163 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
10164                                     struct spoolss_EnumPrintProcessors *r)
10165 {
10166         p->rng_fault_state = true;
10167         return WERR_NOT_SUPPORTED;
10168 }
10169
10170 /****************************************************************
10171  _spoolss_ReadPrinter
10172 ****************************************************************/
10173
10174 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10175                             struct spoolss_ReadPrinter *r)
10176 {
10177         p->rng_fault_state = true;
10178         return WERR_NOT_SUPPORTED;
10179 }
10180
10181 /****************************************************************
10182  _spoolss_GetPrinterData
10183 ****************************************************************/
10184
10185 WERROR _spoolss_GetPrinterData(pipes_struct *p,
10186                                struct spoolss_GetPrinterData *r)
10187 {
10188         p->rng_fault_state = true;
10189         return WERR_NOT_SUPPORTED;
10190 }
10191
10192 /****************************************************************
10193  _spoolss_SetPrinterData
10194 ****************************************************************/
10195
10196 WERROR _spoolss_SetPrinterData(pipes_struct *p,
10197                                struct spoolss_SetPrinterData *r)
10198 {
10199         p->rng_fault_state = true;
10200         return WERR_NOT_SUPPORTED;
10201 }
10202
10203 /****************************************************************
10204  _spoolss_WaitForPrinterChange
10205 ****************************************************************/
10206
10207 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10208                                      struct spoolss_WaitForPrinterChange *r)
10209 {
10210         p->rng_fault_state = true;
10211         return WERR_NOT_SUPPORTED;
10212 }
10213
10214 /****************************************************************
10215  _spoolss_EnumForms
10216 ****************************************************************/
10217
10218 WERROR _spoolss_EnumForms(pipes_struct *p,
10219                           struct spoolss_EnumForms *r)
10220 {
10221         p->rng_fault_state = true;
10222         return WERR_NOT_SUPPORTED;
10223 }
10224
10225 /****************************************************************
10226  _spoolss_EnumPorts
10227 ****************************************************************/
10228
10229 WERROR _spoolss_EnumPorts(pipes_struct *p,
10230                           struct spoolss_EnumPorts *r)
10231 {
10232         p->rng_fault_state = true;
10233         return WERR_NOT_SUPPORTED;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_EnumMonitors
10238 ****************************************************************/
10239
10240 WERROR _spoolss_EnumMonitors(pipes_struct *p,
10241                              struct spoolss_EnumMonitors *r)
10242 {
10243         p->rng_fault_state = true;
10244         return WERR_NOT_SUPPORTED;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_AddPort
10249 ****************************************************************/
10250
10251 WERROR _spoolss_AddPort(pipes_struct *p,
10252                         struct spoolss_AddPort *r)
10253 {
10254         p->rng_fault_state = true;
10255         return WERR_NOT_SUPPORTED;
10256 }
10257
10258 /****************************************************************
10259  _spoolss_ConfigurePort
10260 ****************************************************************/
10261
10262 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10263                               struct spoolss_ConfigurePort *r)
10264 {
10265         p->rng_fault_state = true;
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_DeletePort
10271 ****************************************************************/
10272
10273 WERROR _spoolss_DeletePort(pipes_struct *p,
10274                            struct spoolss_DeletePort *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_CreatePrinterIC
10282 ****************************************************************/
10283
10284 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10285                                 struct spoolss_CreatePrinterIC *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_PlayGDIScriptOnPrinterIC
10293 ****************************************************************/
10294
10295 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10296                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_DeletePrinterIC
10304 ****************************************************************/
10305
10306 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10307                                 struct spoolss_DeletePrinterIC *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_AddPrinterConnection
10315 ****************************************************************/
10316
10317 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10318                                      struct spoolss_AddPrinterConnection *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_DeletePrinterConnection
10326 ****************************************************************/
10327
10328 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10329                                         struct spoolss_DeletePrinterConnection *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_PrinterMessageBox
10337 ****************************************************************/
10338
10339 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10340                                   struct spoolss_PrinterMessageBox *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_AddMonitor
10348 ****************************************************************/
10349
10350 WERROR _spoolss_AddMonitor(pipes_struct *p,
10351                            struct spoolss_AddMonitor *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_DeleteMonitor
10359 ****************************************************************/
10360
10361 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10362                               struct spoolss_DeleteMonitor *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_DeletePrintProcessor
10370 ****************************************************************/
10371
10372 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10373                                      struct spoolss_DeletePrintProcessor *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_AddPrintProvidor
10381 ****************************************************************/
10382
10383 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10384                                  struct spoolss_AddPrintProvidor *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_DeletePrintProvidor
10392 ****************************************************************/
10393
10394 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10395                                     struct spoolss_DeletePrintProvidor *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_EnumPrintProcDataTypes
10403 ****************************************************************/
10404
10405 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
10406                                        struct spoolss_EnumPrintProcDataTypes *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_GetPrinterDriver2
10414 ****************************************************************/
10415
10416 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
10417                                   struct spoolss_GetPrinterDriver2 *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_FindFirstPrinterChangeNotification
10425 ****************************************************************/
10426
10427 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10428                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_FindNextPrinterChangeNotification
10436 ****************************************************************/
10437
10438 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10439                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10447 ****************************************************************/
10448
10449 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10450                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_ReplyOpenPrinter
10458 ****************************************************************/
10459
10460 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10461                                  struct spoolss_ReplyOpenPrinter *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_RouterReplyPrinter
10469 ****************************************************************/
10470
10471 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10472                                    struct spoolss_RouterReplyPrinter *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_ReplyClosePrinter
10480 ****************************************************************/
10481
10482 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10483                                   struct spoolss_ReplyClosePrinter *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_AddPortEx
10491 ****************************************************************/
10492
10493 WERROR _spoolss_AddPortEx(pipes_struct *p,
10494                           struct spoolss_AddPortEx *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_RouterFindFirstPrinterChangeNotification
10502 ****************************************************************/
10503
10504 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10505                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_SpoolerInit
10513 ****************************************************************/
10514
10515 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10516                             struct spoolss_SpoolerInit *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_ResetPrinterEx
10524 ****************************************************************/
10525
10526 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10527                                struct spoolss_ResetPrinterEx *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_RemoteFindFirstPrinterChangeNotifyEx
10535 ****************************************************************/
10536
10537 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
10538                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_RouterReplyPrinterEx
10546 ****************************************************************/
10547
10548 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10549                                      struct spoolss_RouterReplyPrinterEx *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
10557 ****************************************************************/
10558
10559 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
10560                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_44
10568 ****************************************************************/
10569
10570 WERROR _spoolss_44(pipes_struct *p,
10571                    struct spoolss_44 *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_47
10579 ****************************************************************/
10580
10581 WERROR _spoolss_47(pipes_struct *p,
10582                    struct spoolss_47 *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_EnumPrinterData
10590 ****************************************************************/
10591
10592 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
10593                                 struct spoolss_EnumPrinterData *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_4a
10601 ****************************************************************/
10602
10603 WERROR _spoolss_4a(pipes_struct *p,
10604                    struct spoolss_4a *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_4b
10612 ****************************************************************/
10613
10614 WERROR _spoolss_4b(pipes_struct *p,
10615                    struct spoolss_4b *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_4c
10623 ****************************************************************/
10624
10625 WERROR _spoolss_4c(pipes_struct *p,
10626                    struct spoolss_4c *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_EnumPrinterDataEx
10634 ****************************************************************/
10635
10636 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
10637                                   struct spoolss_EnumPrinterDataEx *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_EnumPrinterKey
10645 ****************************************************************/
10646
10647 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
10648                                struct spoolss_EnumPrinterKey *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_53
10656 ****************************************************************/
10657
10658 WERROR _spoolss_53(pipes_struct *p,
10659                    struct spoolss_53 *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_55
10667 ****************************************************************/
10668
10669 WERROR _spoolss_55(pipes_struct *p,
10670                    struct spoolss_55 *r)
10671 {
10672         p->rng_fault_state = true;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_56
10678 ****************************************************************/
10679
10680 WERROR _spoolss_56(pipes_struct *p,
10681                    struct spoolss_56 *r)
10682 {
10683         p->rng_fault_state = true;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_57
10689 ****************************************************************/
10690
10691 WERROR _spoolss_57(pipes_struct *p,
10692                    struct spoolss_57 *r)
10693 {
10694         p->rng_fault_state = true;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_5a
10700 ****************************************************************/
10701
10702 WERROR _spoolss_5a(pipes_struct *p,
10703                    struct spoolss_5a *r)
10704 {
10705         p->rng_fault_state = true;
10706         return WERR_NOT_SUPPORTED;
10707 }
10708
10709 /****************************************************************
10710  _spoolss_5b
10711 ****************************************************************/
10712
10713 WERROR _spoolss_5b(pipes_struct *p,
10714                    struct spoolss_5b *r)
10715 {
10716         p->rng_fault_state = true;
10717         return WERR_NOT_SUPPORTED;
10718 }
10719
10720 /****************************************************************
10721  _spoolss_5c
10722 ****************************************************************/
10723
10724 WERROR _spoolss_5c(pipes_struct *p,
10725                    struct spoolss_5c *r)
10726 {
10727         p->rng_fault_state = true;
10728         return WERR_NOT_SUPPORTED;
10729 }
10730
10731 /****************************************************************
10732  _spoolss_5d
10733 ****************************************************************/
10734
10735 WERROR _spoolss_5d(pipes_struct *p,
10736                    struct spoolss_5d *r)
10737 {
10738         p->rng_fault_state = true;
10739         return WERR_NOT_SUPPORTED;
10740 }
10741
10742 /****************************************************************
10743  _spoolss_5e
10744 ****************************************************************/
10745
10746 WERROR _spoolss_5e(pipes_struct *p,
10747                    struct spoolss_5e *r)
10748 {
10749         p->rng_fault_state = true;
10750         return WERR_NOT_SUPPORTED;
10751 }
10752
10753 /****************************************************************
10754  _spoolss_5f
10755 ****************************************************************/
10756
10757 WERROR _spoolss_5f(pipes_struct *p,
10758                    struct spoolss_5f *r)
10759 {
10760         p->rng_fault_state = true;
10761         return WERR_NOT_SUPPORTED;
10762 }
10763